00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00028 #include "avformat.h"
00029 #include "internal.h"
00030 #include "riff.h"
00031 #include <libnut.h>
00032
00033 #define ID_STRING "nut/multimedia container"
00034 #define ID_LENGTH (strlen(ID_STRING) + 1)
00035
00036 typedef struct {
00037 nut_context_tt * nut;
00038 nut_stream_header_tt * s;
00039 } NUTContext;
00040
00041 static const AVCodecTag nut_tags[] = {
00042 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
00043 { CODEC_ID_MP3, MKTAG('m', 'p', '3', ' ') },
00044 { CODEC_ID_VORBIS, MKTAG('v', 'r', 'b', 's') },
00045 { 0, 0 },
00046 };
00047
00048 #if CONFIG_LIBNUT_MUXER
00049 static int av_write(void * h, size_t len, const uint8_t * buf) {
00050 AVIOContext * bc = h;
00051 avio_write(bc, buf, len);
00052
00053 return len;
00054 }
00055
00056 static int nut_write_header(AVFormatContext * avf) {
00057 NUTContext * priv = avf->priv_data;
00058 AVIOContext * bc = avf->pb;
00059 nut_muxer_opts_tt mopts = {
00060 .output = {
00061 .priv = bc,
00062 .write = av_write,
00063 },
00064 .alloc = { av_malloc, av_realloc, av_free },
00065 .write_index = 1,
00066 .realtime_stream = 0,
00067 .max_distance = 32768,
00068 .fti = NULL,
00069 };
00070 nut_stream_header_tt * s;
00071 int i;
00072
00073 priv->s = s = av_mallocz((avf->nb_streams + 1) * sizeof*s);
00074 if(!s)
00075 return AVERROR(ENOMEM);
00076
00077 for (i = 0; i < avf->nb_streams; i++) {
00078 AVCodecContext * codec = avf->streams[i]->codec;
00079 int j;
00080 int fourcc = 0;
00081 int num, denom, ssize;
00082
00083 s[i].type = codec->codec_type == AVMEDIA_TYPE_VIDEO ? NUT_VIDEO_CLASS : NUT_AUDIO_CLASS;
00084
00085 if (codec->codec_tag) fourcc = codec->codec_tag;
00086 else fourcc = ff_codec_get_tag(nut_tags, codec->codec_id);
00087
00088 if (!fourcc) {
00089 if (codec->codec_type == AVMEDIA_TYPE_VIDEO) fourcc = ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id);
00090 if (codec->codec_type == AVMEDIA_TYPE_AUDIO) fourcc = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_id);
00091 }
00092
00093 s[i].fourcc_len = 4;
00094 s[i].fourcc = av_malloc(s[i].fourcc_len);
00095 for (j = 0; j < s[i].fourcc_len; j++) s[i].fourcc[j] = (fourcc >> (j*8)) & 0xFF;
00096
00097 ff_parse_specific_params(codec, &num, &ssize, &denom);
00098 avpriv_set_pts_info(avf->streams[i], 60, denom, num);
00099
00100 s[i].time_base.num = denom;
00101 s[i].time_base.den = num;
00102
00103 s[i].fixed_fps = 0;
00104 s[i].decode_delay = codec->has_b_frames;
00105 s[i].codec_specific_len = codec->extradata_size;
00106 s[i].codec_specific = codec->extradata;
00107
00108 if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
00109 s[i].width = codec->width;
00110 s[i].height = codec->height;
00111 s[i].sample_width = 0;
00112 s[i].sample_height = 0;
00113 s[i].colorspace_type = 0;
00114 } else {
00115 s[i].samplerate_num = codec->sample_rate;
00116 s[i].samplerate_denom = 1;
00117 s[i].channel_count = codec->channels;
00118 }
00119 }
00120
00121 s[avf->nb_streams].type = -1;
00122 priv->nut = nut_muxer_init(&mopts, s, NULL);
00123
00124 return 0;
00125 }
00126
00127 static int nut_write_packet(AVFormatContext * avf, AVPacket * pkt) {
00128 NUTContext * priv = avf->priv_data;
00129 nut_packet_tt p;
00130
00131 p.len = pkt->size;
00132 p.stream = pkt->stream_index;
00133 p.pts = pkt->pts;
00134 p.flags = pkt->flags & AV_PKT_FLAG_KEY ? NUT_FLAG_KEY : 0;
00135 p.next_pts = 0;
00136
00137 nut_write_frame_reorder(priv->nut, &p, pkt->data);
00138
00139 return 0;
00140 }
00141
00142 static int nut_write_trailer(AVFormatContext * avf) {
00143 AVIOContext * bc = avf->pb;
00144 NUTContext * priv = avf->priv_data;
00145 int i;
00146
00147 nut_muxer_uninit_reorder(priv->nut);
00148 avio_flush(bc);
00149
00150 for(i = 0; priv->s[i].type != -1; i++ ) av_freep(&priv->s[i].fourcc);
00151 av_freep(&priv->s);
00152
00153 return 0;
00154 }
00155
00156 AVOutputFormat ff_libnut_muxer = {
00157 .name = "libnut",
00158 .long_name = "nut format",
00159 .mime_type = "video/x-nut",
00160 .extensions = "nut",
00161 .priv_data_size = sizeof(NUTContext),
00162 .audio_codec = CODEC_ID_VORBIS,
00163 .video_codec = CODEC_ID_MPEG4,
00164 .write_header = nut_write_header,
00165 .write_packet = nut_write_packet,
00166 .write_trailer = nut_write_trailer,
00167 .flags = AVFMT_GLOBALHEADER,
00168 };
00169 #endif
00170
00171 static int nut_probe(AVProbeData *p) {
00172 if (!memcmp(p->buf, ID_STRING, ID_LENGTH)) return AVPROBE_SCORE_MAX;
00173
00174 return 0;
00175 }
00176
00177 static size_t av_read(void * h, size_t len, uint8_t * buf) {
00178 AVIOContext * bc = h;
00179 return avio_read(bc, buf, len);
00180 }
00181
00182 static off_t av_seek(void * h, long long pos, int whence) {
00183 AVIOContext * bc = h;
00184 if (whence == SEEK_END) {
00185 pos = avio_size(bc) + pos;
00186 whence = SEEK_SET;
00187 }
00188 return avio_seek(bc, pos, whence);
00189 }
00190
00191 static int nut_read_header(AVFormatContext * avf) {
00192 NUTContext * priv = avf->priv_data;
00193 AVIOContext * bc = avf->pb;
00194 nut_demuxer_opts_tt dopts = {
00195 .input = {
00196 .priv = bc,
00197 .seek = av_seek,
00198 .read = av_read,
00199 .eof = NULL,
00200 .file_pos = 0,
00201 },
00202 .alloc = { av_malloc, av_realloc, av_free },
00203 .read_index = 1,
00204 .cache_syncpoints = 1,
00205 };
00206 nut_context_tt * nut = priv->nut = nut_demuxer_init(&dopts);
00207 nut_stream_header_tt * s;
00208 int ret, i;
00209
00210 if(!nut)
00211 return -1;
00212
00213 if ((ret = nut_read_headers(nut, &s, NULL))) {
00214 av_log(avf, AV_LOG_ERROR, " NUT error: %s\n", nut_error(ret));
00215 nut_demuxer_uninit(nut);
00216 priv->nut = NULL;
00217 return -1;
00218 }
00219
00220 priv->s = s;
00221
00222 for (i = 0; s[i].type != -1 && i < 2; i++) {
00223 AVStream * st = avformat_new_stream(avf, NULL);
00224 int j;
00225
00226 for (j = 0; j < s[i].fourcc_len && j < 8; j++) st->codec->codec_tag |= s[i].fourcc[j]<<(j*8);
00227
00228 st->codec->has_b_frames = s[i].decode_delay;
00229
00230 st->codec->extradata_size = s[i].codec_specific_len;
00231 if (st->codec->extradata_size) {
00232 st->codec->extradata = av_mallocz(st->codec->extradata_size);
00233 if(!st->codec->extradata){
00234 nut_demuxer_uninit(nut);
00235 priv->nut = NULL;
00236 return AVERROR(ENOMEM);
00237 }
00238 memcpy(st->codec->extradata, s[i].codec_specific, st->codec->extradata_size);
00239 }
00240
00241 avpriv_set_pts_info(avf->streams[i], 60, s[i].time_base.num, s[i].time_base.den);
00242 st->start_time = 0;
00243 st->duration = s[i].max_pts;
00244
00245 st->codec->codec_id = ff_codec_get_id(nut_tags, st->codec->codec_tag);
00246
00247 switch(s[i].type) {
00248 case NUT_AUDIO_CLASS:
00249 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00250 if (st->codec->codec_id == CODEC_ID_NONE) st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, st->codec->codec_tag);
00251
00252 st->codec->channels = s[i].channel_count;
00253 st->codec->sample_rate = s[i].samplerate_num / s[i].samplerate_denom;
00254 break;
00255 case NUT_VIDEO_CLASS:
00256 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00257 if (st->codec->codec_id == CODEC_ID_NONE) st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, st->codec->codec_tag);
00258
00259 st->codec->width = s[i].width;
00260 st->codec->height = s[i].height;
00261 st->sample_aspect_ratio.num = s[i].sample_width;
00262 st->sample_aspect_ratio.den = s[i].sample_height;
00263 break;
00264 }
00265 if (st->codec->codec_id == CODEC_ID_NONE) av_log(avf, AV_LOG_ERROR, "Unknown codec?!\n");
00266 }
00267
00268 return 0;
00269 }
00270
00271 static int nut_read_packet(AVFormatContext * avf, AVPacket * pkt) {
00272 NUTContext * priv = avf->priv_data;
00273 nut_packet_tt pd;
00274 int ret;
00275
00276 ret = nut_read_next_packet(priv->nut, &pd);
00277
00278 if (ret || av_new_packet(pkt, pd.len) < 0) {
00279 if (ret != NUT_ERR_EOF)
00280 av_log(avf, AV_LOG_ERROR, " NUT error: %s\n", nut_error(ret));
00281 return -1;
00282 }
00283
00284 if (pd.flags & NUT_FLAG_KEY) pkt->flags |= AV_PKT_FLAG_KEY;
00285 pkt->pts = pd.pts;
00286 pkt->stream_index = pd.stream;
00287 pkt->pos = avio_tell(avf->pb);
00288
00289 ret = nut_read_frame(priv->nut, &pd.len, pkt->data);
00290
00291 return ret;
00292 }
00293
00294 static int nut_read_seek(AVFormatContext * avf, int stream_index, int64_t target_ts, int flags) {
00295 NUTContext * priv = avf->priv_data;
00296 int active_streams[] = { stream_index, -1 };
00297 double time_pos = target_ts * priv->s[stream_index].time_base.num / (double)priv->s[stream_index].time_base.den;
00298
00299 if (nut_seek(priv->nut, time_pos, 2*!(flags & AVSEEK_FLAG_BACKWARD), active_streams)) return -1;
00300
00301 return 0;
00302 }
00303
00304 static int nut_read_close(AVFormatContext *s) {
00305 NUTContext * priv = s->priv_data;
00306
00307 nut_demuxer_uninit(priv->nut);
00308
00309 return 0;
00310 }
00311
00312 AVInputFormat ff_libnut_demuxer = {
00313 .name = "libnut",
00314 .long_name = NULL_IF_CONFIG_SMALL("NUT format"),
00315 .priv_data_size = sizeof(NUTContext),
00316 .read_probe = nut_probe,
00317 .read_header = nut_read_header,
00318 .read_packet = nut_read_packet,
00319 .read_close = nut_read_close,
00320 .read_seek = nut_read_seek,
00321 .extensions = "nut",
00322 };