Libav
|
00001 /* 00002 * NUT (de)muxing via libnut 00003 * copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org> 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00028 #include "avformat.h" 00029 #include "riff.h" 00030 #include <libnut.h> 00031 00032 #define ID_STRING "nut/multimedia container" 00033 #define ID_LENGTH (strlen(ID_STRING) + 1) 00034 00035 typedef struct { 00036 nut_context_tt * nut; 00037 nut_stream_header_tt * s; 00038 } NUTContext; 00039 00040 static const AVCodecTag nut_tags[] = { 00041 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') }, 00042 { CODEC_ID_MP3, MKTAG('m', 'p', '3', ' ') }, 00043 { CODEC_ID_VORBIS, MKTAG('v', 'r', 'b', 's') }, 00044 { 0, 0 }, 00045 }; 00046 00047 #if CONFIG_LIBNUT_MUXER 00048 static int av_write(void * h, size_t len, const uint8_t * buf) { 00049 ByteIOContext * bc = h; 00050 put_buffer(bc, buf, len); 00051 //put_flush_packet(bc); 00052 return len; 00053 } 00054 00055 static int nut_write_header(AVFormatContext * avf) { 00056 NUTContext * priv = avf->priv_data; 00057 ByteIOContext * bc = avf->pb; 00058 nut_muxer_opts_tt mopts = { 00059 .output = { 00060 .priv = bc, 00061 .write = av_write, 00062 }, 00063 .alloc = { av_malloc, av_realloc, av_free }, 00064 .write_index = 1, 00065 .realtime_stream = 0, 00066 .max_distance = 32768, 00067 .fti = NULL, 00068 }; 00069 nut_stream_header_tt * s; 00070 int i; 00071 00072 priv->s = s = av_mallocz((avf->nb_streams + 1) * sizeof*s); 00073 00074 for (i = 0; i < avf->nb_streams; i++) { 00075 AVCodecContext * codec = avf->streams[i]->codec; 00076 int j; 00077 int fourcc = 0; 00078 int num, denom, ssize; 00079 00080 s[i].type = codec->codec_type == AVMEDIA_TYPE_VIDEO ? NUT_VIDEO_CLASS : NUT_AUDIO_CLASS; 00081 00082 if (codec->codec_tag) fourcc = codec->codec_tag; 00083 else fourcc = ff_codec_get_tag(nut_tags, codec->codec_id); 00084 00085 if (!fourcc) { 00086 if (codec->codec_type == AVMEDIA_TYPE_VIDEO) fourcc = ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id); 00087 if (codec->codec_type == AVMEDIA_TYPE_AUDIO) fourcc = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_id); 00088 } 00089 00090 s[i].fourcc_len = 4; 00091 s[i].fourcc = av_malloc(s[i].fourcc_len); 00092 for (j = 0; j < s[i].fourcc_len; j++) s[i].fourcc[j] = (fourcc >> (j*8)) & 0xFF; 00093 00094 ff_parse_specific_params(codec, &num, &ssize, &denom); 00095 av_set_pts_info(avf->streams[i], 60, denom, num); 00096 00097 s[i].time_base.num = denom; 00098 s[i].time_base.den = num; 00099 00100 s[i].fixed_fps = 0; 00101 s[i].decode_delay = codec->has_b_frames; 00102 s[i].codec_specific_len = codec->extradata_size; 00103 s[i].codec_specific = codec->extradata; 00104 00105 if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { 00106 s[i].width = codec->width; 00107 s[i].height = codec->height; 00108 s[i].sample_width = 0; 00109 s[i].sample_height = 0; 00110 s[i].colorspace_type = 0; 00111 } else { 00112 s[i].samplerate_num = codec->sample_rate; 00113 s[i].samplerate_denom = 1; 00114 s[i].channel_count = codec->channels; 00115 } 00116 } 00117 00118 s[avf->nb_streams].type = -1; 00119 priv->nut = nut_muxer_init(&mopts, s, NULL); 00120 00121 return 0; 00122 } 00123 00124 static int nut_write_packet(AVFormatContext * avf, AVPacket * pkt) { 00125 NUTContext * priv = avf->priv_data; 00126 nut_packet_tt p; 00127 00128 p.len = pkt->size; 00129 p.stream = pkt->stream_index; 00130 p.pts = pkt->pts; 00131 p.flags = pkt->flags & AV_PKT_FLAG_KEY ? NUT_FLAG_KEY : 0; 00132 p.next_pts = 0; 00133 00134 nut_write_frame_reorder(priv->nut, &p, pkt->data); 00135 00136 return 0; 00137 } 00138 00139 static int nut_write_trailer(AVFormatContext * avf) { 00140 ByteIOContext * bc = avf->pb; 00141 NUTContext * priv = avf->priv_data; 00142 int i; 00143 00144 nut_muxer_uninit_reorder(priv->nut); 00145 put_flush_packet(bc); 00146 00147 for(i = 0; priv->s[i].type != -1; i++ ) av_freep(&priv->s[i].fourcc); 00148 av_freep(&priv->s); 00149 00150 return 0; 00151 } 00152 00153 AVOutputFormat libnut_muxer = { 00154 "libnut", 00155 "nut format", 00156 "video/x-nut", 00157 "nut", 00158 sizeof(NUTContext), 00159 CODEC_ID_VORBIS, 00160 CODEC_ID_MPEG4, 00161 nut_write_header, 00162 nut_write_packet, 00163 nut_write_trailer, 00164 .flags = AVFMT_GLOBALHEADER, 00165 }; 00166 #endif /* CONFIG_LIBNUT_MUXER */ 00167 00168 static int nut_probe(AVProbeData *p) { 00169 if (!memcmp(p->buf, ID_STRING, ID_LENGTH)) return AVPROBE_SCORE_MAX; 00170 00171 return 0; 00172 } 00173 00174 static size_t av_read(void * h, size_t len, uint8_t * buf) { 00175 ByteIOContext * bc = h; 00176 return get_buffer(bc, buf, len); 00177 } 00178 00179 static off_t av_seek(void * h, long long pos, int whence) { 00180 ByteIOContext * bc = h; 00181 if (whence == SEEK_END) { 00182 pos = url_fsize(bc) + pos; 00183 whence = SEEK_SET; 00184 } 00185 return url_fseek(bc, pos, whence); 00186 } 00187 00188 static int nut_read_header(AVFormatContext * avf, AVFormatParameters * ap) { 00189 NUTContext * priv = avf->priv_data; 00190 ByteIOContext * bc = avf->pb; 00191 nut_demuxer_opts_tt dopts = { 00192 .input = { 00193 .priv = bc, 00194 .seek = av_seek, 00195 .read = av_read, 00196 .eof = NULL, 00197 .file_pos = 0, 00198 }, 00199 .alloc = { av_malloc, av_realloc, av_free }, 00200 .read_index = 1, 00201 .cache_syncpoints = 1, 00202 }; 00203 nut_context_tt * nut = priv->nut = nut_demuxer_init(&dopts); 00204 nut_stream_header_tt * s; 00205 int ret, i; 00206 00207 if ((ret = nut_read_headers(nut, &s, NULL))) { 00208 av_log(avf, AV_LOG_ERROR, " NUT error: %s\n", nut_error(ret)); 00209 nut_demuxer_uninit(nut); 00210 return -1; 00211 } 00212 00213 priv->s = s; 00214 00215 for (i = 0; s[i].type != -1 && i < 2; i++) { 00216 AVStream * st = av_new_stream(avf, i); 00217 int j; 00218 00219 for (j = 0; j < s[i].fourcc_len && j < 8; j++) st->codec->codec_tag |= s[i].fourcc[j]<<(j*8); 00220 00221 st->codec->has_b_frames = s[i].decode_delay; 00222 00223 st->codec->extradata_size = s[i].codec_specific_len; 00224 if (st->codec->extradata_size) { 00225 st->codec->extradata = av_mallocz(st->codec->extradata_size); 00226 memcpy(st->codec->extradata, s[i].codec_specific, st->codec->extradata_size); 00227 } 00228 00229 av_set_pts_info(avf->streams[i], 60, s[i].time_base.num, s[i].time_base.den); 00230 st->start_time = 0; 00231 st->duration = s[i].max_pts; 00232 00233 st->codec->codec_id = ff_codec_get_id(nut_tags, st->codec->codec_tag); 00234 00235 switch(s[i].type) { 00236 case NUT_AUDIO_CLASS: 00237 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00238 if (st->codec->codec_id == CODEC_ID_NONE) st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, st->codec->codec_tag); 00239 00240 st->codec->channels = s[i].channel_count; 00241 st->codec->sample_rate = s[i].samplerate_num / s[i].samplerate_denom; 00242 break; 00243 case NUT_VIDEO_CLASS: 00244 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00245 if (st->codec->codec_id == CODEC_ID_NONE) st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, st->codec->codec_tag); 00246 00247 st->codec->width = s[i].width; 00248 st->codec->height = s[i].height; 00249 st->sample_aspect_ratio.num = s[i].sample_width; 00250 st->sample_aspect_ratio.den = s[i].sample_height; 00251 break; 00252 } 00253 if (st->codec->codec_id == CODEC_ID_NONE) av_log(avf, AV_LOG_ERROR, "Unknown codec?!\n"); 00254 } 00255 00256 return 0; 00257 } 00258 00259 static int nut_read_packet(AVFormatContext * avf, AVPacket * pkt) { 00260 NUTContext * priv = avf->priv_data; 00261 nut_packet_tt pd; 00262 int ret; 00263 00264 ret = nut_read_next_packet(priv->nut, &pd); 00265 00266 if (ret || av_new_packet(pkt, pd.len) < 0) { 00267 if (ret != NUT_ERR_EOF) 00268 av_log(avf, AV_LOG_ERROR, " NUT error: %s\n", nut_error(ret)); 00269 return -1; 00270 } 00271 00272 if (pd.flags & NUT_FLAG_KEY) pkt->flags |= AV_PKT_FLAG_KEY; 00273 pkt->pts = pd.pts; 00274 pkt->stream_index = pd.stream; 00275 pkt->pos = url_ftell(avf->pb); 00276 00277 ret = nut_read_frame(priv->nut, &pd.len, pkt->data); 00278 00279 return ret; 00280 } 00281 00282 static int nut_read_seek(AVFormatContext * avf, int stream_index, int64_t target_ts, int flags) { 00283 NUTContext * priv = avf->priv_data; 00284 int active_streams[] = { stream_index, -1 }; 00285 double time_pos = target_ts * priv->s[stream_index].time_base.num / (double)priv->s[stream_index].time_base.den; 00286 00287 if (nut_seek(priv->nut, time_pos, 2*!(flags & AVSEEK_FLAG_BACKWARD), active_streams)) return -1; 00288 00289 return 0; 00290 } 00291 00292 static int nut_read_close(AVFormatContext *s) { 00293 NUTContext * priv = s->priv_data; 00294 00295 nut_demuxer_uninit(priv->nut); 00296 00297 return 0; 00298 } 00299 00300 AVInputFormat libnut_demuxer = { 00301 "libnut", 00302 NULL_IF_CONFIG_SMALL("NUT format"), 00303 sizeof(NUTContext), 00304 nut_probe, 00305 nut_read_header, 00306 nut_read_packet, 00307 nut_read_close, 00308 nut_read_seek, 00309 .extensions = "nut", 00310 };