diff options
Diffstat (limited to 'libavformat')
125 files changed, 1846 insertions, 1623 deletions
diff --git a/libavformat/4xm.c b/libavformat/4xm.c index 699277248d..0b79c761a5 100644 --- a/libavformat/4xm.c +++ b/libavformat/4xm.c @@ -246,7 +246,7 @@ static int fourxm_read_packet(AVFormatContext *s, FourxmDemuxContext *fourxm = s->priv_data; AVIOContext *pb = s->pb; unsigned int fourcc_tag; - unsigned int size, out_size; + unsigned int size; int ret = 0; unsigned int track_number; int packet_read = 0; @@ -295,7 +295,7 @@ static int fourxm_read_packet(AVFormatContext *s, case snd__TAG: track_number = avio_rl32(pb); - out_size= avio_rl32(pb); + avio_skip(pb, 4); size-=8; if (track_number < fourxm->track_count && fourxm->tracks[track_number].channels>0) { diff --git a/libavformat/Makefile b/libavformat/Makefile index cbaa4d6840..05f524690b 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -25,7 +25,7 @@ OBJS-$(CONFIG_AC3_MUXER) += rawenc.o OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o OBJS-$(CONFIG_AEA_DEMUXER) += aea.o pcm.o OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o riff.o pcm.o isom.o -OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o riff.o +OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o riff.o isom.o OBJS-$(CONFIG_AMR_DEMUXER) += amr.o OBJS-$(CONFIG_AMR_MUXER) += amr.o OBJS-$(CONFIG_ANM_DEMUXER) += anm.o @@ -234,6 +234,7 @@ OBJS-$(CONFIG_RSO_MUXER) += rsoenc.o rso.o OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ rtpenc_aac.o \ + rtpenc_latm.o \ rtpenc_amr.o \ rtpenc_h263.o \ rtpenc_mpv.o \ @@ -340,9 +341,6 @@ OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o # libavdevice dependencies OBJS-$(CONFIG_JACK_INDEV) += timefilter.o -EXAMPLES = output TESTPROGS = timefilter include $(SUBDIR)../subdir.mak - -$(SUBDIR)output-example$(EXESUF): ELIBS = -lswscale diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index 47e9bf3a18..4ac2cadb8f 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -44,7 +44,7 @@ static int adts_aac_probe(AVProbeData *p) uint32_t header = AV_RB16(buf2); if((header&0xFFF6) != 0xFFF0) break; - fsize = (AV_RB32(buf2+3)>>13) & 0x8FFF; + fsize = (AV_RB32(buf2 + 3) >> 13) & 0x1FFF; if(fsize < 7) break; buf2 += fsize; diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index e691bba29d..9608910340 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -20,6 +20,7 @@ */ #include "libavutil/intfloat_readwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #include "pcm.h" #include "aiff.h" @@ -77,7 +78,7 @@ static void get_meta(AVFormatContext *s, const char *key, int size) } size += (size&1)-res; str[res] = 0; - av_metadata_set2(&s->metadata, key, str, AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(&s->metadata, key, str, AV_METADATA_DONT_STRDUP_VAL); }else size+= size&1; diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index cc3cbc4762..34ab0cc246 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -22,6 +22,7 @@ #include "avformat.h" #include "aiff.h" #include "avio_internal.h" +#include "isom.h" typedef struct { int64_t form; @@ -61,6 +62,12 @@ static int aiff_write_header(AVFormatContext *s) avio_wb32(pb, 0xA2805140); } + if (enc->channels > 2 && enc->channel_layout) { + ffio_wfourcc(pb, "CHAN"); + avio_wb32(pb, 12); + ff_mov_write_chan(pb, enc->channel_layout); + } + /* Common chunk */ ffio_wfourcc(pb, "COMM"); avio_wb32(pb, aifc ? 24 : 18); /* size */ diff --git a/libavformat/ape.c b/libavformat/ape.c index 4b37c7972d..bda6b32b1d 100644 --- a/libavformat/ape.c +++ b/libavformat/ape.c @@ -26,8 +26,6 @@ #include "avformat.h" #include "apetag.h" -#define ENABLE_DEBUG 0 - /* The earliest and latest file formats supported by this library */ #define APE_MIN_VERSION 3950 #define APE_MAX_VERSION 3990 @@ -96,19 +94,19 @@ static int ape_probe(AVProbeData * p) static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx) { -#if ENABLE_DEBUG +#ifdef DEBUG int i; av_log(s, AV_LOG_DEBUG, "Descriptor Block:\n\n"); av_log(s, AV_LOG_DEBUG, "magic = \"%c%c%c%c\"\n", ape_ctx->magic[0], ape_ctx->magic[1], ape_ctx->magic[2], ape_ctx->magic[3]); - av_log(s, AV_LOG_DEBUG, "fileversion = %d\n", ape_ctx->fileversion); - av_log(s, AV_LOG_DEBUG, "descriptorlength = %d\n", ape_ctx->descriptorlength); - av_log(s, AV_LOG_DEBUG, "headerlength = %d\n", ape_ctx->headerlength); - av_log(s, AV_LOG_DEBUG, "seektablelength = %d\n", ape_ctx->seektablelength); - av_log(s, AV_LOG_DEBUG, "wavheaderlength = %d\n", ape_ctx->wavheaderlength); - av_log(s, AV_LOG_DEBUG, "audiodatalength = %d\n", ape_ctx->audiodatalength); - av_log(s, AV_LOG_DEBUG, "audiodatalength_high = %d\n", ape_ctx->audiodatalength_high); - av_log(s, AV_LOG_DEBUG, "wavtaillength = %d\n", ape_ctx->wavtaillength); + av_log(s, AV_LOG_DEBUG, "fileversion = %"PRId16"\n", ape_ctx->fileversion); + av_log(s, AV_LOG_DEBUG, "descriptorlength = %"PRIu32"\n", ape_ctx->descriptorlength); + av_log(s, AV_LOG_DEBUG, "headerlength = %"PRIu32"\n", ape_ctx->headerlength); + av_log(s, AV_LOG_DEBUG, "seektablelength = %"PRIu32"\n", ape_ctx->seektablelength); + av_log(s, AV_LOG_DEBUG, "wavheaderlength = %"PRIu32"\n", ape_ctx->wavheaderlength); + av_log(s, AV_LOG_DEBUG, "audiodatalength = %"PRIu32"\n", ape_ctx->audiodatalength); + av_log(s, AV_LOG_DEBUG, "audiodatalength_high = %"PRIu32"\n", ape_ctx->audiodatalength_high); + av_log(s, AV_LOG_DEBUG, "wavtaillength = %"PRIu32"\n", ape_ctx->wavtaillength); av_log(s, AV_LOG_DEBUG, "md5 = "); for (i = 0; i < 16; i++) av_log(s, AV_LOG_DEBUG, "%02x", ape_ctx->md5[i]); @@ -116,14 +114,14 @@ static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx) av_log(s, AV_LOG_DEBUG, "\nHeader Block:\n\n"); - av_log(s, AV_LOG_DEBUG, "compressiontype = %d\n", ape_ctx->compressiontype); - av_log(s, AV_LOG_DEBUG, "formatflags = %d\n", ape_ctx->formatflags); - av_log(s, AV_LOG_DEBUG, "blocksperframe = %d\n", ape_ctx->blocksperframe); - av_log(s, AV_LOG_DEBUG, "finalframeblocks = %d\n", ape_ctx->finalframeblocks); - av_log(s, AV_LOG_DEBUG, "totalframes = %d\n", ape_ctx->totalframes); - av_log(s, AV_LOG_DEBUG, "bps = %d\n", ape_ctx->bps); - av_log(s, AV_LOG_DEBUG, "channels = %d\n", ape_ctx->channels); - av_log(s, AV_LOG_DEBUG, "samplerate = %d\n", ape_ctx->samplerate); + av_log(s, AV_LOG_DEBUG, "compressiontype = %"PRIu16"\n", ape_ctx->compressiontype); + av_log(s, AV_LOG_DEBUG, "formatflags = %"PRIu16"\n", ape_ctx->formatflags); + av_log(s, AV_LOG_DEBUG, "blocksperframe = %"PRIu32"\n", ape_ctx->blocksperframe); + av_log(s, AV_LOG_DEBUG, "finalframeblocks = %"PRIu32"\n", ape_ctx->finalframeblocks); + av_log(s, AV_LOG_DEBUG, "totalframes = %"PRIu32"\n", ape_ctx->totalframes); + av_log(s, AV_LOG_DEBUG, "bps = %"PRIu16"\n", ape_ctx->bps); + av_log(s, AV_LOG_DEBUG, "channels = %"PRIu16"\n", ape_ctx->channels); + av_log(s, AV_LOG_DEBUG, "samplerate = %"PRIu32"\n", ape_ctx->samplerate); av_log(s, AV_LOG_DEBUG, "\nSeektable\n\n"); if ((ape_ctx->seektablelength / sizeof(uint32_t)) != ape_ctx->totalframes) { @@ -140,12 +138,14 @@ static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx) av_log(s, AV_LOG_DEBUG, "\nFrames\n\n"); for (i = 0; i < ape_ctx->totalframes; i++) - av_log(s, AV_LOG_DEBUG, "%8d %8lld %8d (%d samples)\n", i, ape_ctx->frames[i].pos, ape_ctx->frames[i].size, ape_ctx->frames[i].nblocks); + av_log(s, AV_LOG_DEBUG, "%8d %8"PRId64" %8d (%d samples)\n", i, + ape_ctx->frames[i].pos, ape_ctx->frames[i].size, + ape_ctx->frames[i].nblocks); av_log(s, AV_LOG_DEBUG, "\nCalculated information:\n\n"); - av_log(s, AV_LOG_DEBUG, "junklength = %d\n", ape_ctx->junklength); - av_log(s, AV_LOG_DEBUG, "firstframe = %d\n", ape_ctx->firstframe); - av_log(s, AV_LOG_DEBUG, "totalsamples = %d\n", ape_ctx->totalsamples); + av_log(s, AV_LOG_DEBUG, "junklength = %"PRIu32"\n", ape_ctx->junklength); + av_log(s, AV_LOG_DEBUG, "firstframe = %"PRIu32"\n", ape_ctx->firstframe); + av_log(s, AV_LOG_DEBUG, "totalsamples = %"PRIu32"\n", ape_ctx->totalsamples); #endif } @@ -169,7 +169,8 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) ape->fileversion = avio_rl16(pb); if (ape->fileversion < APE_MIN_VERSION || ape->fileversion > APE_MAX_VERSION) { - av_log(s, AV_LOG_ERROR, "Unsupported file version - %d.%02d\n", ape->fileversion / 1000, (ape->fileversion % 1000) / 10); + av_log(s, AV_LOG_ERROR, "Unsupported file version - %"PRId16".%02"PRId16"\n", + ape->fileversion / 1000, (ape->fileversion % 1000) / 10); return -1; } @@ -247,11 +248,12 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) return AVERROR(EINVAL); } if(ape->totalframes > UINT_MAX / sizeof(APEFrame)){ - av_log(s, AV_LOG_ERROR, "Too many frames: %d\n", ape->totalframes); + av_log(s, AV_LOG_ERROR, "Too many frames: %"PRIu32"\n", + ape->totalframes); return -1; } if (ape->seektablelength && (ape->seektablelength / sizeof(*ape->seektable)) < ape->totalframes) { - av_log(s, AV_LOG_ERROR, "Number of seek entries is less than number of frames: %zd vs. %d\n", + av_log(s, AV_LOG_ERROR, "Number of seek entries is less than number of frames: %ld vs. %"PRIu32"\n", ape->seektablelength / sizeof(*ape->seektable), ape->totalframes); return AVERROR_INVALIDDATA; } @@ -276,7 +278,7 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) ape->frames[0].nblocks = ape->blocksperframe; ape->frames[0].skip = 0; for (i = 1; i < ape->totalframes; i++) { - ape->frames[i].pos = ape->seektable[i] + ape->junklength; //ape->frames[i-1].pos + ape->blocksperframe; + ape->frames[i].pos = ape->seektable[i] + ape->junklength; ape->frames[i].nblocks = ape->blocksperframe; ape->frames[i - 1].size = ape->frames[i].pos - ape->frames[i - 1].pos; ape->frames[i].skip = (ape->frames[i].pos - ape->frames[0].pos) & 3; @@ -301,7 +303,9 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) avio_seek(pb, 0, SEEK_SET); } - av_log(s, AV_LOG_DEBUG, "Decoding file - v%d.%02d, compression level %d\n", ape->fileversion / 1000, (ape->fileversion % 1000) / 10, ape->compressiontype); + av_log(s, AV_LOG_DEBUG, "Decoding file - v%d.%02d, compression level %"PRIu16"\n", + ape->fileversion / 1000, (ape->fileversion % 1000) / 10, + ape->compressiontype); /* now we are ready: build format streams */ st = av_new_stream(s, 0); diff --git a/libavformat/apetag.c b/libavformat/apetag.c index fb46d2bac2..8d53e4cdf7 100644 --- a/libavformat/apetag.c +++ b/libavformat/apetag.c @@ -21,11 +21,10 @@ */ #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #include "apetag.h" -#define ENABLE_DEBUG 0 - #define APE_TAG_VERSION 2000 #define APE_TAG_FOOTER_BYTES 32 #define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31) @@ -35,11 +34,11 @@ static int ape_tag_read_field(AVFormatContext *s) { AVIOContext *pb = s->pb; uint8_t key[1024], *value; - uint32_t size, flags; + uint32_t size; int i, c; size = avio_rl32(pb); /* field size */ - flags = avio_rl32(pb); /* field flags */ + avio_skip(pb, 4); /* field flags */ for (i = 0; i < sizeof(key) - 1; i++) { c = avio_r8(pb); if (c < 0x20 || c > 0x7E) @@ -59,7 +58,7 @@ static int ape_tag_read_field(AVFormatContext *s) return AVERROR(ENOMEM); avio_read(pb, value, size); value[size] = 0; - av_metadata_set2(&s->metadata, key, value, AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); return 0; } diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c index d0de6bbc3e..dec77f80e6 100644 --- a/libavformat/applehttp.c +++ b/libavformat/applehttp.c @@ -28,6 +28,7 @@ #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" +#include "libavutil/dict.h" #include "avformat.h" #include "internal.h" #include <unistd.h> @@ -507,7 +508,7 @@ static int applehttp_read_header(AVFormatContext *s, AVFormatParameters *ap) } avcodec_copy_context(st->codec, v->ctx->streams[j]->codec); if (v->bandwidth) - av_metadata_set2(&st->metadata, "variant_bitrate", bitrate_str, + av_dict_set(&st->metadata, "variant_bitrate", bitrate_str, 0); } stream_offset += v->ctx->nb_streams; diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c index 4a4f1d927c..725e013b17 100644 --- a/libavformat/asfdec.c +++ b/libavformat/asfdec.c @@ -21,8 +21,10 @@ //#define DEBUG +#include "libavutil/bswap.h" #include "libavutil/common.h" #include "libavutil/avstring.h" +#include "libavutil/dict.h" #include "libavcodec/mpegaudio.h" #include "avformat.h" #include "avio_internal.h" @@ -171,7 +173,8 @@ static void get_tag(AVFormatContext *s, const char *key, int type, int len) av_log(s, AV_LOG_DEBUG, "Unsupported value type %d in tag %s.\n", type, key); goto finish; } - av_metadata_set2(&s->metadata, key, value, 0); + if (*value) + av_dict_set(&s->metadata, key, value, 0); finish: av_freep(&value); avio_seek(s->pb, off + len, SEEK_SET); @@ -208,7 +211,6 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) ff_asf_guid g; enum AVMediaType type; int type_specific_size, sizeX; - uint64_t total_size; unsigned int tag1; int64_t pos1, pos2, start_time; int test_for_ext_stream_audio, is_dvr_ms_audio=0; @@ -255,7 +257,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) return -1; } ff_get_guid(pb, &g); - total_size = avio_rl64(pb); + avio_skip(pb, 8); /* total_size */ type_specific_size = avio_rl32(pb); avio_rl32(pb); st->id = avio_rl16(pb) & 0x7f; /* stream id */ @@ -393,7 +395,7 @@ static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size) AVIOContext *pb = s->pb; ff_asf_guid g; int ext_len, payload_ext_ct, stream_ct, i; - uint32_t ext_d, leak_rate, stream_num; + uint32_t leak_rate, stream_num; unsigned int stream_languageid_index; avio_rl64(pb); // starttime @@ -427,7 +429,7 @@ static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size) for (i=0; i<payload_ext_ct; i++){ ff_get_guid(pb, &g); - ext_d=avio_rl16(pb); + avio_skip(pb, 2); ext_len=avio_rl32(pb); avio_skip(pb, ext_len); } @@ -511,7 +513,7 @@ static int asf_read_metadata(AVFormatContext *s, int64_t size) { AVIOContext *pb = s->pb; ASFContext *asf = s->priv_data; - int n, stream_num, name_len, value_len, value_type, value_num; + int n, stream_num, name_len, value_len, value_num; int ret, i; n = avio_rl16(pb); @@ -521,7 +523,7 @@ static int asf_read_metadata(AVFormatContext *s, int64_t size) avio_rl16(pb); //lang_list_index stream_num= avio_rl16(pb); name_len= avio_rl16(pb); - value_type= avio_rl16(pb); + avio_skip(pb, 2); /* value_type */ value_len= avio_rl32(pb); if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len) @@ -626,10 +628,8 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) // if so the next iteration will pick it up continue; } else if (!ff_guidcmp(&g, &ff_asf_head1_guid)) { - int v1, v2; ff_get_guid(pb, &g); - v1 = avio_rl32(pb); - v2 = avio_rl16(pb); + avio_skip(pb, 6); continue; } else if (!ff_guidcmp(&g, &ff_asf_marker_header)) { asf_read_marker(s, gsize); @@ -684,7 +684,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) const char primary_tag[3] = { rfc1766[0], rfc1766[1], '\0' }; // ignore country code if any const char *iso6392 = av_convert_lang_to(primary_tag, AV_LANG_ISO639_2_BIBL); if (iso6392) - av_metadata_set2(&st->metadata, "language", iso6392, 0); + av_dict_set(&st->metadata, "language", iso6392, 0); } } } @@ -799,7 +799,7 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb){ ASFContext *asf = s->priv_data; int rsize = 1; int num = avio_r8(pb); - int64_t ts0, ts1; + int64_t ts0; asf->packet_segments--; asf->packet_key_frame = num >> 7; @@ -822,7 +822,7 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb){ // av_log(s, AV_LOG_DEBUG, "\n"); avio_skip(pb, 10); ts0= avio_rl64(pb); - ts1= avio_rl64(pb); + avio_skip(pb, 8);; avio_skip(pb, 12); avio_rl32(pb); avio_skip(pb, asf->packet_replic_size - 8 - 38 - 4); @@ -849,7 +849,10 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb){ } if (asf->packet_flags & 0x01) { DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal - if(asf->packet_frag_size > asf->packet_size_left - rsize){ + if (rsize > asf->packet_size_left) { + av_log(s, AV_LOG_ERROR, "packet_replic_size is invalid\n"); + return -1; + } else if(asf->packet_frag_size > asf->packet_size_left - rsize){ if (asf->packet_frag_size > asf->packet_size_left - rsize + asf->packet_padsize) { av_log(s, AV_LOG_ERROR, "packet_frag_size is invalid (%d-%d)\n", asf->packet_size_left, rsize); return -1; @@ -1257,21 +1260,22 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int if (!asf->index_read) asf_build_simple_index(s, stream_index); - if(!(asf->index_read && st->index_entries)){ - if(av_seek_frame_binary(s, stream_index, pts, flags)<0) - return -1; - }else{ + if((asf->index_read && st->index_entries)){ index= av_index_search_timestamp(st, pts, flags); - if(index<0) - return -1; + if(index >= 0) { + /* find the position */ + pos = st->index_entries[index].pos; - /* find the position */ - pos = st->index_entries[index].pos; - - /* do the seek */ - av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos); - avio_seek(s->pb, pos, SEEK_SET); + /* do the seek */ + av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos); + avio_seek(s->pb, pos, SEEK_SET); + asf_reset_header(s); + return 0; + } } + /* no index or seeking by index failed */ + if(av_seek_frame_binary(s, stream_index, pts, flags)<0) + return -1; asf_reset_header(s); return 0; } @@ -1286,4 +1290,5 @@ AVInputFormat ff_asf_demuxer = { asf_read_close, asf_read_seek, asf_read_pts, + .flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH, }; diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c index fe5a67ce4b..5c929f4547 100644 --- a/libavformat/asfenc.c +++ b/libavformat/asfenc.c @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" -#include "metadata.h" #include "riff.h" #include "asf.h" #include "avio_internal.h" +#include "libavutil/dict.h" #undef NDEBUG #include <assert.h> @@ -296,7 +296,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data { ASFContext *asf = s->priv_data; AVIOContext *pb = s->pb; - AVMetadataTag *tags[5]; + AVDictionaryEntry *tags[5]; int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; int has_title; int metadata_count; @@ -307,11 +307,11 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL); - tags[0] = av_metadata_get(s->metadata, "title" , NULL, 0); - tags[1] = av_metadata_get(s->metadata, "author" , NULL, 0); - tags[2] = av_metadata_get(s->metadata, "copyright", NULL, 0); - tags[3] = av_metadata_get(s->metadata, "comment" , NULL, 0); - tags[4] = av_metadata_get(s->metadata, "rating" , NULL, 0); + tags[0] = av_dict_get(s->metadata, "title" , NULL, 0); + tags[1] = av_dict_get(s->metadata, "author" , NULL, 0); + tags[2] = av_dict_get(s->metadata, "copyright", NULL, 0); + tags[3] = av_dict_get(s->metadata, "comment" , NULL, 0); + tags[4] = av_dict_get(s->metadata, "rating" , NULL, 0); duration = asf->duration + PREROLL_TIME * 10000; has_title = tags[0] || tags[1] || tags[2] || tags[3] || tags[4]; @@ -381,10 +381,10 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data end_header(pb, hpos); } if (metadata_count) { - AVMetadataTag *tag = NULL; + AVDictionaryEntry *tag = NULL; hpos = put_header(pb, &ff_asf_extended_content_header); avio_wl16(pb, metadata_count); - while ((tag = av_metadata_get(s->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX))) { + while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { put_str16(pb, tag->key); avio_wl16(pb, 0); put_str16(pb, tag->value); diff --git a/libavformat/avformat.h b/libavformat/avformat.h index e558096cf2..05cbf0a6b1 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -23,8 +23,7 @@ /** - * I return the LIBAVFORMAT_VERSION_INT constant. You got - * a fucking problem with that, douchebag? + * Return the LIBAVFORMAT_VERSION_INT constant. */ unsigned avformat_version(void); @@ -41,6 +40,7 @@ const char *avformat_license(void); #include <time.h> #include <stdio.h> /* FILE */ #include "libavcodec/avcodec.h" +#include "libavutil/dict.h" #include "avio.h" #include "libavformat/version.h" @@ -107,21 +107,24 @@ struct AVFormatContext; * variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of */ -#define AV_METADATA_MATCH_CASE 1 -#define AV_METADATA_IGNORE_SUFFIX 2 -#define AV_METADATA_DONT_STRDUP_KEY 4 -#define AV_METADATA_DONT_STRDUP_VAL 8 -#define AV_METADATA_DONT_OVERWRITE 16 ///< Don't overwrite existing tags. +#if FF_API_OLD_METADATA2 +/** + * @defgroup old_metadata Old metadata API + * The following functions are deprecated, use + * their equivalents from libavutil/dict.h instead. + * @{ + */ -typedef struct { - char *key; - char *value; -}AVMetadataTag; +#define AV_METADATA_MATCH_CASE AV_DICT_MATCH_CASE +#define AV_METADATA_IGNORE_SUFFIX AV_DICT_IGNORE_SUFFIX +#define AV_METADATA_DONT_STRDUP_KEY AV_DICT_DONT_STRDUP_KEY +#define AV_METADATA_DONT_STRDUP_VAL AV_DICT_DONT_STRDUP_VAL +#define AV_METADATA_DONT_OVERWRITE AV_DICT_DONT_OVERWRITE + +typedef attribute_deprecated AVDictionary AVMetadata; +typedef attribute_deprecated AVDictionaryEntry AVMetadataTag; -typedef struct AVMetadata AVMetadata; -#if FF_API_OLD_METADATA2 typedef struct AVMetadataConv AVMetadataConv; -#endif /** * Get a metadata element with matching key. @@ -131,8 +134,8 @@ typedef struct AVMetadataConv AVMetadataConv; * @param flags Allows case as well as suffix-insensitive comparisons. * @return Found tag or NULL, changing key or value leads to undefined behavior. */ -AVMetadataTag * -av_metadata_get(AVMetadata *m, const char *key, const AVMetadataTag *prev, int flags); +attribute_deprecated AVDictionaryEntry * +av_metadata_get(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags); #if FF_API_OLD_METADATA /** @@ -158,30 +161,32 @@ attribute_deprecated int av_metadata_set(AVMetadata **pm, const char *key, const * Passing a NULL value will cause an existing tag to be deleted. * @return >= 0 on success otherwise an error code <0 */ -int av_metadata_set2(AVMetadata **pm, const char *key, const char *value, int flags); +attribute_deprecated int av_metadata_set2(AVDictionary **pm, const char *key, const char *value, int flags); -#if FF_API_OLD_METADATA2 /** * This function is provided for compatibility reason and currently does nothing. */ attribute_deprecated void av_metadata_conv(struct AVFormatContext *ctx, const AVMetadataConv *d_conv, const AVMetadataConv *s_conv); -#endif /** - * Copy metadata from one AVMetadata struct into another. - * @param dst pointer to a pointer to a AVMetadata struct. If *dst is NULL, + * Copy metadata from one AVDictionary struct into another. + * @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL, * this function will allocate a struct for you and put it in *dst - * @param src pointer to source AVMetadata struct + * @param src pointer to source AVDictionary struct * @param flags flags to use when setting metadata in *dst - * @note metadata is read using the AV_METADATA_IGNORE_SUFFIX flag + * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag */ -void av_metadata_copy(AVMetadata **dst, AVMetadata *src, int flags); +attribute_deprecated void av_metadata_copy(AVDictionary **dst, AVDictionary *src, int flags); /** - * Free all the memory allocated for an AVMetadata struct. + * Free all the memory allocated for an AVDictionary struct. + */ +attribute_deprecated void av_metadata_free(AVDictionary **m); +/** + * @} */ -void av_metadata_free(AVMetadata **m); +#endif /* packet functions */ @@ -242,20 +247,21 @@ typedef struct AVProbeData { #define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer typedef struct AVFormatParameters { - AVRational time_base; - int sample_rate; - int channels; - int width; - int height; - enum PixelFormat pix_fmt; - int channel; /**< Used to select DV channel. */ - const char *standard; /**< TV standard, NTSC, PAL, SECAM */ - unsigned int mpeg2ts_raw:1; /**< Force raw MPEG-2 transport stream output, if possible. */ - unsigned int mpeg2ts_compute_pcr:1; /**< Compute exact PCR for each transport - stream packet (only meaningful if - mpeg2ts_raw is TRUE). */ - unsigned int initial_pause:1; /**< Do not begin to play the stream - immediately (RTSP only). */ +#if FF_API_FORMAT_PARAMETERS + attribute_deprecated AVRational time_base; + attribute_deprecated int sample_rate; + attribute_deprecated int channels; + attribute_deprecated int width; + attribute_deprecated int height; + attribute_deprecated enum PixelFormat pix_fmt; + attribute_deprecated int channel; /**< Used to select DV channel. */ + attribute_deprecated const char *standard; /**< deprecated, use demuxer-specific options instead. */ + attribute_deprecated unsigned int mpeg2ts_raw:1; /**< deprecated, use mpegtsraw demuxer */ + /**< deprecated, use mpegtsraw demuxer-specific options instead */ + attribute_deprecated unsigned int mpeg2ts_compute_pcr:1; + attribute_deprecated unsigned int initial_pause:1; /**< Do not begin to play the stream + immediately (RTSP only). */ +#endif unsigned int prealloced_context:1; #if FF_API_PARAMETERS_CODEC_ID attribute_deprecated enum CodecID video_codec_id; @@ -276,6 +282,11 @@ typedef struct AVFormatParameters { #define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */ #define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */ #define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ +#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fallback to binary search via read_timestamp */ +#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fallback to generic search */ +#define AVFMT_TS_NONSTRICT 0x8000 /**< Format does not require strictly + increasing timestamps, but they must + still be monotonic */ typedef struct AVOutputFormat { const char *name; @@ -588,7 +599,7 @@ typedef struct AVStream { */ AVRational sample_aspect_ratio; - AVMetadata *metadata; + AVDictionary *metadata; /* Intended mostly for av_read_frame() support. Not supposed to be used by */ /* external applications; try to use something else if at all possible. */ @@ -630,6 +641,13 @@ typedef struct AVStream { int codec_info_nb_frames; /** + * Stream Identifier + * This is the MPEG-TS stream identifier +1 + * 0 means unknown + */ + int stream_identifier; + + /** * Stream informations used internally by av_find_stream_info() */ #define MAX_STD_TIMEBASES (60*12+5) @@ -666,7 +684,11 @@ typedef struct AVProgram { enum AVDiscard discard; ///< selects which program to discard and which to feed to the caller unsigned int *stream_index; unsigned int nb_stream_indexes; - AVMetadata *metadata; + AVDictionary *metadata; + + int program_num; + int pmt_pid; + int pcr_pid; } AVProgram; #define AVFMTCTX_NOHEADER 0x0001 /**< signal that no header is present @@ -679,7 +701,7 @@ typedef struct AVChapter { #if FF_API_OLD_METADATA attribute_deprecated char *title; ///< chapter title #endif - AVMetadata *metadata; + AVDictionary *metadata; } AVChapter; #if FF_API_MAX_STREAMS @@ -789,10 +811,13 @@ typedef struct AVFormatContext { #define AVFMT_FLAG_IGNDTS 0x0008 ///< Ignore DTS on frames that contain both DTS & PTS #define AVFMT_FLAG_NOFILLIN 0x0010 ///< Do not infer any values from other values, just return what is stored in the container #define AVFMT_FLAG_NOPARSE 0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled -#define AVFMT_FLAG_RTP_HINT 0x0040 ///< Add RTP hinting to the output file +#if FF_API_FLAG_RTP_HINT +#define AVFMT_FLAG_RTP_HINT 0x0040 ///< Deprecated, use the -movflags rtphint muxer specific AVOption instead +#endif +#define AVFMT_FLAG_MP4A_LATM 0x0080 ///< Enable RTP MP4A-LATM payload #define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) #define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted) - +#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Dont merge side data but keep it seperate. int loop_input; /** @@ -868,7 +893,7 @@ typedef struct AVFormatContext { struct AVPacketList *packet_buffer_end; - AVMetadata *metadata; + AVDictionary *metadata; /** * Remaining size available for raw_packet_buffer, in bytes. @@ -885,6 +910,17 @@ typedef struct AVFormatContext { * - decoding: Unused. */ int64_t start_time_realtime; + + /** + * decoding: number of frames used to probe fps + */ + int fps_probe_size; + + /** + * Transport stream id. + * This will be moved into demuxer private options. Thus no API/ABI compatibility + */ + int ts_id; } AVFormatContext; typedef struct AVPacketList { @@ -1138,12 +1174,34 @@ int av_demuxer_open(AVFormatContext *ic, AVFormatParameters *ap); */ AVFormatContext *avformat_alloc_context(void); +#if FF_API_ALLOC_OUTPUT_CONTEXT /** - * Allocate an AVFormatContext. - * avformat_free_context() can be used to free the context and everything - * allocated by the framework within it. + * @deprecated deprecated in favor of avformat_alloc_output_context2() */ -AVFormatContext *avformat_alloc_output_context(const char *format, AVOutputFormat *oformat, const char *filename); +attribute_deprecated +AVFormatContext *avformat_alloc_output_context(const char *format, + AVOutputFormat *oformat, + const char *filename); +#endif + +/** + * Allocate an AVFormatContext for an output format. + * avformat_free_context() can be used to free the context and + * everything allocated by the framework within it. + * + * @param *ctx is set to the created format context, or to NULL in + * case of failure + * @param oformat format to use for allocating the context, if NULL + * format_name and filename are used instead + * @param format_name the name of output format to use for allocating the + * context, if NULL filename is used instead + * @param filename the name of the filename to use for allocating the + * context, may be NULL + * @return >= 0 in case of success, a negative AVERROR code in case of + * failure + */ +int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, + const char *format_name, const char *filename); /** * Read packets of a media file to get stream information. This @@ -1493,6 +1551,9 @@ int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, int av_write_trailer(AVFormatContext *s); #if FF_API_DUMP_FORMAT +/** + * @deprecated Deprecated in favor of av_dump_format(). + */ attribute_deprecated void dump_format(AVFormatContext *ic, int index, const char *url, diff --git a/libavformat/avidec.c b/libavformat/avidec.c index 39686491e2..d3ae8bee73 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -19,13 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -//#define DEBUG -//#define DEBUG_SEEK - #include <strings.h> #include "libavutil/intreadwrite.h" #include "libavutil/bswap.h" #include "libavutil/opt.h" +#include "libavutil/dict.h" #include "avformat.h" #include "avi.h" #include "dv.h" @@ -159,10 +157,8 @@ static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){ int64_t last_pos= -1; int64_t filesize= avio_size(s->pb); -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_ERROR, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%16"PRIX64"\n", - longs_pre_entry,index_type, entries_in_use, chunk_id, base); -#endif + av_dlog(s, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%16"PRIX64"\n", + longs_pre_entry,index_type, entries_in_use, chunk_id, base); if(stream_id >= s->nb_streams || stream_id < 0) return -1; @@ -280,8 +276,8 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t AV_WL32(key, tag); - return av_metadata_set2(st ? &st->metadata : &s->metadata, key, value, - AV_METADATA_DONT_STRDUP_VAL); + return av_dict_set(st ? &st->metadata : &s->metadata, key, value, + AV_DICT_DONT_STRDUP_VAL); } static void avi_read_info(AVFormatContext *s, uint64_t end) @@ -296,7 +292,7 @@ static void avi_read_info(AVFormatContext *s, uint64_t end) static const char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -static void avi_metadata_creation_time(AVMetadata **metadata, char *date) +static void avi_metadata_creation_time(AVDictionary **metadata, char *date) { char month[4], time[9], buffer[64]; int i, day, year; @@ -307,11 +303,11 @@ static void avi_metadata_creation_time(AVMetadata **metadata, char *date) if (!strcasecmp(month, months[i])) { snprintf(buffer, sizeof(buffer), "%.4d-%.2d-%.2d %s", year, i+1, day, time); - av_metadata_set2(metadata, "creation_time", buffer, 0); + av_dict_set(metadata, "creation_time", buffer, 0); } } else if (date[4] == '/' && date[7] == '/') { date[4] = date[7] = '-'; - av_metadata_set2(metadata, "creation_time", date, 0); + av_dict_set(metadata, "creation_time", date, 0); } } @@ -339,7 +335,7 @@ static void avi_read_nikon(AVFormatContext *s, uint64_t end) break; } if (name) - av_metadata_set2(&s->metadata, name, buffer, 0); + av_dict_set(&s->metadata, name, buffer, 0); avio_skip(s->pb, size); } break; @@ -792,7 +788,7 @@ static int read_gab2_sub(AVStream *st, AVPacket *pkt) { ret = avio_get_str16le(pb, desc_len, desc, sizeof(desc)); avio_skip(pb, desc_len - ret); if (*desc) - av_metadata_set2(&st->metadata, "title", desc, 0); + av_dict_set(&st->metadata, "title", desc, 0); avio_rl16(pb); /* flags? */ avio_rl32(pb); /* data size */ @@ -1178,10 +1174,8 @@ static int avi_read_idx1(AVFormatContext *s, int size) flags = avio_rl32(pb); pos = avio_rl32(pb); len = avio_rl32(pb); -#if defined(DEBUG_SEEK) - av_log(s, AV_LOG_DEBUG, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/", - i, tag, flags, pos, len); -#endif + av_dlog(s, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/", + i, tag, flags, pos, len); if(i==0 && pos > avi->movi_list) avi->movi_list= 0; //FIXME better check pos += avi->movi_list; @@ -1250,22 +1244,18 @@ static int avi_load_index(AVFormatContext *s) if (avio_seek(pb, avi->movi_end, SEEK_SET) < 0) goto the_end; // maybe truncated file -#ifdef DEBUG_SEEK - printf("movi_end=0x%"PRIx64"\n", avi->movi_end); -#endif + av_dlog(s, "movi_end=0x%"PRIx64"\n", avi->movi_end); for(;;) { if (url_feof(pb)) break; tag = avio_rl32(pb); size = avio_rl32(pb); -#ifdef DEBUG_SEEK - printf("tag=%c%c%c%c size=0x%x\n", - tag & 0xff, - (tag >> 8) & 0xff, - (tag >> 16) & 0xff, - (tag >> 24) & 0xff, - size); -#endif + av_dlog(s, "tag=%c%c%c%c size=0x%x\n", + tag & 0xff, + (tag >> 8) & 0xff, + (tag >> 16) & 0xff, + (tag >> 24) & 0xff, + size); switch(tag) { case MKTAG('i', 'd', 'x', '1'): if (avi_read_idx1(s, size) < 0) diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 9f488d9600..8a53bb53d3 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -23,6 +23,7 @@ #include "avio_internal.h" #include "riff.h" #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" /* * TODO: @@ -157,7 +158,7 @@ static int avi_write_header(AVFormatContext *s) int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; AVCodecContext *stream, *video_enc; int64_t list1, list2, strh, strf; - AVMetadataTag *t = NULL; + AVDictionaryEntry *t = NULL; if (s->nb_streams > AVI_MAX_STREAM_COUNT) { av_log(s, AV_LOG_ERROR, "AVI does not support >%d streams\n", @@ -297,7 +298,7 @@ static int avi_write_header(AVFormatContext *s) return -1; } ff_end_tag(pb, strf); - if ((t = av_metadata_get(s->streams[i]->metadata, "title", NULL, 0))) { + if ((t = av_dict_get(s->streams[i]->metadata, "title", NULL, 0))) { avi_write_info_tag(s->pb, "strn", t->value); t = NULL; } @@ -379,7 +380,7 @@ static int avi_write_header(AVFormatContext *s) ffio_wfourcc(pb, "INFO"); ff_metadata_conv(&s->metadata, ff_avi_metadata_conv, NULL); for (i = 0; *ff_avi_tags[i]; i++) { - if ((t = av_metadata_get(s->metadata, ff_avi_tags[i], NULL, AV_METADATA_MATCH_CASE))) + if ((t = av_dict_get(s->metadata, ff_avi_tags[i], NULL, AV_DICT_MATCH_CASE))) avi_write_info_tag(s->pb, t->key, t->value); } ff_end_tag(pb, list2); diff --git a/libavformat/avio.c b/libavformat/avio.c index 16f8c2f2dd..80644795d5 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -62,11 +62,11 @@ URLProtocol *av_protocol_next(URLProtocol *p) const char *avio_enum_protocols(void **opaque, int output) { - URLProtocol **p = opaque; - *p = *p ? (*p)->next : first_protocol; - if (!*p) return NULL; - if ((output && (*p)->url_write) || (!output && (*p)->url_read)) - return (*p)->name; + URLProtocol *p = *opaque; + p = p ? p->next : first_protocol; + if (!p) return NULL; + if ((output && p->url_write) || (!output && p->url_read)) + return p->name; return avio_enum_protocols(opaque, output); } diff --git a/libavformat/avio.h b/libavformat/avio.h index 9d805822d4..5885349ca7 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -391,6 +391,7 @@ attribute_deprecated int av_register_protocol(URLProtocol *protocol); * freed with av_free(). * * @param buffer Memory block for input/output operations via AVIOContext. + * The buffer must be allocated with av_malloc() and friends. * @param buffer_size The buffer size is very important for performance. * For protocols with fixed blocksize it should be set to this blocksize. * For others a typical size is a cache page, e.g. 4kb. diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index 92528f2d18..4c80163d31 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -98,4 +98,4 @@ int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size); */ int ffio_fdopen(AVIOContext **s, URLContext *h); -#endif // AVFORMAT_AVIO_INTERNAL_H +#endif /* AVFORMAT_AVIO_INTERNAL_H */ diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 456205bc76..c6cea6adfb 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -115,6 +115,8 @@ AVIOContext *avio_alloc_context( int64_t (*seek)(void *opaque, int64_t offset, int whence)) { AVIOContext *s = av_mallocz(sizeof(AVIOContext)); + if (!s) + return NULL; ffio_init_context(s, buffer, buffer_size, write_flag, opaque, read_packet, write_packet, seek); return s; diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index ea9a3c17ae..b24ff1d023 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -29,6 +29,7 @@ #include "riff.h" #include "isom.h" #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "caf.h" typedef struct { @@ -187,7 +188,7 @@ static void read_info_chunk(AVFormatContext *s, int64_t size) char value[1024]; get_strz(pb, key, sizeof(key)); get_strz(pb, value, sizeof(value)); - av_metadata_set2(&s->metadata, key, value, 0); + av_dict_set(&s->metadata, key, value, 0); } } diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index 0f33c6b592..13636f30ee 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -134,7 +134,11 @@ static int caf_write_header(AVFormatContext *s) avio_wb32(pb, enc->channels); //< mChannelsPerFrame avio_wb32(pb, enc->bits_per_coded_sample); //< mBitsPerChannel - ff_mov_write_chan(s, enc->channel_layout, "chan"); + if (enc->channel_layout) { + ffio_wfourcc(pb, "chan"); + avio_wb64(pb, 12); + ff_mov_write_chan(pb, enc->channel_layout); + } ffio_wfourcc(pb, "data"); //< Audio Data chunk caf->data = avio_tell(pb); diff --git a/libavformat/cavsvideodec.c b/libavformat/cavsvideodec.c index 6db9ad9fcf..4a399a26d1 100644 --- a/libavformat/cavsvideodec.c +++ b/libavformat/cavsvideodec.c @@ -65,13 +65,4 @@ static int cavsvideo_probe(AVProbeData *p) return 0; } -AVInputFormat ff_cavsvideo_demuxer = { - "cavsvideo", - NULL_IF_CONFIG_SMALL("raw Chinese AVS video"), - 0, - cavsvideo_probe, - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, - .value = CODEC_ID_CAVS, -}; +FF_DEF_RAWVIDEO_DEMUXER(cavsvideo, "raw Chinese AVS video", cavsvideo_probe, NULL, CODEC_ID_CAVS) diff --git a/libavformat/crypto.c b/libavformat/crypto.c index c83bf92895..d52a503e38 100644 --- a/libavformat/crypto.c +++ b/libavformat/crypto.c @@ -97,8 +97,8 @@ static int crypto_open(URLContext *h, const char *uri, int flags) return 0; err: - av_free(c->key); - av_free(c->iv); + av_freep(&c->key); + av_freep(&c->iv); return ret; } diff --git a/libavformat/diracdec.c b/libavformat/diracdec.c index 6c6896163b..6afda533dc 100644 --- a/libavformat/diracdec.c +++ b/libavformat/diracdec.c @@ -31,13 +31,4 @@ static int dirac_probe(AVProbeData *p) return 0; } -AVInputFormat ff_dirac_demuxer = { - "dirac", - NULL_IF_CONFIG_SMALL("raw Dirac"), - 0, - dirac_probe, - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, - .value = CODEC_ID_DIRAC, -}; +FF_DEF_RAWVIDEO_DEMUXER(dirac, "raw Dirac", dirac_probe, NULL, CODEC_ID_DIRAC) diff --git a/libavformat/dnxhddec.c b/libavformat/dnxhddec.c index 035e1c4b30..f89782a880 100644 --- a/libavformat/dnxhddec.c +++ b/libavformat/dnxhddec.c @@ -42,13 +42,4 @@ static int dnxhd_probe(AVProbeData *p) return AVPROBE_SCORE_MAX; } -AVInputFormat ff_dnxhd_demuxer = { - "dnxhd", - NULL_IF_CONFIG_SMALL("raw DNxHD (SMPTE VC-3)"), - 0, - dnxhd_probe, - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, - .value = CODEC_ID_DNXHD, -}; +FF_DEF_RAWVIDEO_DEMUXER(dnxhd, "raw DNxHD (SMPTE VC-3)", dnxhd_probe, NULL, CODEC_ID_DNXHD) diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c index 604e75183c..e776d0c384 100644 --- a/libavformat/ffmdec.c +++ b/libavformat/ffmdec.c @@ -163,8 +163,6 @@ static int ffm_read_data(AVFormatContext *s, return size1 - size; } -//#define DEBUG_SEEK - /* ensure that acutal seeking happens between FFM_PACKET_SIZE and file_size - FFM_PACKET_SIZE */ static void ffm_seek1(AVFormatContext *s, int64_t pos1) @@ -175,9 +173,7 @@ static void ffm_seek1(AVFormatContext *s, int64_t pos1) pos = FFMIN(pos1, ffm->file_size - FFM_PACKET_SIZE); pos = FFMAX(pos, FFM_PACKET_SIZE); -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_DEBUG, "seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos); -#endif + av_dlog(s, "seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos); avio_seek(pb, pos, SEEK_SET); } @@ -189,9 +185,7 @@ static int64_t get_dts(AVFormatContext *s, int64_t pos) ffm_seek1(s, pos); avio_skip(pb, 4); dts = avio_rb64(pb); -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_DEBUG, "dts=%0.6f\n", dts / 1000000.0); -#endif + av_dlog(s, "dts=%0.6f\n", dts / 1000000.0); return dts; } @@ -464,9 +458,7 @@ static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, in int64_t pts_min, pts_max, pts; double pos1; -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_DEBUG, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0); -#endif + av_dlog(s, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0); /* find the position using linear interpolation (better than dichotomy in typical cases) */ pos_min = FFM_PACKET_SIZE; diff --git a/libavformat/ffmeta.h b/libavformat/ffmeta.h index f96dbb2efb..ae8778d614 100644 --- a/libavformat/ffmeta.h +++ b/libavformat/ffmeta.h @@ -19,11 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVFORMAT_META_H -#define AVFORMAT_META_H +#ifndef AVFORMAT_FFMETA_H +#define AVFORMAT_FFMETA_H #define ID_STRING ";FFMETADATA" #define ID_CHAPTER "[CHAPTER]" #define ID_STREAM "[STREAM]" -#endif /* AVFORMAT_META_H */ +#endif /* AVFORMAT_FFMETA_H */ diff --git a/libavformat/ffmetadec.c b/libavformat/ffmetadec.c index a8bffa09af..0063e6eafa 100644 --- a/libavformat/ffmetadec.c +++ b/libavformat/ffmetadec.c @@ -22,6 +22,7 @@ #include "avformat.h" #include "ffmeta.h" #include "internal.h" +#include "libavutil/dict.h" static int probe(AVProbeData *p) { @@ -93,7 +94,7 @@ static uint8_t *unescape(uint8_t *buf, int size) return ret; } -static int read_tag(uint8_t *line, AVMetadata **m) +static int read_tag(uint8_t *line, AVDictionary **m) { uint8_t *key, *value, *p = line; @@ -117,13 +118,13 @@ static int read_tag(uint8_t *line, AVMetadata **m) return AVERROR(ENOMEM); } - av_metadata_set2(m, key, value, AV_METADATA_DONT_STRDUP_KEY | AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(m, key, value, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); return 0; } static int read_header(AVFormatContext *s, AVFormatParameters *ap) { - AVMetadata **m = &s->metadata; + AVDictionary **m = &s->metadata; uint8_t line[1024]; while(!url_feof(s->pb)) { diff --git a/libavformat/ffmetaenc.c b/libavformat/ffmetaenc.c index 596185b70c..200c9940a4 100644 --- a/libavformat/ffmetaenc.c +++ b/libavformat/ffmetaenc.c @@ -23,6 +23,7 @@ #include "avformat.h" #include "ffmeta.h" +#include "libavutil/dict.h" static void write_escape_str(AVIOContext *s, const uint8_t *str) @@ -37,10 +38,10 @@ static void write_escape_str(AVIOContext *s, const uint8_t *str) } } -static void write_tags(AVIOContext *s, AVMetadata *m) +static void write_tags(AVIOContext *s, AVDictionary *m) { - AVMetadataTag *t = NULL; - while ((t = av_metadata_get(m, "", t, AV_METADATA_IGNORE_SUFFIX))) { + AVDictionaryEntry *t = NULL; + while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) { write_escape_str(s, t->key); avio_w8(s, '='); write_escape_str(s, t->value); diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index 1674527816..24e0287ef8 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -22,7 +22,6 @@ #include "libavcodec/flac.h" #include "avformat.h" #include "flacenc.h" -#include "metadata.h" #include "vorbiscomment.h" #include "libavcodec/bytestream.h" @@ -39,7 +38,7 @@ static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_byte return 0; } -static int flac_write_block_comment(AVIOContext *pb, AVMetadata **m, +static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m, int last_block, int bitexact) { const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 44d21683ba..4fb562f4e2 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -25,6 +25,7 @@ */ #include "libavutil/avstring.h" +#include "libavutil/dict.h" #include "libavcodec/bytestream.h" #include "libavcodec/mpeg4audio.h" #include "avformat.h" @@ -259,17 +260,17 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst if(amf_type == AMF_DATA_TYPE_BOOL) { av_strlcpy(str_val, num_val > 0 ? "true" : "false", sizeof(str_val)); - av_metadata_set2(&s->metadata, key, str_val, 0); + av_dict_set(&s->metadata, key, str_val, 0); } else if(amf_type == AMF_DATA_TYPE_NUMBER) { snprintf(str_val, sizeof(str_val), "%.f", num_val); - av_metadata_set2(&s->metadata, key, str_val, 0); + av_dict_set(&s->metadata, key, str_val, 0); if(!strcmp(key, "duration")) s->duration = num_val * AV_TIME_BASE; else if(!strcmp(key, "videodatarate") && vcodec && 0 <= (int)(num_val * 1024.0)) vcodec->bit_rate = num_val * 1024.0; else if(!strcmp(key, "audiodatarate") && acodec && 0 <= (int)(num_val * 1024.0)) acodec->bit_rate = num_val * 1024.0; } else if (amf_type == AMF_DATA_TYPE_STRING) - av_metadata_set2(&s->metadata, key, str_val, 0); + av_dict_set(&s->metadata, key, str_val, 0); } return 0; @@ -375,7 +376,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) size = avio_rb24(s->pb); dts = avio_rb24(s->pb); dts |= avio_r8(s->pb) << 24; -// av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, dts:%d\n", type, size, dts); + av_dlog(s, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts); if (url_feof(s->pb)) return AVERROR_EOF; avio_skip(s->pb, 3); /* stream id, always 0 */ @@ -421,7 +422,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) st= create_stream(s, is_audio); s->ctx_flags &= ~AVFMTCTX_NOHEADER; } -// av_log(s, AV_LOG_DEBUG, "%d %X %d \n", is_audio, flags, st->discard); + av_dlog(s, "%d %X %d \n", is_audio, flags, st->discard); if( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || is_audio)) ||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && !is_audio)) || st->discard >= AVDISCARD_ALL diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 3e933ce922..cea0d02e3c 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -25,6 +25,7 @@ #include "internal.h" #include "avc.h" #include "metadata.h" +#include "libavutil/dict.h" #undef NDEBUG #include <assert.h> @@ -179,7 +180,7 @@ static int flv_write_header(AVFormatContext *s) int i; double framerate = 0.0; int metadata_size_pos, data_size; - AVMetadataTag *tag = NULL; + AVDictionaryEntry *tag = NULL; for(i=0; i<s->nb_streams; i++){ AVCodecContext *enc = s->streams[i]->codec; @@ -276,7 +277,7 @@ static int flv_write_header(AVFormatContext *s) put_amf_double(pb, audio_enc->codec_tag); } - while ((tag = av_metadata_get(s->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX))) { + while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { put_amf_string(pb, tag->key); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, tag->value); @@ -440,7 +441,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) av_free(data); - return 0; + return pb->error; } AVOutputFormat ff_flv_muxer = { diff --git a/libavformat/gif.c b/libavformat/gif.c index f5f8147e4f..0960705cf3 100644 --- a/libavformat/gif.c +++ b/libavformat/gif.c @@ -295,9 +295,7 @@ static int gif_write_video(AVFormatContext *s, AVCodecContext *enc, const uint8_t *buf, int size) { AVIOContext *pb = s->pb; - GIFContext *gif = s->priv_data; int jiffies; - int64_t delay; /* graphic control extension block */ avio_w8(pb, 0x21); @@ -307,8 +305,6 @@ static int gif_write_video(AVFormatContext *s, /* 1 jiffy is 1/70 s */ /* the delay_time field indicates the number of jiffies - 1 */ - delay = gif->file_time - gif->time; - /* XXX: should use delay, in order to be more accurate */ /* instead of using the same rounded value each time */ /* XXX: don't even remember if I really use it for now */ diff --git a/libavformat/h261dec.c b/libavformat/h261dec.c index 1478ed663f..354a7c78c1 100644 --- a/libavformat/h261dec.c +++ b/libavformat/h261dec.c @@ -62,14 +62,4 @@ static int h261_probe(AVProbeData *p) return 0; } -AVInputFormat ff_h261_demuxer = { - "h261", - NULL_IF_CONFIG_SMALL("raw H.261"), - 0, - h261_probe, - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, - .extensions = "h261", - .value = CODEC_ID_H261, -}; +FF_DEF_RAWVIDEO_DEMUXER(h261, "raw H.261", h261_probe, "h261", CODEC_ID_H261) diff --git a/libavformat/h263dec.c b/libavformat/h263dec.c index 634923d885..b07e9782b8 100644 --- a/libavformat/h263dec.c +++ b/libavformat/h263dec.c @@ -64,14 +64,4 @@ static int h263_probe(AVProbeData *p) return 0; } -AVInputFormat ff_h263_demuxer = { - "h263", - NULL_IF_CONFIG_SMALL("raw H.263"), - 0, - h263_probe, - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, -// .extensions = "h263", //FIXME remove after writing mpeg4_probe - .value = CODEC_ID_H263, -}; +FF_DEF_RAWVIDEO_DEMUXER(h263, "raw H.263", h263_probe, NULL, CODEC_ID_H263) diff --git a/libavformat/h264dec.c b/libavformat/h264dec.c index cec8f85275..e7c6d70deb 100644 --- a/libavformat/h264dec.c +++ b/libavformat/h264dec.c @@ -67,14 +67,4 @@ static int h264_probe(AVProbeData *p) return 0; } -AVInputFormat ff_h264_demuxer = { - "h264", - NULL_IF_CONFIG_SMALL("raw H.264 video format"), - 0, - h264_probe, - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, - .extensions = "h26l,h264,264", //FIXME remove after writing mpeg4_probe - .value = CODEC_ID_H264, -}; +FF_DEF_RAWVIDEO_DEMUXER(h264 , "raw H.264 video format", h264_probe, "h26l,h264,264", CODEC_ID_H264) diff --git a/libavformat/id3v1.c b/libavformat/id3v1.c index 37d46956ef..2d1e806920 100644 --- a/libavformat/id3v1.c +++ b/libavformat/id3v1.c @@ -21,6 +21,7 @@ #include "id3v1.h" #include "libavcodec/avcodec.h" +#include "libavutil/dict.h" const char * const ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1] = { [0] = "Blues", @@ -191,7 +192,7 @@ static void get_string(AVFormatContext *s, const char *key, *q = '\0'; if (*str) - av_metadata_set2(&s->metadata, key, str, 0); + av_dict_set(&s->metadata, key, str, 0); } /** @@ -215,11 +216,11 @@ static int parse_tag(AVFormatContext *s, const uint8_t *buf) get_string(s, "comment", buf + 97, 30); if (buf[125] == 0 && buf[126] != 0) { snprintf(str, sizeof(str), "%d", buf[126]); - av_metadata_set2(&s->metadata, "track", str, 0); + av_dict_set(&s->metadata, "track", str, 0); } genre = buf[127]; if (genre <= ID3v1_GENRE_MAX) - av_metadata_set2(&s->metadata, "genre", ff_id3v1_genre_str[genre], 0); + av_dict_set(&s->metadata, "genre", ff_id3v1_genre_str[genre], 0); return 0; } diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 95353276b5..930ab5c870 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -1,5 +1,4 @@ /* - * ID3v2 header parser * Copyright (c) 2003 Fabrice Bellard * * This file is part of FFmpeg. @@ -19,11 +18,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/** + * @file + * ID3v2 header parser + * + * Specifications available at: + * http://id3.org/Developer_Information + */ + #include "id3v2.h" #include "id3v1.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" -#include "metadata.h" +#include "libavutil/dict.h" #include "avio_internal.h" int ff_id3v2_match(const uint8_t *buf, const char * magic) @@ -133,7 +140,7 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const cha val = dst; if (val) - av_metadata_set2(&s->metadata, key, val, AV_METADATA_DONT_OVERWRITE); + av_dict_set(&s->metadata, key, val, AV_DICT_DONT_OVERWRITE); } static int is_number(const char *str) @@ -142,44 +149,44 @@ static int is_number(const char *str) return !*str; } -static AVMetadataTag* get_date_tag(AVMetadata *m, const char *tag) +static AVDictionaryEntry* get_date_tag(AVDictionary *m, const char *tag) { - AVMetadataTag *t; - if ((t = av_metadata_get(m, tag, NULL, AV_METADATA_MATCH_CASE)) && + AVDictionaryEntry *t; + if ((t = av_dict_get(m, tag, NULL, AV_DICT_MATCH_CASE)) && strlen(t->value) == 4 && is_number(t->value)) return t; return NULL; } -static void merge_date(AVMetadata **m) +static void merge_date(AVDictionary **m) { - AVMetadataTag *t; + AVDictionaryEntry *t; char date[17] = {0}; // YYYY-MM-DD hh:mm if (!(t = get_date_tag(*m, "TYER")) && !(t = get_date_tag(*m, "TYE"))) return; av_strlcpy(date, t->value, 5); - av_metadata_set2(m, "TYER", NULL, 0); - av_metadata_set2(m, "TYE", NULL, 0); + av_dict_set(m, "TYER", NULL, 0); + av_dict_set(m, "TYE", NULL, 0); if (!(t = get_date_tag(*m, "TDAT")) && !(t = get_date_tag(*m, "TDA"))) goto finish; snprintf(date + 4, sizeof(date) - 4, "-%.2s-%.2s", t->value + 2, t->value); - av_metadata_set2(m, "TDAT", NULL, 0); - av_metadata_set2(m, "TDA", NULL, 0); + av_dict_set(m, "TDAT", NULL, 0); + av_dict_set(m, "TDA", NULL, 0); if (!(t = get_date_tag(*m, "TIME")) && !(t = get_date_tag(*m, "TIM"))) goto finish; snprintf(date + 10, sizeof(date) - 10, " %.2s:%.2s", t->value, t->value + 2); - av_metadata_set2(m, "TIME", NULL, 0); - av_metadata_set2(m, "TIM", NULL, 0); + av_dict_set(m, "TIME", NULL, 0); + av_dict_set(m, "TIM", NULL, 0); finish: if (date[0]) - av_metadata_set2(m, "date", date, 0); + av_dict_set(m, "date", date, 0); } static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags) @@ -221,7 +228,7 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t avio_skip(s->pb, get_size(s->pb, 4)); while (len >= taghdrlen) { - unsigned int tflags; + unsigned int tflags = 0; int tunsync = 0; if (isv34) { @@ -238,7 +245,7 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t tag[3] = 0; tlen = avio_rb24(s->pb); } - if (tlen > (1<<28)) + if (tlen > (1<<28) || !tlen) break; len -= taghdrlen + tlen; @@ -248,6 +255,8 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t next = avio_tell(s->pb) + tlen; if (tflags & ID3v2_FLAG_DATALEN) { + if (tlen < 4) + break; avio_rb32(s->pb); tlen -= 4; } @@ -259,6 +268,10 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t if (unsync || tunsync) { int i, j; av_fast_malloc(&buffer, &buffer_size, tlen); + if (!buffer) { + av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", tlen); + goto seek; + } for (i = 0, j = 0; i < tlen; i++, j++) { buffer[j] = avio_r8(s->pb); if (j > 0 && !buffer[j] && buffer[j - 1] == 0xff) { @@ -279,6 +292,7 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t break; } /* Skip to end of tag */ +seek: avio_seek(s->pb, next, SEEK_SET); } diff --git a/libavformat/iff.c b/libavformat/iff.c index da4e858501..db988a6ecd 100644 --- a/libavformat/iff.c +++ b/libavformat/iff.c @@ -1,5 +1,4 @@ /* - * IFF (.iff) file demuxer * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net> * Copyright (c) 2010 Peter Ross <pross@xvid.org> * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com> @@ -31,6 +30,7 @@ #include "libavcodec/bytestream.h" #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #define ID_8SVX MKTAG('8','S','V','X') @@ -60,8 +60,6 @@ #define RIGHT 4 #define STEREO 6 -#define PACKET_SIZE 1024 - /** * This number of bytes if added at the beginning of each AVPacket * which contain additional information about video properties @@ -88,7 +86,8 @@ typedef struct { uint32_t body_size; uint32_t sent_bytes; uint32_t audio_frame_count; - unsigned compression; ///< delta compression method used + svx8_compression_type svx8_compression; + bitmap_compression_type bitmap_compression; ///< delta compression method used unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM) unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise) unsigned flags; ///< 1 for EHB, 0 is no extra half darkening @@ -96,19 +95,6 @@ typedef struct { unsigned masking; ///< masking method used } IffDemuxContext; - -static void interleave_stereo(const uint8_t *src, uint8_t *dest, int size) -{ - uint8_t *end = dest + size; - size = size>>1; - - while(dest < end) { - *dest++ = *src; - *dest++ = *(src+size); - src++; - } -} - /* Metadata string read */ static int get_metadata(AVFormatContext *s, const char *const tag, @@ -124,7 +110,7 @@ static int get_metadata(AVFormatContext *s, return AVERROR(EIO); } buf[data_size] = 0; - av_metadata_set2(&s->metadata, tag, buf, AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(&s->metadata, tag, buf, AV_DICT_DONT_STRDUP_VAL); return 0; } @@ -146,7 +132,6 @@ static int iff_read_header(AVFormatContext *s, AVStream *st; uint8_t *buf; uint32_t chunk_id, data_size; - int compression = -1; uint32_t screenmode = 0; unsigned transparency = 0; unsigned masking = 0; // no mask @@ -178,7 +163,7 @@ static int iff_read_header(AVFormatContext *s, st->codec->sample_rate = avio_rb16(pb); if (data_size >= 16) { avio_skip(pb, 1); - compression = avio_r8(pb); + iff->svx8_compression = avio_r8(pb); } break; @@ -209,6 +194,7 @@ static int iff_read_header(AVFormatContext *s, break; case ID_BMHD: + iff->bitmap_compression = -1; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; if (data_size <= 8) return AVERROR_INVALIDDATA; @@ -219,7 +205,7 @@ static int iff_read_header(AVFormatContext *s, if (data_size >= 10) masking = avio_r8(pb); if (data_size >= 11) - compression = avio_r8(pb); + iff->bitmap_compression = avio_r8(pb); if (data_size >= 14) { avio_skip(pb, 1); // padding transparency = avio_rb16(pb); @@ -231,21 +217,10 @@ static int iff_read_header(AVFormatContext *s, break; case ID_ANNO: - case ID_TEXT: - metadata_tag = "comment"; - break; - - case ID_AUTH: - metadata_tag = "artist"; - break; - - case ID_COPYRIGHT: - metadata_tag = "copyright"; - break; - - case ID_NAME: - metadata_tag = "title"; - break; + case ID_TEXT: metadata_tag = "comment"; break; + case ID_AUTH: metadata_tag = "artist"; break; + case ID_COPYRIGHT: metadata_tag = "copyright"; break; + case ID_NAME: metadata_tag = "title"; break; } if (metadata_tag) { @@ -263,9 +238,9 @@ static int iff_read_header(AVFormatContext *s, case AVMEDIA_TYPE_AUDIO: av_set_pts_info(st, 32, 1, st->codec->sample_rate); - switch(compression) { + switch (iff->svx8_compression) { case COMP_NONE: - st->codec->codec_id = CODEC_ID_PCM_S8; + st->codec->codec_id = CODEC_ID_8SVX_RAW; break; case COMP_FIB: st->codec->codec_id = CODEC_ID_8SVX_FIB; @@ -274,17 +249,17 @@ static int iff_read_header(AVFormatContext *s, st->codec->codec_id = CODEC_ID_8SVX_EXP; break; default: - av_log(s, AV_LOG_ERROR, "unknown compression method\n"); + av_log(s, AV_LOG_ERROR, + "Unknown SVX8 compression method '%d'\n", iff->svx8_compression); return -1; } - st->codec->bits_per_coded_sample = 8; + st->codec->bits_per_coded_sample = iff->svx8_compression == COMP_NONE ? 8 : 4; st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample; st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; break; case AVMEDIA_TYPE_VIDEO: - iff->compression = compression; iff->bpp = st->codec->bits_per_coded_sample; if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) { iff->ham = iff->bpp > 6 ? 6 : 4; @@ -302,14 +277,14 @@ static int iff_read_header(AVFormatContext *s, } buf = st->codec->extradata; bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE); - bytestream_put_byte(&buf, iff->compression); + bytestream_put_byte(&buf, iff->bitmap_compression); bytestream_put_byte(&buf, iff->bpp); bytestream_put_byte(&buf, iff->ham); bytestream_put_byte(&buf, iff->flags); bytestream_put_be16(&buf, iff->transparency); bytestream_put_byte(&buf, iff->masking); - switch (compression) { + switch (iff->bitmap_compression) { case BITMAP_RAW: st->codec->codec_id = CODEC_ID_IFF_ILBM; break; @@ -317,7 +292,8 @@ static int iff_read_header(AVFormatContext *s, st->codec->codec_id = CODEC_ID_IFF_BYTERUN1; break; default: - av_log(s, AV_LOG_ERROR, "unknown compression method\n"); + av_log(s, AV_LOG_ERROR, + "Unknown bitmap compression method '%d'\n", iff->bitmap_compression); return AVERROR_INVALIDDATA; } break; @@ -339,15 +315,8 @@ static int iff_read_packet(AVFormatContext *s, if(iff->sent_bytes >= iff->body_size) return AVERROR(EIO); - if(st->codec->channels == 2) { - uint8_t sample_buffer[PACKET_SIZE]; - - ret = avio_read(pb, sample_buffer, PACKET_SIZE); - if(av_new_packet(pkt, PACKET_SIZE) < 0) { - av_log(s, AV_LOG_ERROR, "cannot allocate packet\n"); - return AVERROR(ENOMEM); - } - interleave_stereo(sample_buffer, pkt->data, PACKET_SIZE); + if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + ret = av_get_packet(pb, pkt, iff->body_size); } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { uint8_t *buf; @@ -359,22 +328,14 @@ static int iff_read_packet(AVFormatContext *s, bytestream_put_be16(&buf, 2); ret = avio_read(pb, buf, iff->body_size); } else { - ret = av_get_packet(pb, pkt, PACKET_SIZE); + av_abort(); } if(iff->sent_bytes == 0) pkt->flags |= AV_PKT_FLAG_KEY; + iff->sent_bytes = iff->body_size; - if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - iff->sent_bytes += PACKET_SIZE; - } else { - iff->sent_bytes = iff->body_size; - } pkt->stream_index = 0; - if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - pkt->pts = iff->audio_frame_count; - iff->audio_frame_count += ret / st->codec->channels; - } return ret; } diff --git a/libavformat/img2.c b/libavformat/img2.c index 19292c39ec..11ebf12d43 100644 --- a/libavformat/img2.c +++ b/libavformat/img2.c @@ -22,12 +22,17 @@ #include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/parseutils.h" #include "avformat.h" #include "avio_internal.h" #include "internal.h" #include <strings.h> typedef struct { + const AVClass *class; /**< Class for private options. */ int img_first; int img_last; int img_number; @@ -35,6 +40,9 @@ typedef struct { int is_pipe; int split_planes; /**< use independent file for each Y, U, V plane */ char path[1024]; + char *pixel_format; /**< Set by a private option. */ + char *video_size; /**< Set by a private option. */ + char *framerate; /**< Set by a private option. */ } VideoData; typedef struct { @@ -77,6 +85,7 @@ static const IdStrMap img_tags[] = { { CODEC_ID_SUNRAST , "sunras"}, { CODEC_ID_JPEG2000 , "j2k"}, { CODEC_ID_JPEG2000 , "jp2"}, + { CODEC_ID_JPEG2000 , "jpc"}, { CODEC_ID_DPX , "dpx"}, { CODEC_ID_PICTOR , "pic"}, { CODEC_ID_NONE , NULL} @@ -201,8 +210,11 @@ enum CodecID av_guess_image2_codec(const char *filename){ static int read_header(AVFormatContext *s1, AVFormatParameters *ap) { VideoData *s = s1->priv_data; - int first_index, last_index; + int first_index, last_index, ret = 0; + int width = 0, height = 0; AVStream *st; + enum PixelFormat pix_fmt = PIX_FMT_NONE; + AVRational framerate; s1->ctx_flags |= AVFMTCTX_NOHEADER; @@ -211,6 +223,29 @@ static int read_header(AVFormatContext *s1, AVFormatParameters *ap) return AVERROR(ENOMEM); } + if (s->pixel_format && (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) { + av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", s->pixel_format); + return AVERROR(EINVAL); + } + if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) { + av_log(s, AV_LOG_ERROR, "Could not parse video size: %s.\n", s->video_size); + return ret; + } + if ((ret = av_parse_video_rate(&framerate, s->framerate)) < 0) { + av_log(s, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s->framerate); + return ret; + } +#if FF_API_FORMAT_PARAMETERS + if (ap->pix_fmt != PIX_FMT_NONE) + pix_fmt = ap->pix_fmt; + if (ap->width > 0) + width = ap->width; + if (ap->height > 0) + height = ap->height; + if (ap->time_base.num) + framerate = (AVRational){ap->time_base.den, ap->time_base.num}; +#endif + av_strlcpy(s->path, s1->filename, sizeof(s->path)); s->img_number = 0; s->img_count = 0; @@ -223,15 +258,11 @@ static int read_header(AVFormatContext *s1, AVFormatParameters *ap) st->need_parsing = AVSTREAM_PARSE_FULL; } - if (!ap->time_base.num) { - av_set_pts_info(st, 60, 1, 25); - } else { - av_set_pts_info(st, 60, ap->time_base.num, ap->time_base.den); - } + av_set_pts_info(st, 60, framerate.den, framerate.num); - if(ap->width && ap->height){ - st->codec->width = ap->width; - st->codec->height= ap->height; + if (width && height) { + st->codec->width = width; + st->codec->height = height; } if (!s->is_pipe) { @@ -257,8 +288,8 @@ static int read_header(AVFormatContext *s1, AVFormatParameters *ap) st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = av_str2id(img_tags, s->path); } - if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ap->pix_fmt != PIX_FMT_NONE) - st->codec->pix_fmt = ap->pix_fmt; + if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != PIX_FMT_NONE) + st->codec->pix_fmt = pix_fmt; return 0; } @@ -429,6 +460,22 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) #endif /* CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER */ +#define OFFSET(x) offsetof(VideoData, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "pixel_format", "", OFFSET(pixel_format), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "video_size", "", OFFSET(video_size), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "framerate", "", OFFSET(framerate), FF_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC }, + { NULL }, +}; + +static const AVClass img2_class = { + .class_name = "image2 demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + /* input */ #if CONFIG_IMAGE2_DEMUXER AVInputFormat ff_image2_demuxer = { @@ -439,6 +486,7 @@ AVInputFormat ff_image2_demuxer = { .read_header = read_header, .read_packet = read_packet, .flags = AVFMT_NOFILE, + .priv_class = &img2_class, }; #endif #if CONFIG_IMAGE2PIPE_DEMUXER @@ -448,6 +496,7 @@ AVInputFormat ff_image2pipe_demuxer = { .priv_data_size = sizeof(VideoData), .read_header = read_header, .read_packet = read_packet, + .priv_class = &img2_class, }; #endif diff --git a/libavformat/ingenientdec.c b/libavformat/ingenientdec.c index eb1e6f6521..4a7ff09dbe 100644 --- a/libavformat/ingenientdec.c +++ b/libavformat/ingenientdec.c @@ -61,11 +61,12 @@ static int ingenient_read_packet(AVFormatContext *s, AVPacket *pkt) AVInputFormat ff_ingenient_demuxer = { "ingenient", NULL_IF_CONFIG_SMALL("raw Ingenient MJPEG"), - 0, + sizeof(FFRawVideoDemuxerContext), NULL, ff_raw_video_read_header, ingenient_read_packet, .flags= AVFMT_GENERIC_INDEX, .extensions = "cgi", // FIXME .value = CODEC_ID_MJPEG, + .priv_class = &ff_rawvideo_demuxer_class, }; diff --git a/libavformat/internal.h b/libavformat/internal.h index d75e0676e5..64992dadfa 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -26,6 +26,12 @@ #define MAX_URL_SIZE 4096 +#ifdef DEBUG +# define hex_dump_debug(class, buf, size) av_hex_dump_log(class, AV_LOG_DEBUG, buf, size) +#else +# define hex_dump_debug(class, buf, size) +#endif + typedef struct AVCodecTag { enum CodecID id; unsigned int tag; @@ -128,10 +134,12 @@ int ff_url_join(char *str, int size, const char *proto, * @param dest_type the destination address type, may be NULL * @param port the destination port of the media stream, 0 if unknown * @param ttl the time to live of the stream, 0 if not multicast + * @param fmt the AVFormatContext, which might contain options modifying + * the generated SDP */ void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, - int port, int ttl); + int port, int ttl, AVFormatContext *fmt); /** * Write a packet to another muxer than the one the user originally diff --git a/libavformat/ipmovie.c b/libavformat/ipmovie.c index 8ea59a3b08..471d6a4bc0 100644 --- a/libavformat/ipmovie.c +++ b/libavformat/ipmovie.c @@ -35,17 +35,6 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" -/* debugging support: #define DEBUG_IPMOVIE as non-zero to see extremely - * verbose information about the demux process */ -#define DEBUG_IPMOVIE 0 - -#if DEBUG_IPMOVIE -#undef printf -#define debug_ipmovie printf -#else -static inline void debug_ipmovie(const char *format, ...) { } -#endif - #define CHUNK_PREAMBLE_SIZE 4 #define OPCODE_PREAMBLE_SIZE 4 @@ -150,8 +139,8 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, s->audio_frame_count += (s->audio_chunk_size - 6) / s->audio_channels; - debug_ipmovie("sending audio frame with pts %"PRId64" (%d audio frames)\n", - pkt->pts, s->audio_frame_count); + av_dlog(NULL, "sending audio frame with pts %"PRId64" (%d audio frames)\n", + pkt->pts, s->audio_frame_count); chunk_type = CHUNK_VIDEO; @@ -184,8 +173,7 @@ static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, pkt->stream_index = s->video_stream_index; pkt->pts = s->video_pts; - debug_ipmovie("sending video frame with pts %"PRId64"\n", - pkt->pts); + av_dlog(NULL, "sending video frame with pts %"PRId64"\n", pkt->pts); s->video_pts += s->frame_pts_inc; @@ -233,36 +221,36 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, chunk_size = AV_RL16(&chunk_preamble[0]); chunk_type = AV_RL16(&chunk_preamble[2]); - debug_ipmovie("chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size); + av_dlog(NULL, "chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size); switch (chunk_type) { case CHUNK_INIT_AUDIO: - debug_ipmovie("initialize audio\n"); + av_dlog(NULL, "initialize audio\n"); break; case CHUNK_AUDIO_ONLY: - debug_ipmovie("audio only\n"); + av_dlog(NULL, "audio only\n"); break; case CHUNK_INIT_VIDEO: - debug_ipmovie("initialize video\n"); + av_dlog(NULL, "initialize video\n"); break; case CHUNK_VIDEO: - debug_ipmovie("video (and audio)\n"); + av_dlog(NULL, "video (and audio)\n"); break; case CHUNK_SHUTDOWN: - debug_ipmovie("shutdown\n"); + av_dlog(NULL, "shutdown\n"); break; case CHUNK_END: - debug_ipmovie("end\n"); + av_dlog(NULL, "end\n"); break; default: - debug_ipmovie("invalid chunk\n"); + av_dlog(NULL, "invalid chunk\n"); chunk_type = CHUNK_BAD; break; @@ -288,29 +276,29 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, chunk_size -= OPCODE_PREAMBLE_SIZE; chunk_size -= opcode_size; if (chunk_size < 0) { - debug_ipmovie("chunk_size countdown just went negative\n"); + av_dlog(NULL, "chunk_size countdown just went negative\n"); chunk_type = CHUNK_BAD; break; } - debug_ipmovie(" opcode type %02X, version %d, 0x%04X bytes: ", - opcode_type, opcode_version, opcode_size); + av_dlog(NULL, " opcode type %02X, version %d, 0x%04X bytes: ", + opcode_type, opcode_version, opcode_size); switch (opcode_type) { case OPCODE_END_OF_STREAM: - debug_ipmovie("end of stream\n"); + av_dlog(NULL, "end of stream\n"); avio_skip(pb, opcode_size); break; case OPCODE_END_OF_CHUNK: - debug_ipmovie("end of chunk\n"); + av_dlog(NULL, "end of chunk\n"); avio_skip(pb, opcode_size); break; case OPCODE_CREATE_TIMER: - debug_ipmovie("create timer\n"); + av_dlog(NULL, "create timer\n"); if ((opcode_version > 0) || (opcode_size > 6)) { - debug_ipmovie("bad create_timer opcode\n"); + av_dlog(NULL, "bad create_timer opcode\n"); chunk_type = CHUNK_BAD; break; } @@ -320,14 +308,15 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; } s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]); - debug_ipmovie(" %.2f frames/second (timer div = %d, subdiv = %d)\n", - 1000000.0/s->frame_pts_inc, AV_RL32(&scratch[0]), AV_RL16(&scratch[4])); + av_dlog(NULL, " %.2f frames/second (timer div = %d, subdiv = %d)\n", + 1000000.0 / s->frame_pts_inc, AV_RL32(&scratch[0]), + AV_RL16(&scratch[4])); break; case OPCODE_INIT_AUDIO_BUFFERS: - debug_ipmovie("initialize audio buffers\n"); + av_dlog(NULL, "initialize audio buffers\n"); if ((opcode_version > 1) || (opcode_size > 10)) { - debug_ipmovie("bad init_audio_buffers opcode\n"); + av_dlog(NULL, "bad init_audio_buffers opcode\n"); chunk_type = CHUNK_BAD; break; } @@ -349,23 +338,22 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, s->audio_type = CODEC_ID_PCM_S16LE; else s->audio_type = CODEC_ID_PCM_U8; - debug_ipmovie("audio: %d bits, %d Hz, %s, %s format\n", - s->audio_bits, - s->audio_sample_rate, - (s->audio_channels == 2) ? "stereo" : "mono", - (s->audio_type == CODEC_ID_INTERPLAY_DPCM) ? - "Interplay audio" : "PCM"); + av_dlog(NULL, "audio: %d bits, %d Hz, %s, %s format\n", + s->audio_bits, s->audio_sample_rate, + (s->audio_channels == 2) ? "stereo" : "mono", + (s->audio_type == CODEC_ID_INTERPLAY_DPCM) ? + "Interplay audio" : "PCM"); break; case OPCODE_START_STOP_AUDIO: - debug_ipmovie("start/stop audio\n"); + av_dlog(NULL, "start/stop audio\n"); avio_skip(pb, opcode_size); break; case OPCODE_INIT_VIDEO_BUFFERS: - debug_ipmovie("initialize video buffers\n"); + av_dlog(NULL, "initialize video buffers\n"); if ((opcode_version > 2) || (opcode_size > 8)) { - debug_ipmovie("bad init_video_buffers opcode\n"); + av_dlog(NULL, "bad init_video_buffers opcode\n"); chunk_type = CHUNK_BAD; break; } @@ -381,8 +369,8 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, } else { s->video_bpp = 16; } - debug_ipmovie("video resolution: %d x %d\n", - s->video_width, s->video_height); + av_dlog(NULL, "video resolution: %d x %d\n", + s->video_width, s->video_height); break; case OPCODE_UNKNOWN_06: @@ -392,17 +380,17 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, case OPCODE_UNKNOWN_13: case OPCODE_UNKNOWN_14: case OPCODE_UNKNOWN_15: - debug_ipmovie("unknown (but documented) opcode %02X\n", opcode_type); + av_dlog(NULL, "unknown (but documented) opcode %02X\n", opcode_type); avio_skip(pb, opcode_size); break; case OPCODE_SEND_BUFFER: - debug_ipmovie("send buffer\n"); + av_dlog(NULL, "send buffer\n"); avio_skip(pb, opcode_size); break; case OPCODE_AUDIO_FRAME: - debug_ipmovie("audio frame\n"); + av_dlog(NULL, "audio frame\n"); /* log position and move on for now */ s->audio_chunk_offset = avio_tell(pb); @@ -411,26 +399,26 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; case OPCODE_SILENCE_FRAME: - debug_ipmovie("silence frame\n"); + av_dlog(NULL, "silence frame\n"); avio_skip(pb, opcode_size); break; case OPCODE_INIT_VIDEO_MODE: - debug_ipmovie("initialize video mode\n"); + av_dlog(NULL, "initialize video mode\n"); avio_skip(pb, opcode_size); break; case OPCODE_CREATE_GRADIENT: - debug_ipmovie("create gradient\n"); + av_dlog(NULL, "create gradient\n"); avio_skip(pb, opcode_size); break; case OPCODE_SET_PALETTE: - debug_ipmovie("set palette\n"); + av_dlog(NULL, "set palette\n"); /* check for the logical maximum palette size * (3 * 256 + 4 bytes) */ if (opcode_size > 0x304) { - debug_ipmovie("demux_ipmovie: set_palette opcode too large\n"); + av_dlog(NULL, "demux_ipmovie: set_palette opcode too large\n"); chunk_type = CHUNK_BAD; break; } @@ -444,7 +432,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, last_color = first_color + AV_RL16(&scratch[2]) - 1; /* sanity check (since they are 16 bit values) */ if ((first_color > 0xFF) || (last_color > 0xFF)) { - debug_ipmovie("demux_ipmovie: set_palette indexes out of range (%d -> %d)\n", + av_dlog(NULL, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n", first_color, last_color); chunk_type = CHUNK_BAD; break; @@ -463,12 +451,12 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; case OPCODE_SET_PALETTE_COMPRESSED: - debug_ipmovie("set palette compressed\n"); + av_dlog(NULL, "set palette compressed\n"); avio_skip(pb, opcode_size); break; case OPCODE_SET_DECODING_MAP: - debug_ipmovie("set decoding map\n"); + av_dlog(NULL, "set decoding map\n"); /* log position and move on for now */ s->decode_map_chunk_offset = avio_tell(pb); @@ -477,7 +465,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; case OPCODE_VIDEO_DATA: - debug_ipmovie("set video data\n"); + av_dlog(NULL, "set video data\n"); /* log position and move on for now */ s->video_chunk_offset = avio_tell(pb); @@ -486,7 +474,7 @@ static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, break; default: - debug_ipmovie("*** unknown opcode type\n"); + av_dlog(NULL, "*** unknown opcode type\n"); chunk_type = CHUNK_BAD; break; diff --git a/libavformat/isom.c b/libavformat/isom.c index 3259128d3a..dcc3b74af3 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -27,7 +27,6 @@ #include "internal.h" #include "isom.h" #include "riff.h" -#include "avio_internal.h" #include "libavcodec/mpeg4audio.h" #include "libavcodec/mpegaudiodata.h" @@ -460,16 +459,18 @@ void ff_mov_read_chan(AVFormatContext *s, int64_t size, AVCodecContext *codec) uint32_t layout_tag; AVIOContext *pb = s->pb; const MovChannelLayout *layouts = mov_channel_layout; - if (size != 12) { + layout_tag = avio_rb32(pb); + size -= 4; + if (layout_tag == 0) { //< kCAFChannelLayoutTag_UseChannelDescriptions // Channel descriptions not implemented av_log_ask_for_sample(s, "Unimplemented container channel layout.\n"); avio_skip(pb, size); return; } - layout_tag = avio_rb32(pb); if (layout_tag == 0x10000) { //< kCAFChannelLayoutTag_UseChannelBitmap codec->channel_layout = avio_rb32(pb); - avio_skip(pb, 4); + size -= 4; + avio_skip(pb, size); return; } while (layouts->channel_layout) { @@ -481,27 +482,20 @@ void ff_mov_read_chan(AVFormatContext *s, int64_t size, AVCodecContext *codec) } if (!codec->channel_layout) av_log(s, AV_LOG_WARNING, "Unknown container channel layout.\n"); - avio_skip(pb, 8); + avio_skip(pb, size); } -void ff_mov_write_chan(AVFormatContext *s, int64_t channel_layout, - const char *chunk_type) +void ff_mov_write_chan(AVIOContext *pb, int64_t channel_layout) { - AVIOContext *pb = s->pb; const MovChannelLayout *layouts; uint32_t layout_tag = 0; - if (!channel_layout) - return; - for (layouts = mov_channel_layout; layouts->channel_layout; layouts++) if (channel_layout == layouts->channel_layout) { layout_tag = layouts->layout_tag; break; } - ffio_wfourcc(pb, chunk_type); - avio_wb64(pb, 12); //< mChunkSize if (layout_tag) { avio_wb32(pb, layout_tag); //< mChannelLayoutTag avio_wb32(pb, 0); //< mChannelBitmap diff --git a/libavformat/isom.h b/libavformat/isom.h index 6e42a1f841..43fa477a7d 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -155,7 +155,6 @@ enum CodecID ff_mov_get_lpcm_codec_id(int bps, int flags); int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries); void ff_mov_read_chan(AVFormatContext *s, int64_t size, AVCodecContext *codec); -void ff_mov_write_chan(AVFormatContext *s, int64_t channel_layout, - const char *chunk_type); +void ff_mov_write_chan(AVIOContext *pb, int64_t channel_layout); #endif /* AVFORMAT_ISOM_H */ diff --git a/libavformat/m4vdec.c b/libavformat/m4vdec.c index f830c7afcf..88f838022e 100644 --- a/libavformat/m4vdec.c +++ b/libavformat/m4vdec.c @@ -49,14 +49,4 @@ static int mpeg4video_probe(AVProbeData *probe_packet) return 0; } -AVInputFormat ff_m4v_demuxer = { - "m4v", - NULL_IF_CONFIG_SMALL("raw MPEG-4 video format"), - 0, - mpeg4video_probe, /** probing for MPEG-4 data */ - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, - .extensions = "m4v", - .value = CODEC_ID_MPEG4, -}; +FF_DEF_RAWVIDEO_DEMUXER(m4v, "raw MPEG-4 video format", mpeg4video_probe, "m4v", CODEC_ID_MPEG4) diff --git a/libavformat/matroska.c b/libavformat/matroska.c index c7e9663316..52481d7556 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -99,3 +99,27 @@ const AVMetadataConv ff_mkv_metadata_conv[] = { { "PART_NUMBER" , "track" }, { 0 } }; + +const char * const matroska_video_stereo_mode[MATROSKA_VIDEO_STEREO_MODE_COUNT] = { + "mono", + "left_right", + "bottom_top", + "top_bottom", + "checkerboard_rl", + "checkerboard_lr" + "row_interleaved_rl", + "row_interleaved_lr", + "col_interleaved_rl", + "col_interleaved_lr", + "anaglyph_cyan_red", + "right_left", + "anaglyph_green_magenta", + "block_lr", + "block_rl", +}; + +const char * const matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_PLANE_COUNT] = { + "left", + "right", + "background", +}; diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 0d0d0bcff4..ab7e3269fa 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -77,8 +77,13 @@ #define MATROSKA_ID_TRACKNUMBER 0xD7 #define MATROSKA_ID_TRACKUID 0x73C5 #define MATROSKA_ID_TRACKTYPE 0x83 -#define MATROSKA_ID_TRACKAUDIO 0xE1 -#define MATROSKA_ID_TRACKVIDEO 0xE0 +#define MATROSKA_ID_TRACKVIDEO 0xE0 +#define MATROSKA_ID_TRACKAUDIO 0xE1 +#define MATROSKA_ID_TRACKOPERATION 0xE2 +#define MATROSKA_ID_TRACKCOMBINEPLANES 0xE3 +#define MATROSKA_ID_TRACKPLANE 0xE4 +#define MATROSKA_ID_TRACKPLANEUID 0xE5 +#define MATROSKA_ID_TRACKPLANETYPE 0xE6 #define MATROSKA_ID_CODECID 0x86 #define MATROSKA_ID_CODECPRIVATE 0x63A2 #define MATROSKA_ID_CODECNAME 0x258688 @@ -111,7 +116,7 @@ #define MATROSKA_ID_VIDEOPIXELCROPR 0x54DD #define MATROSKA_ID_VIDEODISPLAYUNIT 0x54B2 #define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A -#define MATROSKA_ID_VIDEOSTEREOMODE 0x53B9 +#define MATROSKA_ID_VIDEOSTEREOMODE 0x53B8 #define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3 #define MATROSKA_ID_VIDEOCOLORSPACE 0x2EB524 @@ -218,6 +223,24 @@ typedef enum { MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP = 3, } MatroskaTrackEncodingCompAlgo; +typedef enum { + MATROSKA_VIDEO_STEREOMODE_TYPE_MONO = 0, + MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT = 1, + MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP = 2, + MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM = 3, + MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL = 4, + MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR = 5, + MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL = 6, + MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR = 7, + MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL = 8, + MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR = 9, + MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_CYAN_RED = 10, + MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT = 11, + MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_GREEN_MAG = 12, + MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR = 13, + MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL = 14, +} MatroskaVideoStereoModeType; + /* * Matroska Codec IDs, strings */ @@ -235,8 +258,13 @@ typedef struct CodecMime{ /* max. depth in the EBML tree structure */ #define EBML_MAX_DEPTH 16 +#define MATROSKA_VIDEO_STEREO_MODE_COUNT 15 +#define MATROSKA_VIDEO_STEREO_PLANE_COUNT 3 + extern const CodecTags ff_mkv_codec_tags[]; extern const CodecMime ff_mkv_mime_tags[]; extern const AVMetadataConv ff_mkv_metadata_conv[]; +extern const char * const matroska_video_stereo_mode[MATROSKA_VIDEO_STEREO_MODE_COUNT]; +extern const char * const matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_PLANE_COUNT]; #endif /* AVFORMAT_MATROSKA_H */ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index ab67e110c2..efb80a017d 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -42,6 +42,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" #include "libavutil/lzo.h" +#include "libavutil/dict.h" #if CONFIG_ZLIB #include <zlib.h> #endif @@ -111,7 +112,8 @@ typedef struct { uint64_t display_height; uint64_t pixel_width; uint64_t pixel_height; - uint64_t fourcc; + EbmlBin color_space; + uint64_t stereo_mode; } MatroskaTrackVideo; typedef struct { @@ -132,6 +134,15 @@ typedef struct { } MatroskaTrackAudio; typedef struct { + uint64_t uid; + uint64_t type; +} MatroskaTrackPlane; + +typedef struct { + EbmlList combine_planes; +} MatroskaTrackOperation; + +typedef struct { uint64_t num; uint64_t uid; uint64_t type; @@ -145,6 +156,7 @@ typedef struct { uint64_t flag_forced; MatroskaTrackVideo video; MatroskaTrackAudio audio; + MatroskaTrackOperation operation; EbmlList encodings; AVStream *stream; @@ -290,14 +302,14 @@ static EbmlSyntax matroska_track_video[] = { { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,display_height) }, { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_width) }, { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo,pixel_height) }, - { MATROSKA_ID_VIDEOCOLORSPACE, EBML_UINT, 0, offsetof(MatroskaTrackVideo,fourcc) }, + { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, offsetof(MatroskaTrackVideo,color_space) }, + { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo,stereo_mode) }, { MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE }, { MATROSKA_ID_VIDEOFLAGINTERLACED,EBML_NONE }, - { MATROSKA_ID_VIDEOSTEREOMODE, EBML_NONE }, { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, { 0 } }; @@ -329,6 +341,22 @@ static EbmlSyntax matroska_track_encodings[] = { { 0 } }; +static EbmlSyntax matroska_track_plane[] = { + { MATROSKA_ID_TRACKPLANEUID, EBML_UINT, 0, offsetof(MatroskaTrackPlane,uid) }, + { MATROSKA_ID_TRACKPLANETYPE, EBML_UINT, 0, offsetof(MatroskaTrackPlane,type) }, + { 0 } +}; + +static EbmlSyntax matroska_track_combine_planes[] = { + { MATROSKA_ID_TRACKPLANE, EBML_NEST, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n=matroska_track_plane} }, + { 0 } +}; + +static EbmlSyntax matroska_track_operation[] = { + { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, {.n=matroska_track_combine_planes} }, + { 0 } +}; + static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack,num) }, { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, offsetof(MatroskaTrack,name) }, @@ -343,6 +371,7 @@ static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, offsetof(MatroskaTrack,flag_forced), {.u=0} }, { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, offsetof(MatroskaTrack,video), {.n=matroska_track_video} }, { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, offsetof(MatroskaTrack,audio), {.n=matroska_track_audio} }, + { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, offsetof(MatroskaTrack,operation), {.n=matroska_track_operation} }, { MATROSKA_ID_TRACKCONTENTENCODINGS,EBML_NEST, 0, 0, {.n=matroska_track_encodings} }, { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, @@ -1009,7 +1038,8 @@ static void matroska_fix_ass_packet(MatroskaDemuxContext *matroska, char *line, *layer, *ptr = pkt->data, *end = ptr+pkt->size; for (; *ptr!=',' && ptr<end-1; ptr++); if (*ptr == ',') - layer = ++ptr; + ptr++; + layer = ptr; for (; *ptr!=',' && ptr<end-1; ptr++); if (*ptr == ',') { int64_t end_pts = pkt->pts + display_duration; @@ -1044,7 +1074,7 @@ static void matroska_merge_packets(AVPacket *out, AVPacket *in) } static void matroska_convert_tag(AVFormatContext *s, EbmlList *list, - AVMetadata **metadata, char *prefix) + AVDictionary **metadata, char *prefix) { MatroskaTag *tags = list->elem; char key[1024]; @@ -1060,14 +1090,14 @@ static void matroska_convert_tag(AVFormatContext *s, EbmlList *list, if (prefix) snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name); else av_strlcpy(key, tags[i].name, sizeof(key)); if (tags[i].def || !lang) { - av_metadata_set2(metadata, key, tags[i].string, 0); + av_dict_set(metadata, key, tags[i].string, 0); if (tags[i].sub.nb_elem) matroska_convert_tag(s, &tags[i].sub, metadata, key); } if (lang) { av_strlcat(key, "-", sizeof(key)); av_strlcat(key, lang, sizeof(key)); - av_metadata_set2(metadata, key, tags[i].string, 0); + av_dict_set(metadata, key, tags[i].string, 0); if (tags[i].sub.nb_elem) matroska_convert_tag(s, &tags[i].sub, metadata, key); } @@ -1202,20 +1232,25 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) uint64_t max_start = 0; Ebml ebml = { 0 }; AVStream *st; - int i, j, res; + int i, j, k, res; matroska->ctx = s; /* First read the EBML header. */ if (ebml_parse(matroska, ebml_syntax, &ebml) || ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t) - || ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 2) { + || ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 3) { av_log(matroska->ctx, AV_LOG_ERROR, "EBML header using unsupported features\n" "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", ebml.version, ebml.doctype, ebml.doctype_version); ebml_free(ebml_syntax, &ebml); return AVERROR_PATCHWELCOME; + } else if (ebml.doctype_version == 3) { + av_log(matroska->ctx, AV_LOG_WARNING, + "EBML header using unsupported features\n" + "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", + ebml.version, ebml.doctype, ebml.doctype_version); } for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++) if (!strcmp(ebml.doctype, matroska_doctypes[i])) @@ -1235,7 +1270,7 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) if (matroska->duration) matroska->ctx->duration = matroska->duration * matroska->time_scale * 1000 / AV_TIME_BASE; - av_metadata_set2(&s->metadata, "title", matroska->title, 0); + av_dict_set(&s->metadata, "title", matroska->title, 0); tracks = matroska->tracks.elem; for (i=0; i < matroska->tracks.nb_elem; i++) { @@ -1246,6 +1281,7 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) uint8_t *extradata = NULL; int extradata_size = 0; int extradata_offset = 0; + uint32_t fourcc = 0; AVIOContext b; /* Apply some sanity checks. */ @@ -1267,6 +1303,8 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) track->video.display_width = track->video.pixel_width; if (!track->video.display_height) track->video.display_height = track->video.pixel_height; + if (track->video.color_space.size == 4) + fourcc = AV_RL32(track->video.color_space.data); } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { if (!track->audio.out_samplerate) track->audio.out_samplerate = track->audio.samplerate; @@ -1326,8 +1364,8 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) && track->codec_priv.size >= 40 && track->codec_priv.data != NULL) { track->ms_compat = 1; - track->video.fourcc = AV_RL32(track->codec_priv.data + 16); - codec_id = ff_codec_get_id(ff_codec_bmp_tags, track->video.fourcc); + fourcc = AV_RL32(track->codec_priv.data + 16); + codec_id = ff_codec_get_id(ff_codec_bmp_tags, fourcc); extradata_offset = 40; } else if (!strcmp(track->codec_id, "A_MS/ACM") && track->codec_priv.size >= 14 @@ -1343,8 +1381,8 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) } else if (!strcmp(track->codec_id, "V_QUICKTIME") && (track->codec_priv.size >= 86) && (track->codec_priv.data != NULL)) { - track->video.fourcc = AV_RL32(track->codec_priv.data); - codec_id=ff_codec_get_id(codec_movvideo_tags, track->video.fourcc); + fourcc = AV_RL32(track->codec_priv.data); + codec_id = ff_codec_get_id(codec_movvideo_tags, fourcc); } else if (codec_id == CODEC_ID_PCM_S16BE) { switch (track->audio.bitdepth) { case 8: codec_id = CODEC_ID_PCM_U8; break; @@ -1433,8 +1471,8 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) st->codec->codec_id = codec_id; st->start_time = 0; if (strcmp(track->language, "und")) - av_metadata_set2(&st->metadata, "language", track->language, 0); - av_metadata_set2(&st->metadata, "title", track->name, 0); + av_dict_set(&st->metadata, "language", track->language, 0); + av_dict_set(&st->metadata, "title", track->name, 0); if (track->flag_default) st->disposition |= AV_DISPOSITION_DEFAULT; @@ -1462,8 +1500,10 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) } if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { + MatroskaTrackPlane *planes = track->operation.combine_planes.elem; + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_tag = track->video.fourcc; + st->codec->codec_tag = fourcc; st->codec->width = track->video.pixel_width; st->codec->height = track->video.pixel_height; av_reduce(&st->sample_aspect_ratio.num, @@ -1475,6 +1515,25 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) st->need_parsing = AVSTREAM_PARSE_HEADERS; if (track->default_duration) st->avg_frame_rate = av_d2q(1000000000.0/track->default_duration, INT_MAX); + + /* export stereo mode flag as metadata tag */ + if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREO_MODE_COUNT) + av_dict_set(&st->metadata, "stereo_mode", matroska_video_stereo_mode[track->video.stereo_mode], 0); + + /* if we have virtual track, mark the real tracks */ + for (j=0; j < track->operation.combine_planes.nb_elem; j++) { + char buf[32]; + if (planes[j].type >= MATROSKA_VIDEO_STEREO_PLANE_COUNT) + continue; + snprintf(buf, sizeof(buf), "%s_%d", + matroska_video_stereo_plane[planes[j].type], i); + for (k=0; k < matroska->tracks.nb_elem; k++) + if (planes[j].uid == tracks[k].uid) { + av_dict_set(&s->streams[k]->metadata, + "stereo_mode", buf, 0); + break; + } + } } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->sample_rate = track->audio.out_samplerate; @@ -1495,7 +1554,7 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) AVStream *st = av_new_stream(s, 0); if (st == NULL) break; - av_metadata_set2(&st->metadata, "filename",attachements[j].filename, 0); + av_dict_set(&st->metadata, "filename",attachements[j].filename, 0); st->codec->codec_id = CODEC_ID_NONE; st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; st->codec->extradata = av_malloc(attachements[j].bin.size); @@ -1523,7 +1582,7 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) ff_new_chapter(s, chapters[i].uid, (AVRational){1, 1000000000}, chapters[i].start, chapters[i].end, chapters[i].title); - av_metadata_set2(&chapters[i].chapter->metadata, + av_dict_set(&chapters[i].chapter->metadata, "title", chapters[i].title, 0); max_start = chapters[i].start; } diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 387cead8cd..9e42019415 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -30,6 +30,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/random_seed.h" #include "libavutil/lfg.h" +#include "libavutil/dict.h" #include "libavcodec/xiph.h" #include "libavcodec/mpeg4audio.h" #include <strings.h> @@ -523,7 +524,7 @@ static int mkv_write_tracks(AVFormatContext *s) int bit_depth = av_get_bits_per_sample(codec->codec_id); int sample_rate = codec->sample_rate; int output_sample_rate = 0; - AVMetadataTag *tag; + AVDictionaryEntry *tag; if (!bit_depth) bit_depth = av_get_bits_per_sample_fmt(codec->sample_fmt); @@ -536,9 +537,9 @@ static int mkv_write_tracks(AVFormatContext *s) put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1); put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) - if ((tag = av_metadata_get(st->metadata, "title", NULL, 0))) + if ((tag = av_dict_get(st->metadata, "title", NULL, 0))) put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value); - tag = av_metadata_get(st->metadata, "language", NULL, 0); + tag = av_dict_get(st->metadata, "language", NULL, 0); put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag ? tag->value:"und"); if (st->disposition) @@ -586,12 +587,38 @@ static int mkv_write_tracks(AVFormatContext *s) // XXX: interlace flag? put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width); put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); + + if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) || + (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) { + // save stereo mode flag + uint64_t st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT; + + for (j=0; j<MATROSKA_VIDEO_STEREO_MODE_COUNT; j++) + if (!strcmp(tag->value, matroska_video_stereo_mode[j])){ + st_mode = j; + break; + } + + if ((mkv->mode == MODE_WEBM && st_mode > 3 && st_mode != 11) + || st_mode >= MATROSKA_VIDEO_STEREO_MODE_COUNT) { + av_log(s, AV_LOG_ERROR, + "The specified stereo mode is not valid.\n"); + return AVERROR(EINVAL); + } else + put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, st_mode); + } + if (st->sample_aspect_ratio.num) { int d_width = codec->width*av_q2d(st->sample_aspect_ratio); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height); put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, 3); } + + if (codec->codec_id == CODEC_ID_RAWVIDEO) { + uint32_t color_space = av_le2ne32(codec->codec_tag); + put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space)); + } end_ebml_master(pb, subinfo); break; @@ -656,7 +683,7 @@ static int mkv_write_chapters(AVFormatContext *s) for (i = 0; i < s->nb_chapters; i++) { ebml_master chapteratom, chapterdisplay; AVChapter *c = s->chapters[i]; - AVMetadataTag *t = NULL; + AVDictionaryEntry *t = NULL; chapteratom = start_ebml_master(pb, MATROSKA_ID_CHAPTERATOM, 0); put_ebml_uint(pb, MATROSKA_ID_CHAPTERUID, c->id); @@ -666,7 +693,7 @@ static int mkv_write_chapters(AVFormatContext *s) av_rescale_q(c->end, c->time_base, scale)); put_ebml_uint(pb, MATROSKA_ID_CHAPTERFLAGHIDDEN , 0); put_ebml_uint(pb, MATROSKA_ID_CHAPTERFLAGENABLED, 1); - if ((t = av_metadata_get(c->metadata, "title", NULL, 0))) { + if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { chapterdisplay = start_ebml_master(pb, MATROSKA_ID_CHAPTERDISPLAY, 0); put_ebml_string(pb, MATROSKA_ID_CHAPSTRING, t->value); put_ebml_string(pb, MATROSKA_ID_CHAPLANG , "und"); @@ -679,7 +706,7 @@ static int mkv_write_chapters(AVFormatContext *s) return 0; } -static void mkv_write_simpletag(AVIOContext *pb, AVMetadataTag *t) +static void mkv_write_simpletag(AVIOContext *pb, AVDictionaryEntry *t) { uint8_t *key = av_strdup(t->key); uint8_t *p = key; @@ -709,12 +736,12 @@ static void mkv_write_simpletag(AVIOContext *pb, AVMetadataTag *t) av_freep(&key); } -static int mkv_write_tag(AVFormatContext *s, AVMetadata *m, unsigned int elementid, +static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int elementid, unsigned int uid, ebml_master *tags) { MatroskaMuxContext *mkv = s->priv_data; ebml_master tag, targets; - AVMetadataTag *t = NULL; + AVDictionaryEntry *t = NULL; int ret; if (!tags->pos) { @@ -730,8 +757,8 @@ static int mkv_write_tag(AVFormatContext *s, AVMetadata *m, unsigned int element put_ebml_uint(s->pb, elementid, uid); end_ebml_master(s->pb, targets); - while ((t = av_metadata_get(m, "", t, AV_METADATA_IGNORE_SUFFIX))) - if (strcasecmp(t->key, "title")) + while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) + if (strcasecmp(t->key, "title") && strcasecmp(t->key, "stereo_mode")) mkv_write_simpletag(s->pb, t); end_ebml_master(s->pb, tag); @@ -745,7 +772,7 @@ static int mkv_write_tags(AVFormatContext *s) ff_metadata_conv_ctx(s, ff_mkv_metadata_conv, NULL); - if (av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) { + if (av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) { ret = mkv_write_tag(s, s->metadata, 0, 0, &tags); if (ret < 0) return ret; } @@ -753,7 +780,7 @@ static int mkv_write_tags(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if (!av_metadata_get(st->metadata, "", 0, AV_METADATA_IGNORE_SUFFIX)) + if (!av_dict_get(st->metadata, "", 0, AV_DICT_IGNORE_SUFFIX)) continue; ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &tags); @@ -763,7 +790,7 @@ static int mkv_write_tags(AVFormatContext *s) for (i = 0; i < s->nb_chapters; i++) { AVChapter *ch = s->chapters[i]; - if (!av_metadata_get(ch->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) + if (!av_dict_get(ch->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) continue; ret = mkv_write_tag(s, ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID, ch->id, &tags); @@ -780,7 +807,7 @@ static int mkv_write_header(AVFormatContext *s) MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; ebml_master ebml_header, segment_info; - AVMetadataTag *tag; + AVDictionaryEntry *tag; int ret, i; if (!strcmp(s->oformat->name, "webm")) mkv->mode = MODE_WEBM; @@ -817,7 +844,7 @@ static int mkv_write_header(AVFormatContext *s) segment_info = start_ebml_master(pb, MATROSKA_ID_INFO, 0); put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); - if ((tag = av_metadata_get(s->metadata, "title", NULL, 0))) + if ((tag = av_dict_get(s->metadata, "title", NULL, 0))) put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value); if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { uint32_t segment_uid[4]; @@ -1199,7 +1226,7 @@ AVOutputFormat ff_webm_muxer = { mkv_write_header, mkv_write_packet, mkv_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, + .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, }; #endif diff --git a/libavformat/metadata.c b/libavformat/metadata.c index 68d42fd257..8caeffa316 100644 --- a/libavformat/metadata.c +++ b/libavformat/metadata.c @@ -21,71 +21,20 @@ #include <strings.h> #include "avformat.h" #include "metadata.h" +#include "libavutil/dict.h" -AVMetadataTag * -av_metadata_get(AVMetadata *m, const char *key, const AVMetadataTag *prev, int flags) +#if FF_API_OLD_METADATA2 +AVDictionaryEntry * +av_metadata_get(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags) { - unsigned int i, j; - - if(!m) - return NULL; - - if(prev) i= prev - m->elems + 1; - else i= 0; - - for(; i<m->count; i++){ - const char *s= m->elems[i].key; - if(flags & AV_METADATA_MATCH_CASE) for(j=0; s[j] == key[j] && key[j]; j++); - else for(j=0; toupper(s[j]) == toupper(key[j]) && key[j]; j++); - if(key[j]) - continue; - if(s[j] && !(flags & AV_METADATA_IGNORE_SUFFIX)) - continue; - return &m->elems[i]; - } - return NULL; + return av_dict_get(m, key, prev, flags); } -int av_metadata_set2(AVMetadata **pm, const char *key, const char *value, int flags) +int av_metadata_set2(AVDictionary **pm, const char *key, const char *value, int flags) { - AVMetadata *m= *pm; - AVMetadataTag *tag= av_metadata_get(m, key, NULL, flags); - - if(!m) - m=*pm= av_mallocz(sizeof(*m)); - - if(tag){ - if (flags & AV_METADATA_DONT_OVERWRITE) - return 0; - av_free(tag->value); - av_free(tag->key); - *tag= m->elems[--m->count]; - }else{ - AVMetadataTag *tmp= av_realloc(m->elems, (m->count+1) * sizeof(*m->elems)); - if(tmp){ - m->elems= tmp; - }else - return AVERROR(ENOMEM); - } - if(value){ - if(flags & AV_METADATA_DONT_STRDUP_KEY){ - m->elems[m->count].key = key; - }else - m->elems[m->count].key = av_strdup(key ); - if(flags & AV_METADATA_DONT_STRDUP_VAL){ - m->elems[m->count].value= value; - }else - m->elems[m->count].value= av_strdup(value); - m->count++; - } - if(!m->count) { - av_free(m->elems); - av_freep(pm); - } - - return 0; + return av_dict_set(pm, key, value, flags); } - +#endif #if FF_API_OLD_METADATA int av_metadata_set(AVMetadata **pm, const char *key, const char *value) { @@ -94,41 +43,38 @@ int av_metadata_set(AVMetadata **pm, const char *key, const char *value) #endif #if FF_API_OLD_METADATA2 + void av_metadata_conv(AVFormatContext *ctx, const AVMetadataConv *d_conv, const AVMetadataConv *s_conv) { return; } -#endif -void av_metadata_free(AVMetadata **pm) +void av_metadata_free(AVDictionary **pm) { - AVMetadata *m= *pm; + av_dict_free(pm); +} - if(m){ - while(m->count--){ - av_free(m->elems[m->count].key); - av_free(m->elems[m->count].value); - } - av_free(m->elems); - } - av_freep(pm); +void av_metadata_copy(AVDictionary **dst, AVDictionary *src, int flags) +{ + av_dict_copy(dst, src, flags); } +#endif -void ff_metadata_conv(AVMetadata **pm, const AVMetadataConv *d_conv, +void ff_metadata_conv(AVDictionary **pm, const AVMetadataConv *d_conv, const AVMetadataConv *s_conv) { /* TODO: use binary search to look up the two conversion tables if the tables are getting big enough that it would matter speed wise */ const AVMetadataConv *sc, *dc; - AVMetadataTag *mtag = NULL; - AVMetadata *dst = NULL; + AVDictionaryEntry *mtag = NULL; + AVDictionary *dst = NULL; const char *key; if (d_conv == s_conv) return; - while((mtag=av_metadata_get(*pm, "", mtag, AV_METADATA_IGNORE_SUFFIX))) { + while ((mtag = av_dict_get(*pm, "", mtag, AV_DICT_IGNORE_SUFFIX))) { key = mtag->key; if (s_conv) for (sc=s_conv; sc->native; sc++) @@ -142,9 +88,9 @@ void ff_metadata_conv(AVMetadata **pm, const AVMetadataConv *d_conv, key = dc->native; break; } - av_metadata_set2(&dst, key, mtag->value, 0); + av_dict_set(&dst, key, mtag->value, 0); } - av_metadata_free(pm); + av_dict_free(pm); *pm = dst; } @@ -161,10 +107,3 @@ void ff_metadata_conv_ctx(AVFormatContext *ctx, const AVMetadataConv *d_conv, ff_metadata_conv(&ctx->programs[i]->metadata, d_conv, s_conv); } -void av_metadata_copy(AVMetadata **dst, AVMetadata *src, int flags) -{ - AVMetadataTag *t = NULL; - - while ((t = av_metadata_get(src, "", t, AV_METADATA_IGNORE_SUFFIX))) - av_metadata_set2(dst, t->key, t->value, flags); -} diff --git a/libavformat/metadata.h b/libavformat/metadata.h index dd9b69005c..aa96118f80 100644 --- a/libavformat/metadata.h +++ b/libavformat/metadata.h @@ -29,11 +29,7 @@ #include "avformat.h" - -struct AVMetadata{ - int count; - AVMetadataTag *elems; -}; +#include "libavutil/dict.h" struct AVMetadataConv{ const char *native; @@ -48,7 +44,7 @@ void ff_metadata_demux_compat(AVFormatContext *s); void ff_metadata_mux_compat(AVFormatContext *s); #endif -void ff_metadata_conv(AVMetadata **pm, const AVMetadataConv *d_conv, +void ff_metadata_conv(AVDictionary **pm, const AVMetadataConv *d_conv, const AVMetadataConv *s_conv); void ff_metadata_conv_ctx(AVFormatContext *ctx, const AVMetadataConv *d_conv, const AVMetadataConv *s_conv); diff --git a/libavformat/mmf.c b/libavformat/mmf.c index fc6fcc3caa..89e33b4ce2 100644 --- a/libavformat/mmf.c +++ b/libavformat/mmf.c @@ -186,13 +186,13 @@ static int mmf_read_header(AVFormatContext *s, unsigned int tag; AVIOContext *pb = s->pb; AVStream *st; - int64_t file_size, size; + int64_t size; int rate, params; tag = avio_rl32(pb); if (tag != MKTAG('M', 'M', 'M', 'D')) return -1; - file_size = avio_rb32(pb); + avio_skip(pb, 4); /* file_size */ /* Skip some unused chunks that may or may not be present */ for(;; avio_skip(pb, size)) { @@ -263,12 +263,10 @@ static int mmf_read_packet(AVFormatContext *s, AVPacket *pkt) { MMFContext *mmf = s->priv_data; - AVStream *st; int ret, size; if (url_feof(s->pb)) return AVERROR(EIO); - st = s->streams[0]; size = MAX_SIZE; if(size > mmf->data_size) diff --git a/libavformat/mms.h b/libavformat/mms.h index 788851e24f..0117089d24 100644 --- a/libavformat/mms.h +++ b/libavformat/mms.h @@ -60,4 +60,5 @@ typedef struct { int ff_mms_asf_header_parser(MMSContext * mms); int ff_mms_read_data(MMSContext *mms, uint8_t *buf, const int size); int ff_mms_read_header(MMSContext * mms, uint8_t * buf, const int size); -#endif + +#endif /* AVFORMAT_MMS_H */ diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c index 70664b9776..105e53c82b 100644 --- a/libavformat/mmsh.c +++ b/libavformat/mmsh.c @@ -28,7 +28,7 @@ #include <string.h> #include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" -#include "libavformat/internal.h" +#include "internal.h" #include "mms.h" #include "asf.h" #include "http.h" @@ -231,7 +231,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) host, sizeof(host), &port, path, sizeof(path), location); if (port<0) port = 80; // default mmsh protocol port - ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, path); + ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, "%s", path); if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_RDONLY) < 0) { return AVERROR(EIO); diff --git a/libavformat/mmst.c b/libavformat/mmst.c index 775ab7ea7f..7c1041ec85 100644 --- a/libavformat/mmst.c +++ b/libavformat/mmst.c @@ -152,7 +152,7 @@ static int send_command_packet(MMSTContext *mmst) return 0; } -static void mms_put_utf16(MMSContext *mms, uint8_t *src) +static void mms_put_utf16(MMSContext *mms, const uint8_t *src) { AVIOContext bic; int size = mms->write_out_ptr - mms->out_buffer; diff --git a/libavformat/mov.c b/libavformat/mov.c index c16add7713..302ab18857 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -23,11 +23,11 @@ #include <limits.h> //#define DEBUG -//#define DEBUG_METADATA //#define MOV_EXPORT_ALL_METADATA #include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" +#include "libavutil/dict.h" #include "avformat.h" #include "avio_internal.h" #include "riff.h" @@ -79,15 +79,15 @@ typedef struct MOVParseTableEntry { static const MOVParseTableEntry mov_default_parse_table[]; -static int mov_metadata_trkn(MOVContext *c, AVIOContext *pb, unsigned len) +static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb, unsigned len, const char *type) { char buf[16]; avio_rb16(pb); // unknown snprintf(buf, sizeof(buf), "%d", avio_rb16(pb)); - av_metadata_set2(&c->fc->metadata, "track", buf, 0); + av_dict_set(&c->fc->metadata, type, buf, 0); - avio_rb16(pb); // total tracks + avio_rb16(pb); // total tracks/discs return 0; } @@ -138,7 +138,7 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) const char *key = NULL; uint16_t str_size, langcode = 0; uint32_t data_type = 0; - int (*parse)(MOVContext*, AVIOContext*, unsigned) = NULL; + int (*parse)(MOVContext*, AVIOContext*, unsigned, const char *) = NULL; switch (atom.type) { case MKTAG(0xa9,'n','a','m'): key = "title"; break; @@ -164,7 +164,9 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) case MKTAG( 't','v','e','n'): key = "episode_id";break; case MKTAG( 't','v','n','n'): key = "network"; break; case MKTAG( 't','r','k','n'): key = "track"; - parse = mov_metadata_trkn; break; + parse = mov_metadata_track_or_disc_number; break; + case MKTAG( 'd','i','s','k'): key = "disc"; + parse = mov_metadata_track_or_disc_number; break; } if (c->itunes_metadata && atom.size > 8) { @@ -199,7 +201,7 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) str_size = FFMIN3(sizeof(str)-1, str_size, atom.size); if (parse) - parse(c, pb, str_size); + parse(c, pb, str_size, key); else { if (data_type == 3 || (data_type == 0 && langcode < 0x800)) { // MAC Encoded mov_read_mac_string(c, pb, str_size, str, sizeof(str)); @@ -207,17 +209,15 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_read(pb, str, str_size); str[str_size] = 0; } - av_metadata_set2(&c->fc->metadata, key, str, 0); + av_dict_set(&c->fc->metadata, key, str, 0); if (*language && strcmp(language, "und")) { snprintf(key2, sizeof(key2), "%s-%s", key, language); - av_metadata_set2(&c->fc->metadata, key2, str, 0); + av_dict_set(&c->fc->metadata, key2, str, 0); } } -#ifdef DEBUG_METADATA - av_log(c->fc, AV_LOG_DEBUG, "lang \"%3s\" ", language); - av_log(c->fc, AV_LOG_DEBUG, "tag \"%s\" value \"%s\" atom \"%.4s\" %d %lld\n", - key, str, (char*)&atom.type, str_size, atom.size); -#endif + av_dlog(c->fc, "lang \"%3s\" ", language); + av_dlog(c->fc, "tag \"%s\" value \"%s\" atom \"%.4s\" %d %"PRId64"\n", + key, str, (char*)&atom.type, str_size, atom.size); return 0; } @@ -431,7 +431,7 @@ static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; uint32_t type; - uint32_t ctype; + uint32_t av_unused ctype; if (c->fc->nb_streams < 1) // meta before first trak return 0; @@ -467,21 +467,21 @@ static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom) int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb, MOVAtom atom) { AVStream *st; - int tag, len; + int tag; if (fc->nb_streams < 1) return 0; st = fc->streams[fc->nb_streams-1]; avio_rb32(pb); /* version + flags */ - len = ff_mp4_read_descr(fc, pb, &tag); + ff_mp4_read_descr(fc, pb, &tag); if (tag == MP4ESDescrTag) { avio_rb16(pb); /* ID */ avio_r8(pb); /* priority */ } else avio_rb16(pb); /* ID */ - len = ff_mp4_read_descr(fc, pb, &tag); + ff_mp4_read_descr(fc, pb, &tag); if (tag == MP4DecConfigDescrTag) ff_mp4_read_dec_config_descr(fc, st, pb); return 0; @@ -513,6 +513,19 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams-1]; + + ff_get_wav_header(pb, st->codec, atom.size); + + return 0; +} + static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom) { const int num = avio_rb32(pb); @@ -558,10 +571,10 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (strcmp(type, "qt ")) c->isom = 1; av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type); - av_metadata_set2(&c->fc->metadata, "major_brand", type, 0); + av_dict_set(&c->fc->metadata, "major_brand", type, 0); minor_ver = avio_rb32(pb); /* minor version */ snprintf(minor_ver_str, sizeof(minor_ver_str), "%d", minor_ver); - av_metadata_set2(&c->fc->metadata, "minor_version", minor_ver_str, 0); + av_dict_set(&c->fc->metadata, "minor_version", minor_ver_str, 0); comp_brand_size = atom.size - 8; if (comp_brand_size < 0) @@ -571,7 +584,7 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR(ENOMEM); avio_read(pb, comp_brands_str, comp_brand_size); comp_brands_str[comp_brand_size] = 0; - av_metadata_set2(&c->fc->metadata, "compatible_brands", comp_brands_str, 0); + av_dict_set(&c->fc->metadata, "compatible_brands", comp_brands_str, 0); av_freep(&comp_brands_str); return 0; @@ -595,7 +608,7 @@ static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom) return mov_read_default(c, pb, atom); } -static void mov_metadata_creation_time(AVMetadata **metadata, time_t time) +static void mov_metadata_creation_time(AVDictionary **metadata, time_t time) { char buffer[32]; if (time) { @@ -604,7 +617,7 @@ static void mov_metadata_creation_time(AVMetadata **metadata, time_t time) ptm = gmtime(&time); if (!ptm) return; strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", ptm); - av_metadata_set2(metadata, "creation_time", buffer, 0); + av_dict_set(metadata, "creation_time", buffer, 0); } } @@ -641,7 +654,7 @@ static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) lang = avio_rb16(pb); /* language */ if (ff_mov_lang_to_iso639(lang, language)) - av_metadata_set2(&st->metadata, "language", language, 0); + av_dict_set(&st->metadata, "language", language, 0); avio_rb16(pb); /* quality */ return 0; @@ -718,7 +731,7 @@ static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; st = c->fc->streams[c->fc->nb_streams-1]; - little_endian = avio_rb16(pb); + little_endian = avio_rb16(pb) & 0xFF; av_dlog(c->fc, "enda %d\n", little_endian); if (little_endian == 1) { switch (st->codec->codec_id) { @@ -1525,10 +1538,11 @@ static void mov_build_index(MOVContext *mov, AVStream *st) /* adjust first dts according to edit list */ if (sc->time_offset && mov->time_scale > 0) { - int rescaled = sc->time_offset < 0 ? av_rescale(sc->time_offset, sc->time_scale, mov->time_scale) : sc->time_offset; - current_dts = -rescaled; + if (sc->time_offset < 0) + sc->time_offset = av_rescale(sc->time_offset, sc->time_scale, mov->time_scale); + current_dts = -sc->time_offset; if (sc->ctts_data && sc->stts_data && - sc->ctts_data[0].duration / sc->stts_data[0].duration > 16) { + sc->ctts_data[0].duration / FFMAX(sc->stts_data[0].duration, 1) > 16) { /* more than 16 frames delay, dts are likely wrong this happens with files created by iMovie */ sc->wrong_dts = 1; @@ -1690,13 +1704,13 @@ static void mov_build_index(MOVContext *mov, AVStream *st) } } -static int mov_open_dref(AVIOContext **pb, char *src, MOVDref *ref) +static int mov_open_dref(AVIOContext **pb, const char *src, MOVDref *ref) { /* try relative path, we do not try the absolute because it can leak information about our system to an attacker */ if (ref->nlvl_to > 0 && ref->nlvl_from > 0) { char filename[1024]; - char *src_path; + const char *src_path; int i, l; /* find a source dir */ @@ -1914,6 +1928,10 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->width = width >> 16; sc->height = height >> 16; + if (display_matrix[0][0] == -65536 && display_matrix[1][1] == -65536) { + av_dict_set(&st->metadata, "rotate", "180", 0); + } + // transform the display width/height according to the matrix // skip this if the display matrix is the default identity matrix // or if it is rotating the picture, ex iPhone 3GS @@ -2056,7 +2074,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (flags & 0x001) data_offset = avio_rb32(pb); if (flags & 0x004) first_sample_flags = avio_rb32(pb); - dts = st->duration; + dts = st->duration - sc->time_offset; offset = frag->base_data_offset + data_offset; distance = 0; av_dlog(c->fc, "first sample flags 0x%x\n", first_sample_flags); @@ -2085,7 +2103,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) offset += sample_size; } frag->moof_offset = offset; - st->duration = dts; + st->duration = dts + sc->time_offset; return 0; } @@ -2149,9 +2167,6 @@ static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom) goto free_and_return; atom.type = MKTAG('m','o','o','v'); atom.size = moov_len; -#ifdef DEBUG -// { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); } -#endif ret = mov_read_default(c, &ctx, atom); free_and_return: av_free(moov_data); @@ -2265,6 +2280,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('e','s','d','s'), mov_read_esds }, { MKTAG('d','a','c','3'), mov_read_dac3 }, /* AC-3 info */ { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */ +{ MKTAG('w','f','e','x'), mov_read_wfex }, { MKTAG('c','m','o','v'), mov_read_cmov }, { MKTAG('c','h','a','n'), mov_read_chan }, { 0, NULL } diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 1b61706da3..ebfcacb107 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -32,10 +32,27 @@ #include "libavcodec/put_bits.h" #include "internal.h" #include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "libavutil/dict.h" +#include "rtpenc.h" #undef NDEBUG #include <assert.h> +static const AVOption options[] = { + { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), FF_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "rtphint", "Add RTP hint tracks", 0, FF_OPT_TYPE_CONST, {.dbl = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags), + { NULL }, +}; + +static const AVClass mov_muxer_class = { + .class_name = "MOV/3GP/MP4/3G2 muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + //FIXME support 64 bit variant with wide placeholders static int64_t updateSize(AVIOContext *pb, int64_t pos) { @@ -1274,20 +1291,49 @@ static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track) // This box seems important for the psp playback ... without it the movie seems to hang static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track) { - avio_wb32(pb, 0x24); /* size */ + int64_t duration = av_rescale_rnd(track->trackDuration, MOV_TIMESCALE, + track->timescale, AV_ROUND_UP); + int version = duration < INT32_MAX ? 0 : 1; + int entry_size, entry_count, size; + int64_t delay, start_ct = track->cluster[0].cts; + delay = av_rescale_rnd(track->cluster[0].dts + start_ct, MOV_TIMESCALE, + track->timescale, AV_ROUND_DOWN); + version |= delay < INT32_MAX ? 0 : 1; + + entry_size = (version == 1) ? 20 : 12; + entry_count = 1 + (delay > 0); + size = 24 + entry_count * entry_size; + + /* write the atom data */ + avio_wb32(pb, size); ffio_wfourcc(pb, "edts"); - avio_wb32(pb, 0x1c); /* size */ + avio_wb32(pb, size - 8); ffio_wfourcc(pb, "elst"); - avio_wb32(pb, 0x0); - avio_wb32(pb, 0x1); + avio_w8(pb, version); + avio_wb24(pb, 0); /* flags */ - /* duration ... doesn't seem to effect psp */ - avio_wb32(pb, av_rescale_rnd(track->trackDuration, MOV_TIMESCALE, - track->timescale, AV_ROUND_UP)); + avio_wb32(pb, entry_count); + if (delay > 0) { /* add an empty edit to delay presentation */ + if (version == 1) { + avio_wb64(pb, delay); + avio_wb64(pb, -1); + } else { + avio_wb32(pb, delay); + avio_wb32(pb, -1); + } + avio_wb32(pb, 0x00010000); + } - avio_wb32(pb, track->cluster[0].cts); /* first pts is cts since dts is 0 */ + /* duration */ + if (version == 1) { + avio_wb64(pb, duration); + avio_wb64(pb, start_ct); + } else { + avio_wb32(pb, duration); + avio_wb32(pb, start_ct); + } avio_wb32(pb, 0x00010000); - return 0x24; + return size; } static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track) @@ -1319,12 +1365,12 @@ static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov) return 0x34; } -static int mov_write_udta_sdp(AVIOContext *pb, AVCodecContext *ctx, int index) +static int mov_write_udta_sdp(AVIOContext *pb, AVFormatContext *ctx, int index) { char buf[1000] = ""; int len; - ff_sdp_write_media(buf, sizeof(buf), ctx, NULL, NULL, 0, 0); + ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0]->codec, NULL, NULL, 0, 0, ctx); av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", index); len = strlen(buf); @@ -1344,7 +1390,7 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVTrack *track, AVStream *st) avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "trak"); mov_write_tkhd_tag(pb, track, st); - if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS) + if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS || track->cluster[0].dts) mov_write_edts_tag(pb, track); // PSP Movies require edts box if (track->tref_tag) mov_write_tref_tag(pb, track); @@ -1352,7 +1398,7 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVTrack *track, AVStream *st) if (track->mode == MODE_PSP) mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box if (track->tag == MKTAG('r','t','p',' ')) - mov_write_udta_sdp(pb, track->rtp_ctx->streams[0]->codec, track->trackID); + mov_write_udta_sdp(pb, track->rtp_ctx, track->trackID); if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && track->mode == MODE_MOV) { double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); if (0.0 != sample_aspect_ratio && 1.0 != sample_aspect_ratio) @@ -1491,15 +1537,15 @@ static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb, int long_style) { int l, lang = 0, len, len2; - AVMetadataTag *t, *t2 = NULL; + AVDictionaryEntry *t, *t2 = NULL; char tag2[16]; - if (!(t = av_metadata_get(s->metadata, tag, NULL, 0))) + if (!(t = av_dict_get(s->metadata, tag, NULL, 0))) return 0; len = strlen(t->key); snprintf(tag2, sizeof(tag2), "%s-", tag); - while ((t2 = av_metadata_get(s->metadata, tag2, t2, AV_METADATA_IGNORE_SUFFIX))) { + while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) { len2 = strlen(t2->key); if (len2 == len+4 && !strcmp(t->value, t2->value) && (l=ff_mov_iso639_to_lang(&t2->key[len2-3], 1)) >= 0) { @@ -1514,7 +1560,7 @@ static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb, static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) { - AVMetadataTag *t = av_metadata_get(s->metadata, "track", NULL, 0); + AVDictionaryEntry *t = av_dict_get(s->metadata, "track", NULL, 0); int size = 0, track = t ? atoi(t->value) : 0; if (track) { avio_wb32(pb, 32); /* size */ @@ -1606,7 +1652,7 @@ static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s, const char *tag, const char *str) { int64_t pos = avio_tell(pb); - AVMetadataTag *t = av_metadata_get(s->metadata, str, NULL, 0); + AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0); if (!t || !utf8len(t->value)) return 0; avio_wb32(pb, 0); /* size */ @@ -1618,7 +1664,7 @@ static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s, avio_wb16(pb, language_code("eng")); /* language */ avio_write(pb, t->value, strlen(t->value)+1); /* UTF8 string value */ if (!strcmp(tag, "albm") && - (t = av_metadata_get(s->metadata, "track", NULL, 0))) + (t = av_dict_get(s->metadata, "track", NULL, 0))) avio_w8(pb, atoi(t->value)); } return updateSize(pb, pos); @@ -1637,10 +1683,10 @@ static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s) for (i = 0; i < nb_chapters; i++) { AVChapter *c = s->chapters[i]; - AVMetadataTag *t; + AVDictionaryEntry *t; avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000})); - if ((t = av_metadata_get(c->metadata, "title", NULL, 0))) { + if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { int len = FFMIN(strlen(t->value), 255); avio_w8(pb, len); avio_write(pb, t->value, len); @@ -1718,7 +1764,7 @@ static void mov_write_psp_udta_tag(AVIOContext *pb, static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s) { - AVMetadataTag *title = av_metadata_get(s->metadata, "title", NULL, 0); + AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0); int64_t pos, pos2; if (title) { @@ -2072,13 +2118,13 @@ static void mov_create_chapter_track(AVFormatContext *s, int tracknum) for (i = 0; i < s->nb_chapters; i++) { AVChapter *c = s->chapters[i]; - AVMetadataTag *t; + AVDictionaryEntry *t; int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE}); pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE}); pkt.duration = end - pkt.dts; - if ((t = av_metadata_get(c->metadata, "title", NULL, 0))) { + if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { len = strlen(t->value); pkt.size = len+2; pkt.data = av_malloc(pkt.size); @@ -2125,7 +2171,15 @@ static int mov_write_header(AVFormatContext *s) if (mov->mode & (MODE_MOV|MODE_IPOD) && s->nb_chapters) mov->chapter_track = mov->nb_streams++; +#if FF_API_FLAG_RTP_HINT if (s->flags & AVFMT_FLAG_RTP_HINT) { + av_log(s, AV_LOG_WARNING, "The RTP_HINT flag is deprecated, enable it " + "via the -movflags rtphint muxer option " + "instead.\n"); + mov->flags |= FF_MOV_FLAG_RTP_HINT; + } +#endif + if (mov->flags & FF_MOV_FLAG_RTP_HINT) { /* Add hint tracks for each audio and video stream */ hint_track = mov->nb_streams; for (i = 0; i < s->nb_streams; i++) { @@ -2144,7 +2198,7 @@ static int mov_write_header(AVFormatContext *s) for(i=0; i<s->nb_streams; i++){ AVStream *st= s->streams[i]; MOVTrack *track= &mov->tracks[i]; - AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL,0); + AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0); track->enc = st->codec; track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV); @@ -2221,7 +2275,7 @@ static int mov_write_header(AVFormatContext *s) if (mov->chapter_track) mov_create_chapter_track(s, mov->chapter_track); - if (s->flags & AVFMT_FLAG_RTP_HINT) { + if (mov->flags & FF_MOV_FLAG_RTP_HINT) { /* Initialize the hint tracks for each audio and video stream */ for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; @@ -2298,6 +2352,7 @@ AVOutputFormat ff_mov_muxer = { mov_write_trailer, .flags = AVFMT_GLOBALHEADER, .codec_tag = (const AVCodecTag* const []){codec_movvideo_tags, codec_movaudio_tags, 0}, + .priv_class = &mov_muxer_class, }; #endif #if CONFIG_TGP_MUXER @@ -2314,6 +2369,7 @@ AVOutputFormat ff_tgp_muxer = { mov_write_trailer, .flags = AVFMT_GLOBALHEADER, .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0}, + .priv_class = &mov_muxer_class, }; #endif #if CONFIG_MP4_MUXER @@ -2330,6 +2386,7 @@ AVOutputFormat ff_mp4_muxer = { mov_write_trailer, .flags = AVFMT_GLOBALHEADER, .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0}, + .priv_class = &mov_muxer_class, }; #endif #if CONFIG_PSP_MUXER @@ -2346,6 +2403,7 @@ AVOutputFormat ff_psp_muxer = { mov_write_trailer, .flags = AVFMT_GLOBALHEADER, .codec_tag = (const AVCodecTag* const []){ff_mp4_obj_type, 0}, + .priv_class = &mov_muxer_class, }; #endif #if CONFIG_TG2_MUXER @@ -2362,6 +2420,7 @@ AVOutputFormat ff_tg2_muxer = { mov_write_trailer, .flags = AVFMT_GLOBALHEADER, .codec_tag = (const AVCodecTag* const []){codec_3gp_tags, 0}, + .priv_class = &mov_muxer_class, }; #endif #if CONFIG_IPOD_MUXER @@ -2378,5 +2437,6 @@ AVOutputFormat ff_ipod_muxer = { mov_write_trailer, .flags = AVFMT_GLOBALHEADER, .codec_tag = (const AVCodecTag* const []){codec_ipod_tags, 0}, + .priv_class = &mov_muxer_class, }; #endif diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 182c5edc8c..610683fa6a 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -101,6 +101,7 @@ typedef struct MOVIndex { } MOVTrack; typedef struct MOVMuxContext { + const AVClass *av_class; int mode; int64_t time; int nb_streams; @@ -108,8 +109,13 @@ typedef struct MOVMuxContext { int64_t mdat_pos; uint64_t mdat_size; MOVTrack *tracks; + + int flags; + int rtp_flags; } MOVMuxContext; +#define FF_MOV_FLAG_RTP_HINT 1 + int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt); int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index); diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c index 1306888b46..64f6ea8c0e 100644 --- a/libavformat/mp3dec.c +++ b/libavformat/mp3dec.c @@ -21,6 +21,7 @@ #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #include "id3v2.h" #include "id3v1.h" @@ -149,7 +150,7 @@ static int mp3_read_header(AVFormatContext *s, off = avio_tell(s->pb); - if (!av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) + if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); if (mp3_parse_vbr_tags(s, st, off) < 0) diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 082450779f..50342bb950 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -27,22 +27,24 @@ #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" +#include "libavcodec/mpegaudio.h" #include "libavcodec/mpegaudiodata.h" #include "libavcodec/mpegaudiodecheader.h" #include "libavformat/avio_internal.h" +#include "libavutil/dict.h" static int id3v1_set_string(AVFormatContext *s, const char *key, uint8_t *buf, int buf_size) { - AVMetadataTag *tag; - if ((tag = av_metadata_get(s->metadata, key, NULL, 0))) + AVDictionaryEntry *tag; + if ((tag = av_dict_get(s->metadata, key, NULL, 0))) av_strlcpy(buf, tag->value, buf_size); return !!tag; } static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf) { - AVMetadataTag *tag; + AVDictionaryEntry *tag; int i, count = 0; memset(buf, 0, ID3v1_TAG_SIZE); /* fail safe */ @@ -54,13 +56,13 @@ static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf) count += id3v1_set_string(s, "TALB", buf + 63, 30); //album count += id3v1_set_string(s, "TDRL", buf + 93, 4); //date count += id3v1_set_string(s, "comment", buf + 97, 30); - if ((tag = av_metadata_get(s->metadata, "TRCK", NULL, 0))) { //track + if ((tag = av_dict_get(s->metadata, "TRCK", NULL, 0))) { //track buf[125] = 0; buf[126] = atoi(tag->value); count++; } buf[127] = 0xFF; /* default to unknown genre */ - if ((tag = av_metadata_get(s->metadata, "TCON", NULL, 0))) { //genre + if ((tag = av_dict_get(s->metadata, "TCON", NULL, 0))) { //genre for(i = 0; i <= ID3v1_GENRE_MAX; i++) { if (!strcasecmp(tag->value, ff_id3v1_genre_str[i])) { buf[127] = i; @@ -185,7 +187,7 @@ static const AVClass mp3_muxer_class = { .version = LIBAVUTIL_VERSION_INT, }; -static int id3v2_check_write_tag(AVFormatContext *s, AVMetadataTag *t, const char table[][4], +static int id3v2_check_write_tag(AVFormatContext *s, AVDictionaryEntry *t, const char table[][4], enum ID3v2Encoding enc) { uint32_t tag; @@ -344,7 +346,7 @@ static void mp3_fix_xing(AVFormatContext *s) static int mp3_write_header(struct AVFormatContext *s) { MP3Context *mp3 = s->priv_data; - AVMetadataTag *t = NULL; + AVDictionaryEntry *t = NULL; int totlen = 0, enc = mp3->id3v2_version == 3 ? ID3v2_ENCODING_UTF16BOM : ID3v2_ENCODING_UTF8; int64_t size_pos, cur_pos; @@ -361,7 +363,7 @@ static int mp3_write_header(struct AVFormatContext *s) if (mp3->id3v2_version == 4) ff_metadata_conv(&s->metadata, ff_id3v2_4_metadata_conv, NULL); - while ((t = av_metadata_get(s->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))) { + while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) { int ret; if ((ret = id3v2_check_write_tag(s, t, ff_id3v2_tags, enc)) > 0) { diff --git a/libavformat/mpc.c b/libavformat/mpc.c index 3544cf11cf..4d6854f13f 100644 --- a/libavformat/mpc.c +++ b/libavformat/mpc.c @@ -23,6 +23,7 @@ #include "avformat.h" #include "apetag.h" #include "id3v1.h" +#include "libavutil/dict.h" #define MPC_FRAMESIZE 1152 #define DELAY_FRAMES 32 @@ -96,7 +97,7 @@ static int mpc_read_header(AVFormatContext *s, AVFormatParameters *ap) if (s->pb->seekable) { int64_t pos = avio_tell(s->pb); ff_ape_parse_tag(s); - if (!av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) + if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); avio_seek(s->pb, pos, SEEK_SET); } diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index f9f818951f..1bc4480cd8 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -23,8 +23,6 @@ #include "internal.h" #include "mpeg.h" -//#define DEBUG_SEEK - #undef NDEBUG #include <assert.h> @@ -572,10 +570,9 @@ static int mpegps_read_packet(AVFormatContext *s, pkt->dts = dts; pkt->pos = dummy_pos; pkt->stream_index = st->index; -#if 0 - av_log(s, AV_LOG_DEBUG, "%d: pts=%0.3f dts=%0.3f size=%d\n", - pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, pkt->size); -#endif + av_dlog(s, "%d: pts=%0.3f dts=%0.3f size=%d\n", + pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, + pkt->size); return 0; } @@ -587,18 +584,13 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, int64_t pos, pts, dts; pos = *ppos; -#ifdef DEBUG_SEEK - printf("read_dts: pos=0x%"PRIx64" next=%d -> ", pos, find_next); -#endif if (avio_seek(s->pb, pos, SEEK_SET) < 0) return AV_NOPTS_VALUE; for(;;) { len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); if (len < 0) { -#ifdef DEBUG_SEEK - printf("none (ret=%d)\n", len); -#endif + av_dlog(s, "none (ret=%d)\n", len); return AV_NOPTS_VALUE; } if (startcode == s->streams[stream_index]->id && @@ -607,9 +599,8 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, } avio_skip(s->pb, len); } -#ifdef DEBUG_SEEK - printf("pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", pos, dts, dts / 90000.0); -#endif + av_dlog(s, "pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", + pos, dts, dts / 90000.0); *ppos = pos; return dts; } diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c index e42fac4ceb..9c808d0f1e 100644 --- a/libavformat/mpegenc.c +++ b/libavformat/mpegenc.c @@ -25,7 +25,6 @@ #include "mpeg.h" #define MAX_PAYLOAD_SIZE 4096 -//#define DEBUG_SEEK #undef NDEBUG #include <assert.h> @@ -1078,10 +1077,8 @@ retry: best_dts= pkt_desc->dts; } -#if 0 - av_log(ctx, AV_LOG_DEBUG, "bumping scr, scr:%f, dts:%f\n", - scr/90000.0, best_dts/90000.0); -#endif + av_dlog(ctx, "bumping scr, scr:%f, dts:%f\n", + scr / 90000.0, best_dts / 90000.0); if(best_dts == INT64_MAX) return 0; diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 6452861e38..89109c0689 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -19,12 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -//#define DEBUG -//#define DEBUG_SEEK //#define USE_SYNCPOINT_SEARCH #include "libavutil/crc.h" #include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "libavutil/dict.h" +#include "libavutil/opt.h" #include "libavcodec/bytestream.h" #include "avformat.h" #include "mpegts.h" @@ -86,6 +87,7 @@ struct Program { }; struct MpegTSContext { + const AVClass *class; /* user data */ AVFormatContext *stream; /** raw packet size, including FEC if present */ @@ -122,6 +124,19 @@ struct MpegTSContext { MpegTSFilter *pids[NB_PID_MAX]; }; +static const AVOption options[] = { + {"compute_pcr", "Compute exact PCR for each transport stream packet.", offsetof(MpegTSContext, mpeg2ts_compute_pcr), FF_OPT_TYPE_INT, + {.dbl = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass mpegtsraw_class = { + .class_name = "mpegtsraw demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + /* TS stream handling */ enum MpegTSState { @@ -205,6 +220,17 @@ static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid, unsigned i p->pids[p->nb_pids++] = pid; } +static void set_pcr_pid(AVFormatContext *s, unsigned int programid, unsigned int pid) +{ + int i; + for(i=0; i<s->nb_programs; i++) { + if(s->programs[i]->id == programid) { + s->programs[i]->pcr_pid = pid; + break; + } + } +} + /** * \brief discard_pid() decides if the pid is to be discarded according * to caller's programs selection @@ -928,7 +954,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type language[1] = get8(pp, desc_end); language[2] = get8(pp, desc_end); language[3] = 0; - av_metadata_set2(&st->metadata, "language", language, 0); + av_dict_set(&st->metadata, "language", language, 0); break; case 0x59: /* subtitling descriptor */ language[0] = get8(pp, desc_end); @@ -957,7 +983,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type } } *pp += 4; - av_metadata_set2(&st->metadata, "language", language, 0); + av_dict_set(&st->metadata, "language", language, 0); break; case 0x0a: /* ISO 639 language descriptor */ for (i = 0; i + 4 <= desc_len; i += 4) { @@ -973,7 +999,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type } if (i) { language[i - 1] = 0; - av_metadata_set2(&st->metadata, "language", language, 0); + av_dict_set(&st->metadata, "language", language, 0); } break; case 0x05: /* registration descriptor */ @@ -983,6 +1009,9 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type stream_type == STREAM_TYPE_PRIVATE_DATA) mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types); break; + case 0x52: /* stream identifier descriptor */ + st->stream_identifier = 1 + get8(pp, desc_end); + break; default: break; } @@ -1004,10 +1033,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len int mp4_dec_config_descr_len = 0; int mp4_es_id = 0; -#ifdef DEBUG av_dlog(ts->stream, "PMT: len %i\n", section_len); - av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len); -#endif + hex_dump_debug(ts->stream, (uint8_t *)section, section_len); p_end = section + section_len - 4; p = section; @@ -1025,6 +1052,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (pcr_pid < 0) return; add_pid_to_pmt(ts, h->id, pcr_pid); + set_pcr_pid(ts->stream, h->id, pcr_pid); av_dlog(ts->stream, "pcr_pid=0x%x\n", pcr_pid); @@ -1123,11 +1151,11 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len SectionHeader h1, *h = &h1; const uint8_t *p, *p_end; int sid, pmt_pid; + AVProgram *program; -#ifdef DEBUG av_dlog(ts->stream, "PAT:\n"); - av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len); -#endif + hex_dump_debug(ts->stream, (uint8_t *)section, section_len); + p_end = section + section_len - 4; p = section; if (parse_section_header(h, &p, p_end) < 0) @@ -1135,6 +1163,8 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (h->tid != PAT_TID) return; + ts->stream->ts_id = h->id; + clear_programs(ts); for(;;) { sid = get16(&p, p_end); @@ -1149,7 +1179,9 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (sid == 0x0000) { /* NIT info */ } else { - av_new_program(ts->stream, sid); + program = av_new_program(ts->stream, sid); + program->program_num = sid; + program->pmt_pid = pmt_pid; if (ts->pids[pmt_pid]) mpegts_close_filter(ts, ts->pids[pmt_pid]); mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1); @@ -1168,10 +1200,8 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type; char *name, *provider_name; -#ifdef DEBUG av_dlog(ts->stream, "SDT:\n"); - av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len); -#endif + hex_dump_debug(ts->stream, (uint8_t *)section, section_len); p_end = section + section_len - 4; p = section; @@ -1222,8 +1252,8 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (name) { AVProgram *program = av_new_program(ts->stream, sid); if(program) { - av_metadata_set2(&program->metadata, "service_name", name, 0); - av_metadata_set2(&program->metadata, "service_provider", provider_name, 0); + av_dict_set(&program->metadata, "service_name", name, 0); + av_dict_set(&program->metadata, "service_provider", provider_name, 0); } } av_free(name); @@ -1460,13 +1490,16 @@ static int mpegts_read_header(AVFormatContext *s, int len; int64_t pos; +#if FF_API_FORMAT_PARAMETERS if (ap) { - ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr; + if (ap->mpeg2ts_compute_pcr) + ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr; if(ap->mpeg2ts_raw){ av_log(s, AV_LOG_ERROR, "use mpegtsraw_demuxer!\n"); return -1; } } +#endif /* read the first 1024 bytes to get packet size */ pos = avio_tell(pb); @@ -1544,10 +1577,8 @@ static int mpegts_read_header(AVFormatContext *s, s->bit_rate = (TS_PACKET_SIZE * 8) * 27e6 / ts->pcr_incr; st->codec->bit_rate = s->bit_rate; st->start_time = ts->cur_pcr; -#if 0 - av_log(ts->stream, AV_LOG_DEBUG, "start=%0.3f pcr=%0.3f incr=%d\n", - st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr); -#endif + av_dlog(ts->stream, "start=%0.3f pcr=%0.3f incr=%d\n", + st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr); } avio_seek(pb, pos, SEEK_SET); @@ -1888,4 +1919,5 @@ AVInputFormat ff_mpegtsraw_demuxer = { #ifdef USE_SYNCPOINT_SEARCH .read_seek2 = read_seek2, #endif + .priv_class = &mpegtsraw_class, }; diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index e7d70015aa..7e9647257f 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -21,6 +21,7 @@ #include "libavutil/bswap.h" #include "libavutil/crc.h" +#include "libavutil/dict.h" #include "libavutil/opt.h" #include "libavcodec/mpegvideo.h" #include "avformat.h" @@ -53,6 +54,7 @@ typedef struct MpegTSService { } MpegTSService; typedef struct MpegTSWrite { + const AVClass *av_class; MpegTSSection pat; /* MPEG2 pat table */ MpegTSSection sdt; /* MPEG2 sdt table context */ MpegTSService **services; @@ -243,7 +245,7 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) for(i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; MpegTSWriteStream *ts_st = st->priv_data; - AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL,0); + AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0); switch(st->codec->codec_id) { case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: @@ -442,7 +444,7 @@ static int mpegts_write_header(AVFormatContext *s) MpegTSWriteStream *ts_st; MpegTSService *service; AVStream *st, *pcr_st = NULL; - AVMetadataTag *title, *provider; + AVDictionaryEntry *title, *provider; int i, j; const char *service_name; const char *provider_name; @@ -451,11 +453,11 @@ static int mpegts_write_header(AVFormatContext *s) ts->tsid = ts->transport_stream_id; ts->onid = ts->original_network_id; /* allocate a single DVB service */ - title = av_metadata_get(s->metadata, "service_name", NULL, 0); + title = av_dict_get(s->metadata, "service_name", NULL, 0); if (!title) - title = av_metadata_get(s->metadata, "title", NULL, 0); + title = av_dict_get(s->metadata, "title", NULL, 0); service_name = title ? title->value : DEFAULT_SERVICE_NAME; - provider = av_metadata_get(s->metadata, "service_provider", NULL, 0); + provider = av_dict_get(s->metadata, "service_provider", NULL, 0); provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; service = mpegts_add_service(ts, ts->service_id, provider_name, service_name); service->pmt.write_packet = section_write_packet; diff --git a/libavformat/mpegvideodec.c b/libavformat/mpegvideodec.c index d1ba1f8c2c..d38d6955e4 100644 --- a/libavformat/mpegvideodec.c +++ b/libavformat/mpegvideodec.c @@ -55,13 +55,4 @@ static int mpegvideo_probe(AVProbeData *p) return 0; } -AVInputFormat ff_mpegvideo_demuxer = { - "mpegvideo", - NULL_IF_CONFIG_SMALL("raw MPEG video"), - 0, - mpegvideo_probe, - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, - .value = CODEC_ID_MPEG1VIDEO, -}; +FF_DEF_RAWVIDEO_DEMUXER(mpegvideo, "raw MPEG video", mpegvideo_probe, NULL, CODEC_ID_MPEG1VIDEO) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 6b44b8f3e3..8548c792f6 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -309,7 +309,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) if (klv_read_packet(&klv, s->pb) < 0) return -1; PRINT_KEY(s, "read packet", klv.key); - av_dlog(s, "size %lld offset %#llx\n", klv.length, klv.offset); + av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) { int res = mxf_decrypt_triplet(s, pkt, &klv); if (res < 0) { @@ -522,8 +522,8 @@ static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int case 0x3F06: av_dlog(NULL, "IndexSID %d\n", avio_rb32(pb)); break; case 0x3F07: av_dlog(NULL, "BodySID %d\n", avio_rb32(pb)); break; case 0x3F0B: av_dlog(NULL, "IndexEditRate %d/%d\n", avio_rb32(pb), avio_rb32(pb)); break; - case 0x3F0C: av_dlog(NULL, "IndexStartPosition %lld\n", avio_rb64(pb)); break; - case 0x3F0D: av_dlog(NULL, "IndexDuration %lld\n", avio_rb64(pb)); break; + case 0x3F0C: av_dlog(NULL, "IndexStartPosition %"PRIu64"\n", avio_rb64(pb)); break; + case 0x3F0D: av_dlog(NULL, "IndexDuration %"PRIu64"\n", avio_rb64(pb)); break; } return 0; } @@ -920,7 +920,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) if (klv_read_packet(&klv, s->pb) < 0) return -1; PRINT_KEY(s, "read header", klv.key); - av_dlog(s, "size %lld offset %#llx\n", klv.length, klv.offset); + av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) || IS_KLV_KEY(klv.key, mxf_essence_element_key)) { /* FIXME avoid seek */ diff --git a/libavformat/network.h b/libavformat/network.h index f2a0c97d77..f7e19b196e 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -21,7 +21,10 @@ #ifndef AVFORMAT_NETWORK_H #define AVFORMAT_NETWORK_H +#include <errno.h> + #include "config.h" +#include "libavutil/error.h" #include "os_support.h" #if HAVE_WINSOCK2_H @@ -33,7 +36,8 @@ #define ECONNREFUSED WSAECONNREFUSED #define EINPROGRESS WSAEINPROGRESS -static inline int ff_neterrno() { +static inline int ff_neterrno(void) +{ int err = WSAGetLastError(); switch (err) { case WSAEWOULDBLOCK: diff --git a/libavformat/nsvdec.c b/libavformat/nsvdec.c index 300a8fd7f8..4898187f3a 100644 --- a/libavformat/nsvdec.c +++ b/libavformat/nsvdec.c @@ -20,10 +20,10 @@ */ #include "avformat.h" #include "riff.h" +#include "libavutil/dict.h" +#include "libavutil/intreadwrite.h" -//#define DEBUG //#define DEBUG_DUMP_INDEX // XXX dumbdriving-271.nsv breaks with it commented!! -//#define DEBUG_SEEK #define CHECK_SUBSEQUENT_NSVS //#define DISABLE_AUDIO @@ -267,7 +267,8 @@ static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap) { NSVContext *nsv = s->priv_data; AVIOContext *pb = s->pb; - unsigned int file_size, size; + unsigned int av_unused file_size; + unsigned int size; int64_t duration; int strings_size; int table_entries; @@ -327,7 +328,7 @@ static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap) break; *p++ = '\0'; av_dlog(s, "NSV NSVf INFO: %s='%s'\n", token, value); - av_metadata_set2(&s->metadata, token, value, 0); + av_dict_set(&s->metadata, token, value, 0); } av_free(strings); } @@ -531,7 +532,7 @@ static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap) err = nsv_read_chunk(s, 1); av_dlog(s, "parsed header\n"); - return 0; + return err; } static int nsv_read_chunk(AVFormatContext *s, int fill_header) @@ -546,7 +547,7 @@ static int nsv_read_chunk(AVFormatContext *s, int fill_header) uint32_t vsize; uint16_t asize; uint16_t auxsize; - uint32_t auxtag; + uint32_t av_unused auxtag; av_dlog(s, "%s(%d)\n", __FUNCTION__, fill_header); @@ -736,10 +737,8 @@ static int nsv_read_close(AVFormatContext *s) static int nsv_probe(AVProbeData *p) { - int i; - int score; - int vsize, asize, auxcount; - score = 0; + int i, score = 0; + av_dlog(NULL, "nsv_probe(), buf_size %d\n", p->buf_size); /* check file header */ /* streamed files might not have any header */ @@ -751,19 +750,14 @@ static int nsv_probe(AVProbeData *p) /* seems the servers don't bother starting clean chunks... */ /* sometimes even the first header is at 9KB or something :^) */ for (i = 1; i < p->buf_size - 3; i++) { - if (p->buf[i+0] == 'N' && p->buf[i+1] == 'S' && - p->buf[i+2] == 'V' && p->buf[i+3] == 's') { - score = AVPROBE_SCORE_MAX/5; + if (AV_RL32(p->buf + i) == AV_RL32("NSVs")) { /* Get the chunk size and check if at the end we are getting 0xBEEF */ - auxcount = p->buf[i+19]; - vsize = p->buf[i+20] | p->buf[i+21] << 8; - asize = p->buf[i+22] | p->buf[i+23] << 8; - vsize = (vsize << 4) | (auxcount >> 4); - if ((asize + vsize + i + 23) < p->buf_size - 2) { - if (p->buf[i+23+asize+vsize+1] == 0xEF && - p->buf[i+23+asize+vsize+2] == 0xBE) - return AVPROBE_SCORE_MAX-20; - } + int vsize = AV_RL24(p->buf+i+19) >> 4; + int asize = AV_RL16(p->buf+i+22); + int offset = i + 23 + asize + vsize + 1; + if (offset <= p->buf_size - 2 && AV_RL16(p->buf + offset) == 0xBEEF) + return 4*AVPROBE_SCORE_MAX/5; + score = AVPROBE_SCORE_MAX/5; } } /* so we'll have more luck on extension... */ diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c index 2957a2b173..8af0c48bfc 100644 --- a/libavformat/nutdec.c +++ b/libavformat/nutdec.c @@ -23,6 +23,7 @@ #include <strings.h> #include "libavutil/avstring.h" #include "libavutil/bswap.h" +#include "libavutil/dict.h" #include "libavutil/tree.h" #include "avio_internal.h" #include "nut.h" @@ -194,7 +195,6 @@ static int decode_main_header(NUTContext *nut){ uint64_t tmp, end; unsigned int stream_count; int i, j, tmp_stream, tmp_mul, tmp_pts, tmp_size, count, tmp_res, tmp_head_idx; - int64_t tmp_match; end= get_packetheader(nut, bc, 1, MAIN_STARTCODE); end += avio_tell(bc); @@ -222,7 +222,6 @@ static int decode_main_header(NUTContext *nut){ tmp_pts=0; tmp_mul=1; tmp_stream=0; - tmp_match= 1-(1LL<<62); tmp_head_idx= 0; for(i=0; i<256;){ int tmp_flags = ffio_read_varlen(bc); @@ -236,7 +235,7 @@ static int decode_main_header(NUTContext *nut){ else tmp_res = 0; if(tmp_fields>5) count = ffio_read_varlen(bc); else count = tmp_mul - tmp_size; - if(tmp_fields>6) tmp_match = get_s(bc); + if(tmp_fields>6) get_s(bc); if(tmp_fields>7) tmp_head_idx= ffio_read_varlen(bc); while(tmp_fields-- > 8) @@ -407,7 +406,7 @@ static int decode_info_header(NUTContext *nut){ const char *type; AVChapter *chapter= NULL; AVStream *st= NULL; - AVMetadata **metadata = NULL; + AVDictionary **metadata = NULL; end= get_packetheader(nut, bc, 1, INFO_STARTCODE); end += avio_tell(bc); @@ -465,7 +464,7 @@ static int decode_info_header(NUTContext *nut){ } if(metadata && strcasecmp(name,"Uses") && strcasecmp(name,"Depends") && strcasecmp(name,"Replaces")) - av_metadata_set2(metadata, name, str_value, 0); + av_dict_set(metadata, name, str_value, 0); } } diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index 4756ca2a1a..6ec9bcd8fd 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -21,6 +21,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/tree.h" +#include "libavutil/dict.h" #include "libavcodec/mpegaudiodata.h" #include "nut.h" #include "internal.h" @@ -432,7 +433,7 @@ static int add_info(AVIOContext *bc, const char *type, const char *value){ static int write_globalinfo(NUTContext *nut, AVIOContext *bc){ AVFormatContext *s= nut->avf; - AVMetadataTag *t = NULL; + AVDictionaryEntry *t = NULL; AVIOContext *dyn_bc; uint8_t *dyn_buf=NULL; int count=0, dyn_size; @@ -440,7 +441,7 @@ static int write_globalinfo(NUTContext *nut, AVIOContext *bc){ if(ret < 0) return ret; - while ((t = av_metadata_get(s->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))) + while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) count += add_info(dyn_bc, t->key, t->value); ff_put_v(bc, 0); //stream_if_plus1 @@ -491,7 +492,7 @@ static int write_chapter(NUTContext *nut, AVIOContext *bc, int id) { AVIOContext *dyn_bc; uint8_t *dyn_buf = NULL; - AVMetadataTag *t = NULL; + AVDictionaryEntry *t = NULL; AVChapter *ch = nut->avf->chapters[id]; int ret, dyn_size, count = 0; @@ -504,7 +505,7 @@ static int write_chapter(NUTContext *nut, AVIOContext *bc, int id) put_tt(nut, nut->chapter[id].time_base, bc, ch->start); // chapter_start ff_put_v(bc, ch->end - ch->start); // chapter_len - while ((t = av_metadata_get(ch->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))) + while ((t = av_dict_get(ch->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) count += add_info(dyn_bc, t->key, t->value); ff_put_v(bc, count); diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index c799ce5205..655da35dd4 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -193,18 +193,17 @@ static int ogg_read_page(AVFormatContext *s, int *str) AVIOContext *bc = s->pb; struct ogg *ogg = s->priv_data; struct ogg_stream *os; - int i = 0; + int ret, i = 0; int flags, nsegs; uint64_t gp; uint32_t serial; - uint32_t seq; - uint32_t crc; int size, idx; uint8_t sync[4]; int sp = 0; - if (avio_read (bc, sync, 4) < 4) - return -1; + ret = avio_read (bc, sync, 4); + if (ret < 4) + return ret < 0 ? ret : AVERROR_EOF; do{ int c; @@ -216,23 +215,22 @@ static int ogg_read_page(AVFormatContext *s, int *str) c = avio_r8(bc); if (url_feof(bc)) - return -1; + return AVERROR_EOF; sync[sp++ & 3] = c; }while (i++ < MAX_PAGE_SIZE); if (i >= MAX_PAGE_SIZE){ av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n"); - return -1; + return AVERROR_INVALIDDATA; } if (avio_r8(bc) != 0) /* version */ - return -1; + return AVERROR_INVALIDDATA; flags = avio_r8(bc); gp = avio_rl64 (bc); serial = avio_rl32 (bc); - seq = avio_rl32 (bc); - crc = avio_rl32 (bc); + avio_skip(bc, 8); /* seq, crc */ nsegs = avio_r8(bc); idx = ogg_find_stream (ogg, serial); @@ -251,7 +249,7 @@ static int ogg_read_page(AVFormatContext *s, int *str) idx = ogg_new_stream(s, serial, 1); } if (idx < 0) - return -1; + return idx; } os = ogg->streams + idx; @@ -260,8 +258,9 @@ static int ogg_read_page(AVFormatContext *s, int *str) if(os->psize > 0) ogg_new_buf(ogg, idx); - if (avio_read (bc, os->segments, nsegs) < nsegs) - return -1; + ret = avio_read (bc, os->segments, nsegs); + if (ret < nsegs) + return ret < 0 ? ret : AVERROR_EOF; os->nsegs = nsegs; os->segp = 0; @@ -292,8 +291,9 @@ static int ogg_read_page(AVFormatContext *s, int *str) os->buf = nb; } - if (avio_read (bc, os->buf + os->bufpos, size) < size) - return -1; + ret = avio_read (bc, os->buf + os->bufpos, size); + if (ret < size) + return ret < 0 ? ret : AVERROR_EOF; os->bufpos += size; os->granule = gp; @@ -309,35 +309,32 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, int64_t *fpos) { struct ogg *ogg = s->priv_data; - int idx, i; + int idx, i, ret; struct ogg_stream *os; int complete = 0; int segp = 0, psize = 0; -#if 0 - av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx); -#endif + av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx); do{ idx = ogg->curidx; while (idx < 0){ - if (ogg_read_page (s, &idx) < 0) - return -1; + ret = ogg_read_page (s, &idx); + if (ret < 0) + return ret; } os = ogg->streams + idx; -#if 0 - av_log (s, AV_LOG_DEBUG, - "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n", + av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n", idx, os->pstart, os->psize, os->segp, os->nsegs); -#endif if (!os->codec){ if (os->header < 0){ os->codec = ogg_find_codec (os->buf, os->bufpos); if (!os->codec){ + av_log(s, AV_LOG_WARNING, "Codec not found\n"); os->header = 0; return 0; } @@ -364,11 +361,6 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, } }while (!complete); -#if 0 - av_log (s, AV_LOG_DEBUG, - "ogg_packet: idx %i, frame size %i, start %i\n", - idx, os->psize, os->pstart); -#endif if (os->granule == -1) av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos); @@ -418,6 +410,8 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, *fpos = os->sync_pos; os->pstart += os->psize; os->psize = 0; + if(os->pstart == os->bufpos) + os->bufpos = os->pstart = 0; os->sync_pos = os->page_pos; } @@ -439,15 +433,15 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, static int ogg_get_headers(AVFormatContext *s) { struct ogg *ogg = s->priv_data; + int ret; do{ - if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0) - return -1; + ret = ogg_packet (s, NULL, NULL, NULL, NULL); + if (ret < 0) + return ret; }while (!ogg->headers); -#if 0 - av_log (s, AV_LOG_DEBUG, "found headers\n"); -#endif + av_dlog(s, "found headers\n"); return 0; } @@ -503,11 +497,12 @@ static int ogg_get_length(AVFormatContext *s) static int ogg_read_header(AVFormatContext *s, AVFormatParameters *ap) { struct ogg *ogg = s->priv_data; - int i; + int ret, i; ogg->curidx = -1; //linear headers seek from start - if (ogg_get_headers (s) < 0){ - return -1; + ret = ogg_get_headers (s); + if (ret < 0){ + return ret; } for (i = 0; i < ogg->nstreams; i++) diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h index 82efd97aec..184a628622 100644 --- a/libavformat/oggdec.h +++ b/libavformat/oggdec.h @@ -112,7 +112,7 @@ extern const struct ogg_codec ff_speex_codec; extern const struct ogg_codec ff_theora_codec; extern const struct ogg_codec ff_vorbis_codec; -int ff_vorbis_comment(AVFormatContext *ms, AVMetadata **m, const uint8_t *buf, int size); +int ff_vorbis_comment(AVFormatContext *ms, AVDictionary **m, const uint8_t *buf, int size); static inline int ogg_find_stream (struct ogg * ogg, int serial) diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index 45e677fb08..04f536f157 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -241,7 +241,7 @@ static int ogg_buffer_data(AVFormatContext *s, AVStream *st, } static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact, - int *header_len, AVMetadata **m, int framing_bit) + int *header_len, AVDictionary **m, int framing_bit) { const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; int size; @@ -267,7 +267,7 @@ static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact, static int ogg_build_flac_headers(AVCodecContext *avctx, OGGStreamContext *oggstream, int bitexact, - AVMetadata **m) + AVDictionary **m) { enum FLACExtradataFormat format; uint8_t *streaminfo; @@ -307,7 +307,7 @@ static int ogg_build_flac_headers(AVCodecContext *avctx, static int ogg_build_speex_headers(AVCodecContext *avctx, OGGStreamContext *oggstream, int bitexact, - AVMetadata **m) + AVDictionary **m) { uint8_t *p; diff --git a/libavformat/oggparsecelt.c b/libavformat/oggparsecelt.c index bbb695f438..2adc06046a 100644 --- a/libavformat/oggparsecelt.c +++ b/libavformat/oggparsecelt.c @@ -41,8 +41,8 @@ static int celt_header(AVFormatContext *s, int idx) /* Main header */ - uint32_t version, header_size, sample_rate, nb_channels, frame_size; - uint32_t overlap, bytes_per_packet, extra_headers; + uint32_t version, header_size av_unused, sample_rate, nb_channels, frame_size; + uint32_t overlap, bytes_per_packet av_unused, extra_headers; uint8_t *extradata; extradata = av_malloc(2 * sizeof(uint32_t) + diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index dda5be601a..9526c3acc1 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -39,7 +39,6 @@ ogm_header(AVFormatContext *s, int idx) const uint8_t *p = os->buf + os->pstart; uint64_t time_unit; uint64_t spu; - uint32_t default_len; if(!(*p & 1)) return 0; @@ -74,8 +73,7 @@ ogm_header(AVFormatContext *s, int idx) time_unit = bytestream_get_le64(&p); spu = bytestream_get_le64(&p); - default_len = bytestream_get_le32(&p); - + p += 4; /* default_len */ p += 8; /* buffersize + bits_per_sample */ if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){ diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 830f0bca37..86951f3e2f 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include "libavutil/avstring.h" #include "libavutil/bswap.h" +#include "libavutil/dict.h" #include "libavcodec/get_bits.h" #include "libavcodec/bytestream.h" #include "avformat.h" @@ -57,8 +58,8 @@ static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val) if (!chapter) return 0; - av_metadata_set2(&chapter->metadata, "title", val, - AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(&chapter->metadata, "title", val, + AV_DICT_DONT_STRDUP_VAL); } else return 0; @@ -67,7 +68,7 @@ static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val) } int -ff_vorbis_comment(AVFormatContext * as, AVMetadata **m, const uint8_t *buf, int size) +ff_vorbis_comment(AVFormatContext * as, AVDictionary **m, const uint8_t *buf, int size) { const uint8_t *p = buf; const uint8_t *end = buf + size; @@ -127,9 +128,9 @@ ff_vorbis_comment(AVFormatContext * as, AVMetadata **m, const uint8_t *buf, int ct[vl] = 0; if (!ogm_chapter(as, tt, ct)) - av_metadata_set2(m, tt, ct, - AV_METADATA_DONT_STRDUP_KEY | - AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(m, tt, ct, + AV_DICT_DONT_STRDUP_KEY | + AV_DICT_DONT_STRDUP_VAL); } } diff --git a/libavformat/oma.c b/libavformat/oma.c index f29b16a4d6..aac96d14e5 100644 --- a/libavformat/oma.c +++ b/libavformat/oma.c @@ -80,6 +80,8 @@ static int oma_read_header(AVFormatContext *s, ff_id3v2_read(s, ID3v2_EA3_MAGIC); ret = avio_read(s->pb, buf, EA3_HEADER_SIZE); + if (ret < EA3_HEADER_SIZE) + return -1; if (memcmp(buf, ((const uint8_t[]){'E', 'A', '3'}),3) || buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) { av_log(s, AV_LOG_ERROR, "Couldn't find the EA3 header !\n"); diff --git a/libavformat/options.c b/libavformat/options.c index a6f78817f4..ffd82ba207 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -49,8 +49,12 @@ static const AVOption options[]={ {"nofillin", "do not fill in missing values that can be exactly calculated", 0, FF_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_NOFILLIN }, INT_MIN, INT_MAX, D, "fflags"}, {"noparse", "disable AVParsers, this needs nofillin too", 0, FF_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_NOPARSE }, INT_MIN, INT_MAX, D, "fflags"}, {"igndts", "ignore dts", 0, FF_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_IGNDTS }, INT_MIN, INT_MAX, D, "fflags"}, -{"rtphint", "add rtp hinting", 0, FF_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_RTP_HINT }, INT_MIN, INT_MAX, E, "fflags"}, +#if FF_API_FLAG_RTP_HINT +{"rtphint", "add rtp hinting (deprecated, use the -movflags rtphint option instead)", 0, FF_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_RTP_HINT }, INT_MIN, INT_MAX, E, "fflags"}, +#endif {"sortdts", "try to interleave outputted packets by dts", 0, FF_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_SORT_DTS }, INT_MIN, INT_MAX, D, "fflags"}, +{"keepside", "dont merge side data", 0, FF_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_KEEP_SIDE_DATA }, INT_MIN, INT_MAX, D, "fflags"}, +{"latm", "enable RTP MP4A-LATM payload", 0, FF_OPT_TYPE_CONST, {.dbl = AVFMT_FLAG_MP4A_LATM }, INT_MIN, INT_MAX, E, "fflags"}, {"analyzeduration", "how many microseconds are analyzed to estimate duration", OFFSET(max_analyze_duration), FF_OPT_TYPE_INT, {.dbl = 5*AV_TIME_BASE }, 0, INT_MAX, D}, {"cryptokey", "decryption key", OFFSET(key), FF_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D}, {"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), FF_OPT_TYPE_INT, {.dbl = 1<<20 }, 0, INT_MAX, D}, @@ -58,6 +62,7 @@ static const AVOption options[]={ {"fdebug", "print specific debug info", OFFSET(debug), FF_OPT_TYPE_FLAGS, {.dbl = DEFAULT }, 0, INT_MAX, E|D, "fdebug"}, {"ts", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = FF_FDEBUG_TS }, INT_MIN, INT_MAX, E|D, "fdebug"}, {"max_delay", "maximum muxing or demuxing delay in microseconds", OFFSET(max_delay), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, 0, INT_MAX, E|D}, +{"fpsprobesize", "number of frames used to probe fps", OFFSET(fps_probe_size), FF_OPT_TYPE_INT, {.dbl = -1}, -1, INT_MAX-1, D}, {NULL}, }; diff --git a/libavformat/output-example.c b/libavformat/output-example.c deleted file mode 100644 index 1a429638d1..0000000000 --- a/libavformat/output-example.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Libavformat API example: Output a media file in any supported - * libavformat format. The default codecs are used. - * - * Copyright (c) 2003 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <math.h> - -#include "libavformat/avformat.h" -#include "libswscale/swscale.h" - -#undef exit - -/* 5 seconds stream duration */ -#define STREAM_DURATION 5.0 -#define STREAM_FRAME_RATE 25 /* 25 images/s */ -#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE)) -#define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */ - -static int sws_flags = SWS_BICUBIC; - -/**************************************************************/ -/* audio output */ - -float t, tincr, tincr2; -int16_t *samples; -uint8_t *audio_outbuf; -int audio_outbuf_size; -int audio_input_frame_size; - -/* - * add an audio output stream - */ -static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id) -{ - AVCodecContext *c; - AVStream *st; - - st = av_new_stream(oc, 1); - if (!st) { - fprintf(stderr, "Could not alloc stream\n"); - exit(1); - } - - c = st->codec; - c->codec_id = codec_id; - c->codec_type = AVMEDIA_TYPE_AUDIO; - - /* put sample parameters */ - c->sample_fmt = AV_SAMPLE_FMT_S16; - c->bit_rate = 64000; - c->sample_rate = 44100; - c->channels = 2; - - // some formats want stream headers to be separate - if(oc->oformat->flags & AVFMT_GLOBALHEADER) - c->flags |= CODEC_FLAG_GLOBAL_HEADER; - - return st; -} - -static void open_audio(AVFormatContext *oc, AVStream *st) -{ - AVCodecContext *c; - AVCodec *codec; - - c = st->codec; - - /* find the audio encoder */ - codec = avcodec_find_encoder(c->codec_id); - if (!codec) { - fprintf(stderr, "codec not found\n"); - exit(1); - } - - /* open it */ - if (avcodec_open(c, codec) < 0) { - fprintf(stderr, "could not open codec\n"); - exit(1); - } - - /* init signal generator */ - t = 0; - tincr = 2 * M_PI * 110.0 / c->sample_rate; - /* increment frequency by 110 Hz per second */ - tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; - - audio_outbuf_size = 10000; - audio_outbuf = av_malloc(audio_outbuf_size); - - /* ugly hack for PCM codecs (will be removed ASAP with new PCM - support to compute the input frame size in samples */ - if (c->frame_size <= 1) { - audio_input_frame_size = audio_outbuf_size / c->channels; - switch(st->codec->codec_id) { - case CODEC_ID_PCM_S16LE: - case CODEC_ID_PCM_S16BE: - case CODEC_ID_PCM_U16LE: - case CODEC_ID_PCM_U16BE: - audio_input_frame_size >>= 1; - break; - default: - break; - } - } else { - audio_input_frame_size = c->frame_size; - } - samples = av_malloc(audio_input_frame_size * 2 * c->channels); -} - -/* prepare a 16 bit dummy audio frame of 'frame_size' samples and - 'nb_channels' channels */ -static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels) -{ - int j, i, v; - int16_t *q; - - q = samples; - for(j=0;j<frame_size;j++) { - v = (int)(sin(t) * 10000); - for(i = 0; i < nb_channels; i++) - *q++ = v; - t += tincr; - tincr += tincr2; - } -} - -static void write_audio_frame(AVFormatContext *oc, AVStream *st) -{ - AVCodecContext *c; - AVPacket pkt; - av_init_packet(&pkt); - - c = st->codec; - - get_audio_frame(samples, audio_input_frame_size, c->channels); - - pkt.size= avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples); - - if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) - pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base); - pkt.flags |= AV_PKT_FLAG_KEY; - pkt.stream_index= st->index; - pkt.data= audio_outbuf; - - /* write the compressed frame in the media file */ - if (av_interleaved_write_frame(oc, &pkt) != 0) { - fprintf(stderr, "Error while writing audio frame\n"); - exit(1); - } -} - -static void close_audio(AVFormatContext *oc, AVStream *st) -{ - avcodec_close(st->codec); - - av_free(samples); - av_free(audio_outbuf); -} - -/**************************************************************/ -/* video output */ - -AVFrame *picture, *tmp_picture; -uint8_t *video_outbuf; -int frame_count, video_outbuf_size; - -/* add a video output stream */ -static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id) -{ - AVCodecContext *c; - AVStream *st; - - st = av_new_stream(oc, 0); - if (!st) { - fprintf(stderr, "Could not alloc stream\n"); - exit(1); - } - - c = st->codec; - c->codec_id = codec_id; - c->codec_type = AVMEDIA_TYPE_VIDEO; - - /* put sample parameters */ - c->bit_rate = 400000; - /* resolution must be a multiple of two */ - c->width = 352; - c->height = 288; - /* time base: this is the fundamental unit of time (in seconds) in terms - of which frame timestamps are represented. for fixed-fps content, - timebase should be 1/framerate and timestamp increments should be - identically 1. */ - c->time_base.den = STREAM_FRAME_RATE; - c->time_base.num = 1; - c->gop_size = 12; /* emit one intra frame every twelve frames at most */ - c->pix_fmt = STREAM_PIX_FMT; - if (c->codec_id == CODEC_ID_MPEG2VIDEO) { - /* just for testing, we also add B frames */ - c->max_b_frames = 2; - } - if (c->codec_id == CODEC_ID_MPEG1VIDEO){ - /* Needed to avoid using macroblocks in which some coeffs overflow. - This does not happen with normal video, it just happens here as - the motion of the chroma plane does not match the luma plane. */ - c->mb_decision=2; - } - // some formats want stream headers to be separate - if(oc->oformat->flags & AVFMT_GLOBALHEADER) - c->flags |= CODEC_FLAG_GLOBAL_HEADER; - - return st; -} - -static AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height) -{ - AVFrame *picture; - uint8_t *picture_buf; - int size; - - picture = avcodec_alloc_frame(); - if (!picture) - return NULL; - size = avpicture_get_size(pix_fmt, width, height); - picture_buf = av_malloc(size); - if (!picture_buf) { - av_free(picture); - return NULL; - } - avpicture_fill((AVPicture *)picture, picture_buf, - pix_fmt, width, height); - return picture; -} - -static void open_video(AVFormatContext *oc, AVStream *st) -{ - AVCodec *codec; - AVCodecContext *c; - - c = st->codec; - - /* find the video encoder */ - codec = avcodec_find_encoder(c->codec_id); - if (!codec) { - fprintf(stderr, "codec not found\n"); - exit(1); - } - - /* open the codec */ - if (avcodec_open(c, codec) < 0) { - fprintf(stderr, "could not open codec\n"); - exit(1); - } - - video_outbuf = NULL; - if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { - /* allocate output buffer */ - /* XXX: API change will be done */ - /* buffers passed into lav* can be allocated any way you prefer, - as long as they're aligned enough for the architecture, and - they're freed appropriately (such as using av_free for buffers - allocated with av_malloc) */ - video_outbuf_size = 200000; - video_outbuf = av_malloc(video_outbuf_size); - } - - /* allocate the encoded raw picture */ - picture = alloc_picture(c->pix_fmt, c->width, c->height); - if (!picture) { - fprintf(stderr, "Could not allocate picture\n"); - exit(1); - } - - /* if the output format is not YUV420P, then a temporary YUV420P - picture is needed too. It is then converted to the required - output format */ - tmp_picture = NULL; - if (c->pix_fmt != PIX_FMT_YUV420P) { - tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height); - if (!tmp_picture) { - fprintf(stderr, "Could not allocate temporary picture\n"); - exit(1); - } - } -} - -/* prepare a dummy image */ -static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height) -{ - int x, y, i; - - i = frame_index; - - /* Y */ - for(y=0;y<height;y++) { - for(x=0;x<width;x++) { - pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3; - } - } - - /* Cb and Cr */ - for(y=0;y<height/2;y++) { - for(x=0;x<width/2;x++) { - pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2; - pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5; - } - } -} - -static void write_video_frame(AVFormatContext *oc, AVStream *st) -{ - int out_size, ret; - AVCodecContext *c; - static struct SwsContext *img_convert_ctx; - - c = st->codec; - - if (frame_count >= STREAM_NB_FRAMES) { - /* no more frame to compress. The codec has a latency of a few - frames if using B frames, so we get the last frames by - passing the same picture again */ - } else { - if (c->pix_fmt != PIX_FMT_YUV420P) { - /* as we only generate a YUV420P picture, we must convert it - to the codec pixel format if needed */ - if (img_convert_ctx == NULL) { - img_convert_ctx = sws_getContext(c->width, c->height, - PIX_FMT_YUV420P, - c->width, c->height, - c->pix_fmt, - sws_flags, NULL, NULL, NULL); - if (img_convert_ctx == NULL) { - fprintf(stderr, "Cannot initialize the conversion context\n"); - exit(1); - } - } - fill_yuv_image(tmp_picture, frame_count, c->width, c->height); - sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize, - 0, c->height, picture->data, picture->linesize); - } else { - fill_yuv_image(picture, frame_count, c->width, c->height); - } - } - - - if (oc->oformat->flags & AVFMT_RAWPICTURE) { - /* raw video case. The API will change slightly in the near - futur for that */ - AVPacket pkt; - av_init_packet(&pkt); - - pkt.flags |= AV_PKT_FLAG_KEY; - pkt.stream_index= st->index; - pkt.data= (uint8_t *)picture; - pkt.size= sizeof(AVPicture); - - ret = av_interleaved_write_frame(oc, &pkt); - } else { - /* encode the image */ - out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture); - /* if zero size, it means the image was buffered */ - if (out_size > 0) { - AVPacket pkt; - av_init_packet(&pkt); - - if (c->coded_frame->pts != AV_NOPTS_VALUE) - pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base); - if(c->coded_frame->key_frame) - pkt.flags |= AV_PKT_FLAG_KEY; - pkt.stream_index= st->index; - pkt.data= video_outbuf; - pkt.size= out_size; - - /* write the compressed frame in the media file */ - ret = av_interleaved_write_frame(oc, &pkt); - } else { - ret = 0; - } - } - if (ret != 0) { - fprintf(stderr, "Error while writing video frame\n"); - exit(1); - } - frame_count++; -} - -static void close_video(AVFormatContext *oc, AVStream *st) -{ - avcodec_close(st->codec); - av_free(picture->data[0]); - av_free(picture); - if (tmp_picture) { - av_free(tmp_picture->data[0]); - av_free(tmp_picture); - } - av_free(video_outbuf); -} - -/**************************************************************/ -/* media file output */ - -int main(int argc, char **argv) -{ - const char *filename; - AVOutputFormat *fmt; - AVFormatContext *oc; - AVStream *audio_st, *video_st; - double audio_pts, video_pts; - int i; - - /* initialize libavcodec, and register all codecs and formats */ - av_register_all(); - - if (argc != 2) { - printf("usage: %s output_file\n" - "API example program to output a media file with libavformat.\n" - "The output format is automatically guessed according to the file extension.\n" - "Raw images can also be output by using '%%d' in the filename\n" - "\n", argv[0]); - exit(1); - } - - filename = argv[1]; - - /* allocate the output media context */ - oc = avformat_alloc_output_context(NULL, NULL, filename); - if (!oc) { - printf("Could not deduce output format from file extension: using MPEG.\n"); - oc = avformat_alloc_output_context("mpeg", NULL, filename); - } - if (!oc) { - exit(1); - } - fmt= oc->oformat; - - /* add the audio and video streams using the default format codecs - and initialize the codecs */ - video_st = NULL; - audio_st = NULL; - if (fmt->video_codec != CODEC_ID_NONE) { - video_st = add_video_stream(oc, fmt->video_codec); - } - if (fmt->audio_codec != CODEC_ID_NONE) { - audio_st = add_audio_stream(oc, fmt->audio_codec); - } - - av_dump_format(oc, 0, filename, 1); - - /* now that all the parameters are set, we can open the audio and - video codecs and allocate the necessary encode buffers */ - if (video_st) - open_video(oc, video_st); - if (audio_st) - open_audio(oc, audio_st); - - /* open the output file, if needed */ - if (!(fmt->flags & AVFMT_NOFILE)) { - if (avio_open(&oc->pb, filename, AVIO_WRONLY) < 0) { - fprintf(stderr, "Could not open '%s'\n", filename); - exit(1); - } - } - - /* write the stream header, if any */ - av_write_header(oc); - - for(;;) { - /* compute current audio and video time */ - if (audio_st) - audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den; - else - audio_pts = 0.0; - - if (video_st) - video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den; - else - video_pts = 0.0; - - if ((!audio_st || audio_pts >= STREAM_DURATION) && - (!video_st || video_pts >= STREAM_DURATION)) - break; - - /* write interleaved audio and video frames */ - if (!video_st || (video_st && audio_st && audio_pts < video_pts)) { - write_audio_frame(oc, audio_st); - } else { - write_video_frame(oc, video_st); - } - } - - /* write the trailer, if any. the trailer must be written - * before you close the CodecContexts open when you wrote the - * header; otherwise write_trailer may try to use memory that - * was freed on av_codec_close() */ - av_write_trailer(oc); - - /* close each codec */ - if (video_st) - close_video(oc, video_st); - if (audio_st) - close_audio(oc, audio_st); - - /* free the streams */ - for(i = 0; i < oc->nb_streams; i++) { - av_freep(&oc->streams[i]->codec); - av_freep(&oc->streams[i]); - } - - if (!(fmt->flags & AVFMT_NOFILE)) { - /* close the output file */ - avio_close(oc->pb); - } - - /* free the stream */ - av_free(oc); - - return 0; -} diff --git a/libavformat/pcmdec.c b/libavformat/pcmdec.c index 6441d89c5c..ab3b739ccb 100644 --- a/libavformat/pcmdec.c +++ b/libavformat/pcmdec.c @@ -50,7 +50,7 @@ static int raw_read_packet(AVFormatContext *s, AVPacket *pkt) AVInputFormat ff_pcm_ ## name ## _demuxer = {\ #name,\ NULL_IF_CONFIG_SMALL(long_name),\ - 0,\ + sizeof(RawAudioDemuxerContext),\ NULL,\ ff_raw_read_header,\ raw_read_packet,\ @@ -59,6 +59,7 @@ AVInputFormat ff_pcm_ ## name ## _demuxer = {\ .flags= AVFMT_GENERIC_INDEX,\ .extensions = ext,\ .value = codec,\ + .priv_class = &ff_rawaudio_demuxer_class,\ }; PCMDEF(f64be, "PCM 64 bit floating-point big-endian format", diff --git a/libavformat/r3d.c b/libavformat/r3d.c index 5e027d158b..af74a9ee56 100644 --- a/libavformat/r3d.c +++ b/libavformat/r3d.c @@ -22,6 +22,7 @@ //#define DEBUG #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" typedef struct { @@ -43,7 +44,7 @@ static int read_atom(AVFormatContext *s, Atom *atom) if (atom->size < 8) return -1; atom->tag = avio_rl32(s->pb); - av_dlog(s, "atom %d %.4s offset %#llx\n", + av_dlog(s, "atom %u %.4s offset %#"PRIx64"\n", atom->size, (char*)&atom->tag, atom->offset); return atom->size; } @@ -52,7 +53,8 @@ static int r3d_read_red1(AVFormatContext *s) { AVStream *st = av_new_stream(s, 0); char filename[258]; - int tmp, tmp2; + int tmp; + int av_unused tmp2; if (!st) return AVERROR(ENOMEM); @@ -97,7 +99,7 @@ static int r3d_read_red1(AVFormatContext *s) avio_read(s->pb, filename, 257); filename[sizeof(filename)-1] = 0; - av_metadata_set2(&st->metadata, "filename", filename, 0); + av_dict_set(&st->metadata, "filename", filename, 0); av_dlog(s, "filename %s\n", filename); av_dlog(s, "resolution %dx%d\n", st->codec->width, st->codec->height); @@ -131,7 +133,7 @@ static int r3d_read_rdvo(AVFormatContext *s, Atom *atom) if (st->codec->time_base.den) st->duration = (uint64_t)r3d->video_offsets_count* st->time_base.den*st->codec->time_base.num/st->codec->time_base.den; - av_dlog(s, "duration %lld\n", st->duration); + av_dlog(s, "duration %"PRId64"\n", st->duration); return 0; } @@ -139,7 +141,7 @@ static int r3d_read_rdvo(AVFormatContext *s, Atom *atom) static void r3d_read_reos(AVFormatContext *s) { R3DContext *r3d = s->priv_data; - int tmp; + int av_unused tmp; r3d->rdvo_offset = avio_rb32(s->pb); avio_rb32(s->pb); // rdvs offset @@ -176,7 +178,7 @@ static int r3d_read_header(AVFormatContext *s, AVFormatParameters *ap) } s->data_offset = avio_tell(s->pb); - av_dlog(s, "data offset %#llx\n", s->data_offset); + av_dlog(s, "data offset %#"PRIx64"\n", s->data_offset); if (!s->pb->seekable) return 0; // find REOB/REOF/REOS to load index @@ -209,7 +211,8 @@ static int r3d_read_header(AVFormatContext *s, AVFormatParameters *ap) static int r3d_read_redv(AVFormatContext *s, AVPacket *pkt, Atom *atom) { AVStream *st = s->streams[0]; - int tmp, tmp2; + int tmp; + int av_unused tmp2; uint64_t pos = avio_tell(s->pb); unsigned dts; int ret; @@ -255,7 +258,7 @@ static int r3d_read_redv(AVFormatContext *s, AVPacket *pkt, Atom *atom) if (st->codec->time_base.den) pkt->duration = (uint64_t)st->time_base.den* st->codec->time_base.num/st->codec->time_base.den; - av_dlog(s, "pkt dts %lld duration %d\n", pkt->dts, pkt->duration); + av_dlog(s, "pkt dts %"PRId64" duration %d\n", pkt->dts, pkt->duration); return 0; } @@ -263,7 +266,8 @@ static int r3d_read_redv(AVFormatContext *s, AVPacket *pkt, Atom *atom) static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom) { AVStream *st = s->streams[1]; - int tmp, tmp2, samples, size; + int av_unused tmp, tmp2; + int samples, size; uint64_t pos = avio_tell(s->pb); unsigned dts; int ret; @@ -299,7 +303,7 @@ static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom) pkt->stream_index = 1; pkt->dts = dts; pkt->duration = av_rescale(samples, st->time_base.den, st->codec->sample_rate); - av_dlog(s, "pkt dts %lld duration %d samples %d sample rate %d\n", + av_dlog(s, "pkt dts %"PRId64" duration %d samples %d sample rate %d\n", pkt->dts, pkt->duration, samples, st->codec->sample_rate); return 0; @@ -356,7 +360,8 @@ static int r3d_seek(AVFormatContext *s, int stream_index, int64_t sample_time, i frame_num = sample_time*st->codec->time_base.den/ ((int64_t)st->codec->time_base.num*st->time_base.den); - av_dlog(s, "seek frame num %d timestamp %lld\n", frame_num, sample_time); + av_dlog(s, "seek frame num %d timestamp %"PRId64"\n", + frame_num, sample_time); if (frame_num < r3d->video_offsets_count) { avio_seek(s->pb, r3d->video_offsets_count, SEEK_SET); diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c index 0387e3d266..a4e009b7e0 100644 --- a/libavformat/rawdec.c +++ b/libavformat/rawdec.c @@ -23,6 +23,9 @@ #include "avformat.h" #include "avio_internal.h" #include "rawdec.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" /* raw input */ int ff_raw_read_header(AVFormatContext *s, AVFormatParameters *ap) @@ -43,26 +46,64 @@ int ff_raw_read_header(AVFormatContext *s, AVFormatParameters *ap) st->codec->codec_id = id; switch(st->codec->codec_type) { - case AVMEDIA_TYPE_AUDIO: - st->codec->sample_rate = ap->sample_rate; - if(ap->channels) st->codec->channels = ap->channels; - else st->codec->channels = 1; + case AVMEDIA_TYPE_AUDIO: { + RawAudioDemuxerContext *s1 = s->priv_data; + +#if FF_API_FORMAT_PARAMETERS + if (ap->sample_rate) + st->codec->sample_rate = ap->sample_rate; + if (ap->channels) + st->codec->channels = ap->channels; + else st->codec->channels = 1; +#endif + + if (s1->sample_rate) + st->codec->sample_rate = s1->sample_rate; + if (s1->channels) + st->codec->channels = s1->channels; + st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id); assert(st->codec->bits_per_coded_sample > 0); st->codec->block_align = st->codec->bits_per_coded_sample*st->codec->channels/8; av_set_pts_info(st, 64, 1, st->codec->sample_rate); break; - case AVMEDIA_TYPE_VIDEO: - if(ap->time_base.num) - av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den); - else - av_set_pts_info(st, 64, 1, 25); - st->codec->width = ap->width; - st->codec->height = ap->height; - st->codec->pix_fmt = ap->pix_fmt; - if(st->codec->pix_fmt == PIX_FMT_NONE) - st->codec->pix_fmt= PIX_FMT_YUV420P; - break; + } + case AVMEDIA_TYPE_VIDEO: { + FFRawVideoDemuxerContext *s1 = s->priv_data; + int width = 0, height = 0, ret = 0; + enum PixelFormat pix_fmt; + AVRational framerate; + + if (s1->video_size && (ret = av_parse_video_size(&width, &height, s1->video_size)) < 0) { + av_log(s, AV_LOG_ERROR, "Couldn't parse video size.\n"); + goto fail; + } + if ((pix_fmt = av_get_pix_fmt(s1->pixel_format)) == PIX_FMT_NONE) { + av_log(s, AV_LOG_ERROR, "No such pixel format: %s.\n", s1->pixel_format); + ret = AVERROR(EINVAL); + goto fail; + } + if ((ret = av_parse_video_rate(&framerate, s1->framerate)) < 0) { + av_log(s, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s1->framerate); + goto fail; + } +#if FF_API_FORMAT_PARAMETERS + if (ap->width > 0) + width = ap->width; + if (ap->height > 0) + height = ap->height; + if (ap->pix_fmt) + pix_fmt = ap->pix_fmt; + if (ap->time_base.num) + framerate = (AVRational){ap->time_base.den, ap->time_base.num}; +#endif + av_set_pts_info(st, 64, framerate.den, framerate.num); + st->codec->width = width; + st->codec->height = height; + st->codec->pix_fmt = pix_fmt; +fail: + return ret; + } default: return -1; } @@ -111,45 +152,82 @@ int ff_raw_video_read_header(AVFormatContext *s, AVFormatParameters *ap) { AVStream *st; + FFRawVideoDemuxerContext *s1 = s->priv_data; + AVRational framerate; + int ret = 0; + st = av_new_stream(s, 0); - if (!st) - return AVERROR(ENOMEM); + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = s->iformat->value; st->need_parsing = AVSTREAM_PARSE_FULL; - /* for MJPEG, specify frame rate */ - /* for MPEG-4 specify it, too (most MPEG-4 streams do not have the fixed_vop_rate set ...)*/ - if (ap->time_base.num) { - st->codec->time_base= ap->time_base; - } else if ( st->codec->codec_id == CODEC_ID_MJPEG || - st->codec->codec_id == CODEC_ID_MPEG4 || - st->codec->codec_id == CODEC_ID_DIRAC || - st->codec->codec_id == CODEC_ID_DNXHD || - st->codec->codec_id == CODEC_ID_VC1 || - st->codec->codec_id == CODEC_ID_H264) { - st->codec->time_base= (AVRational){1,25}; + if ((ret = av_parse_video_rate(&framerate, s1->framerate)) < 0) { + av_log(s, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s1->framerate); + goto fail; } +#if FF_API_FORMAT_PARAMETERS + if (ap->time_base.num) + framerate = (AVRational){ap->time_base.den, ap->time_base.num}; +#endif + + st->codec->time_base = (AVRational){framerate.den, framerate.num}; av_set_pts_info(st, 64, 1, 1200000); - return 0; +fail: + return ret; } /* Note: Do not forget to add new entries to the Makefile as well. */ +static const AVOption audio_options[] = { + { "sample_rate", "", offsetof(RawAudioDemuxerContext, sample_rate), FF_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "channels", "", offsetof(RawAudioDemuxerContext, channels), FF_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +const AVClass ff_rawaudio_demuxer_class = { + .class_name = "rawaudio demuxer", + .item_name = av_default_item_name, + .option = audio_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +#define OFFSET(x) offsetof(FFRawVideoDemuxerContext, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +static const AVOption video_options[] = { + { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "pixel_format", "", OFFSET(pixel_format), FF_OPT_TYPE_STRING, {.str = "yuv420p"}, 0, 0, DEC }, + { "framerate", "", OFFSET(framerate), FF_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC }, + { NULL }, +}; +#undef OFFSET +#undef DEC + +const AVClass ff_rawvideo_demuxer_class = { + .class_name = "rawvideo demuxer", + .item_name = av_default_item_name, + .option = video_options, + .version = LIBAVUTIL_VERSION_INT, +}; + #if CONFIG_G722_DEMUXER AVInputFormat ff_g722_demuxer = { "g722", NULL_IF_CONFIG_SMALL("raw G.722"), - 0, + sizeof(RawAudioDemuxerContext), NULL, ff_raw_read_header, ff_raw_read_partial_packet, .flags= AVFMT_GENERIC_INDEX, .extensions = "g722,722", .value = CODEC_ID_ADPCM_G722, + .priv_class = &ff_rawaudio_demuxer_class, }; #endif @@ -168,17 +246,7 @@ AVInputFormat ff_gsm_demuxer = { #endif #if CONFIG_MJPEG_DEMUXER -AVInputFormat ff_mjpeg_demuxer = { - "mjpeg", - NULL_IF_CONFIG_SMALL("raw MJPEG video"), - 0, - NULL, - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, - .extensions = "mjpg,mjpeg", - .value = CODEC_ID_MJPEG, -}; +FF_DEF_RAWVIDEO_DEMUXER(mjpeg, "raw MJPEG video", NULL, "mjpg,mjpeg", CODEC_ID_MJPEG) #endif #if CONFIG_MLP_DEMUXER @@ -224,14 +292,5 @@ AVInputFormat ff_shorten_demuxer = { #endif #if CONFIG_VC1_DEMUXER -AVInputFormat ff_vc1_demuxer = { - "vc1", - NULL_IF_CONFIG_SMALL("raw VC-1"), - 0, - NULL /* vc1_probe */, - ff_raw_video_read_header, - ff_raw_read_partial_packet, - .extensions = "vc1", - .value = CODEC_ID_VC1, -}; +FF_DEF_RAWVIDEO_DEMUXER(vc1, "raw VC-1", NULL, "vc1", CODEC_ID_VC1) #endif diff --git a/libavformat/rawdec.h b/libavformat/rawdec.h index 0b0cf1beef..6cb5af2b0a 100644 --- a/libavformat/rawdec.h +++ b/libavformat/rawdec.h @@ -23,6 +23,23 @@ #define AVFORMAT_RAWDEC_H #include "avformat.h" +#include "libavutil/log.h" + +typedef struct RawAudioDemuxerContext { + AVClass *class; + int sample_rate; + int channels; +} RawAudioDemuxerContext; + +typedef struct FFRawVideoDemuxerContext { + const AVClass *class; /**< Class for private options. */ + char *video_size; /**< String describing video size, set by a private option. */ + char *pixel_format; /**< Set by a private option. */ + char *framerate; /**< String describing framerate, set by a private option. */ +} FFRawVideoDemuxerContext; + +extern const AVClass ff_rawaudio_demuxer_class; +extern const AVClass ff_rawvideo_demuxer_class; int ff_raw_read_header(AVFormatContext *s, AVFormatParameters *ap); @@ -32,4 +49,18 @@ int ff_raw_audio_read_header(AVFormatContext *s, AVFormatParameters *ap); int ff_raw_video_read_header(AVFormatContext *s, AVFormatParameters *ap); +#define FF_DEF_RAWVIDEO_DEMUXER(shortname, longname, probe, ext, id)\ +AVInputFormat ff_ ## shortname ## _demuxer = {\ + .name = #shortname,\ + .long_name = NULL_IF_CONFIG_SMALL(longname),\ + .read_probe = probe,\ + .read_header = ff_raw_video_read_header,\ + .read_packet = ff_raw_read_partial_packet,\ + .extensions = ext,\ + .flags = AVFMT_GENERIC_INDEX,\ + .value = id,\ + .priv_data_size = sizeof(FFRawVideoDemuxerContext),\ + .priv_class = &ff_rawvideo_demuxer_class,\ +}; + #endif /* AVFORMAT_RAWDEC_H */ diff --git a/libavformat/rawvideodec.c b/libavformat/rawvideodec.c index 127119f18a..36f5d954ae 100644 --- a/libavformat/rawvideodec.c +++ b/libavformat/rawvideodec.c @@ -47,11 +47,12 @@ static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt) AVInputFormat ff_rawvideo_demuxer = { "rawvideo", NULL_IF_CONFIG_SMALL("raw video format"), - 0, + sizeof(FFRawVideoDemuxerContext), NULL, ff_raw_read_header, rawvideo_read_packet, .flags= AVFMT_GENERIC_INDEX, .extensions = "yuv,cif,qcif,rgb", .value = CODEC_ID_RAWVIDEO, + .priv_class = &ff_rawvideo_demuxer_class, }; diff --git a/libavformat/riff.c b/libavformat/riff.c index 833a6bf9e8..544c29f116 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -250,6 +250,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') }, { CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') }, { CODEC_ID_CAVS, MKTAG('C', 'A', 'V', 'S') }, + { CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, { CODEC_ID_JPEG2000, MKTAG('M', 'J', '2', 'C') }, { CODEC_ID_VMNC, MKTAG('V', 'M', 'n', 'c') }, { CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') }, @@ -536,6 +537,7 @@ int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) } codec->extradata_size = cbSize; if (cbSize > 0) { + av_free(codec->extradata); codec->extradata = av_mallocz(codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!codec->extradata) return AVERROR(ENOMEM); diff --git a/libavformat/rl2.c b/libavformat/rl2.c index 93d4c34459..e41406791e 100644 --- a/libavformat/rl2.c +++ b/libavformat/rl2.c @@ -80,8 +80,6 @@ static av_cold int rl2_read_header(AVFormatContext *s, unsigned int audio_frame_counter = 0; unsigned int video_frame_counter = 0; unsigned int back_size; - int data_size; - unsigned short encoding_method; unsigned short sound_rate; unsigned short rate; unsigned short channels; @@ -98,14 +96,14 @@ static av_cold int rl2_read_header(AVFormatContext *s, avio_skip(pb,4); /* skip FORM tag */ back_size = avio_rl32(pb); /**< get size of the background frame */ signature = avio_rb32(pb); - data_size = avio_rb32(pb); + avio_skip(pb, 4); /* data size */ frame_count = avio_rl32(pb); /* disallow back_sizes and frame_counts that may lead to overflows later */ if(back_size > INT_MAX/2 || frame_count > INT_MAX / sizeof(uint32_t)) return AVERROR_INVALIDDATA; - encoding_method = avio_rl16(pb); + avio_skip(pb, 2); /* encoding mentod */ sound_rate = avio_rl16(pb); rate = avio_rl16(pb); channels = avio_rl16(pb); diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index 6fb362473e..c2eee815c2 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -21,6 +21,7 @@ #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #include "riff.h" #include "rm.h" @@ -104,7 +105,7 @@ static void rm_read_metadata(AVFormatContext *s, int wide) for (i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { int len = wide ? avio_rb16(s->pb) : avio_r8(s->pb); get_strl(s->pb, buf, sizeof(buf), len); - av_metadata_set2(&s->metadata, ff_rm_metadata[i], buf, 0); + av_dict_set(&s->metadata, ff_rm_metadata[i], buf, 0); } } @@ -280,7 +281,7 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb, if (rm_read_audio_stream_info(s, pb, st, rst, 0)) return -1; } else { - int fps, fps2; + int fps; if (avio_rl32(pb) != MKTAG('V', 'I', 'D', 'O')) { fail1: av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n"); @@ -298,7 +299,7 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb, fps= avio_rb16(pb); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; avio_rb32(pb); - fps2= avio_rb16(pb); + avio_skip(pb, 2); avio_rb16(pb); if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (avio_tell(pb) - codec_pos))) < 0) diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c index e08b677987..575d895a6a 100644 --- a/libavformat/rmenc.c +++ b/libavformat/rmenc.c @@ -21,6 +21,7 @@ #include "avformat.h" #include "avio_internal.h" #include "rm.h" +#include "libavutil/dict.h" typedef struct { int nb_packets; @@ -71,7 +72,7 @@ static int rv10_write_header(AVFormatContext *ctx, const char *desc, *mimetype; int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i; int bit_rate, v, duration, flags, data_pos; - AVMetadataTag *tag; + AVDictionaryEntry *tag; start_ptr = s->buf_ptr; @@ -127,13 +128,13 @@ static int rv10_write_header(AVFormatContext *ctx, ffio_wfourcc(s,"CONT"); size = 4 * 2 + 10; for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { - tag = av_metadata_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); + tag = av_dict_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); if(tag) size += strlen(tag->value); } avio_wb32(s,size); avio_wb16(s,0); for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { - tag = av_metadata_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); + tag = av_dict_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); put_str(s, tag ? tag->value : ""); } diff --git a/libavformat/rpl.c b/libavformat/rpl.c index 9702fc7035..151893cdd7 100644 --- a/libavformat/rpl.c +++ b/libavformat/rpl.c @@ -20,6 +20,7 @@ */ #include "libavutil/avstring.h" +#include "libavutil/dict.h" #include "avformat.h" #include <stdlib.h> @@ -131,11 +132,11 @@ static int rpl_read_header(AVFormatContext *s, AVFormatParameters *ap) // for the text in a few cases; samples needed.) error |= read_line(pb, line, sizeof(line)); // ARMovie error |= read_line(pb, line, sizeof(line)); // movie name - av_metadata_set2(&s->metadata, "title" , line, 0); + av_dict_set(&s->metadata, "title" , line, 0); error |= read_line(pb, line, sizeof(line)); // date/copyright - av_metadata_set2(&s->metadata, "copyright", line, 0); + av_dict_set(&s->metadata, "copyright", line, 0); error |= read_line(pb, line, sizeof(line)); // author and other - av_metadata_set2(&s->metadata, "author" , line, 0); + av_dict_set(&s->metadata, "author" , line, 0); // video headers vst = av_new_stream(s, 0); @@ -299,9 +300,9 @@ static int rpl_read_packet(AVFormatContext *s, AVPacket *pkt) stream->codec->codec_tag == 124) { // We have to split Escape 124 frames because there are // multiple frames per chunk in Escape 124 samples. - uint32_t frame_size, frame_flags; + uint32_t frame_size; - frame_flags = avio_rl32(pb); + avio_skip(pb, 4); /* flags */ frame_size = avio_rl32(pb); if (avio_seek(pb, -8, SEEK_CUR) < 0) return AVERROR(EIO); diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c index 53c6a5fe19..4b6d549f74 100644 --- a/libavformat/rtmppkt.c +++ b/libavformat/rtmppkt.c @@ -233,9 +233,11 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, int timestamp, int size) { - pkt->data = av_malloc(size); - if (!pkt->data) - return AVERROR(ENOMEM); + if (size) { + pkt->data = av_malloc(size); + if (!pkt->data) + return AVERROR(ENOMEM); + } pkt->data_size = size; pkt->channel_id = channel_id; pkt->type = type; diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 94361ca80d..3701a77176 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -690,7 +690,7 @@ static int get_packet(URLContext *s, int for_header) return AVERROR_EOF; for (;;) { - RTMPPacket rpkt; + RTMPPacket rpkt = { 0 }; if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt, rt->chunk_size, rt->prev_pkt[0])) <= 0) { if (ret == 0) { diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 0a9a8bc8d6..9fc30d7b66 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -321,7 +321,7 @@ int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count) avio_flush(pb); len = avio_close_dyn_buf(pb, &buf); if ((len > 0) && buf) { - int result; + int av_unused result; av_dlog(s->ic, "sending %d bytes of RR\n", len); result= ffurl_write(s->rtp_ctx, buf, len); av_dlog(s->ic, "result from ffurl_write: %d\n", result); diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c index b2ac2b7ac0..58c9068a87 100644 --- a/libavformat/rtpdec_asf.c +++ b/libavformat/rtpdec_asf.c @@ -113,7 +113,7 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p) ret = av_open_input_stream(&rt->asf_ctx, &pb, "", &ff_asf_demuxer, NULL); if (ret < 0) return ret; - av_metadata_copy(&s->metadata, rt->asf_ctx->metadata, 0); + av_dict_copy(&s->metadata, rt->asf_ctx->metadata, 0); rt->asf_pb_pos = avio_tell(&pb); av_free(buf); rt->asf_ctx->pb = NULL; diff --git a/libavformat/rtpdec_latm.c b/libavformat/rtpdec_latm.c index 2b366a0dc2..4bf2c3fb23 100644 --- a/libavformat/rtpdec_latm.c +++ b/libavformat/rtpdec_latm.c @@ -108,8 +108,7 @@ static int parse_fmtp_config(AVStream *st, char *value) int len = ff_hex_to_data(NULL, value), i, ret = 0; GetBitContext gb; uint8_t *config; - int audio_mux_version, same_time_framing, num_sub_frames, - num_programs, num_layers; + int audio_mux_version, same_time_framing, num_programs, num_layers; /* Pad this buffer, too, to avoid out of bounds reads with get_bits below */ config = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE); @@ -119,7 +118,7 @@ static int parse_fmtp_config(AVStream *st, char *value) init_get_bits(&gb, config, len*8); audio_mux_version = get_bits(&gb, 1); same_time_framing = get_bits(&gb, 1); - num_sub_frames = get_bits(&gb, 6); + skip_bits(&gb, 6); /* num_sub_frames */ num_programs = get_bits(&gb, 4); num_layers = get_bits(&gb, 3); if (audio_mux_version != 0 || same_time_framing != 1 || num_programs != 0 || diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 71ccdabf4a..60629b098b 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -23,11 +23,24 @@ #include "mpegts.h" #include "internal.h" #include "libavutil/random_seed.h" +#include "libavutil/opt.h" #include "rtpenc.h" //#define DEBUG +static const AVOption options[] = { + FF_RTP_FLAG_OPTS(RTPMuxContext, flags), + { NULL }, +}; + +static const AVClass rtp_muxer_class = { + .class_name = "RTP muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + #define RTCP_SR_SIZE 28 static int is_supported(enum CodecID id) @@ -404,7 +417,10 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) ff_rtp_send_mpegvideo(s1, pkt->data, size); break; case CODEC_ID_AAC: - ff_rtp_send_aac(s1, pkt->data, size); + if (s->flags & FF_RTP_FLAG_MP4A_LATM) + ff_rtp_send_latm(s1, pkt->data, size); + else + ff_rtp_send_aac(s1, pkt->data, size); break; case CODEC_ID_AMR_NB: case CODEC_ID_AMR_WB: @@ -455,4 +471,5 @@ AVOutputFormat ff_rtp_muxer = { rtp_write_header, rtp_write_packet, rtp_write_trailer, + .priv_class = &rtp_muxer_class, }; diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.h index b9663c55b0..cba0d02d91 100644 --- a/libavformat/rtpenc.h +++ b/libavformat/rtpenc.h @@ -25,6 +25,7 @@ #include "rtp.h" struct RTPMuxContext { + const AVClass *av_class; AVFormatContext *ic; AVStream *st; int payload_type; @@ -56,15 +57,24 @@ struct RTPMuxContext { * (1, 2 or 4) */ int nal_length_size; + + int flags; }; typedef struct RTPMuxContext RTPMuxContext; +#define FF_RTP_FLAG_MP4A_LATM 1 + +#define FF_RTP_FLAG_OPTS(ctx, fieldname) \ + { "rtpflags", "RTP muxer flags", offsetof(ctx, fieldname), FF_OPT_TYPE_FLAGS, {.dbl = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \ + { "latm", "Use MP4A-LATM packetization instead of MPEG4-GENERIC for AAC", 0, FF_OPT_TYPE_CONST, {.dbl = FF_RTP_FLAG_MP4A_LATM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" } \ + void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m); void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_h263(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size); +void ff_rtp_send_latm(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_amr(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size); void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size); diff --git a/libavformat/rtpenc_chain.c b/libavformat/rtpenc_chain.c index bd3d1a875d..7f1a8868eb 100644 --- a/libavformat/rtpenc_chain.c +++ b/libavformat/rtpenc_chain.c @@ -23,6 +23,7 @@ #include "avio_internal.h" #include "rtpenc_chain.h" #include "avio_internal.h" +#include "libavutil/opt.h" AVFormatContext *ff_rtp_chain_mux_open(AVFormatContext *s, AVStream *st, URLContext *handle, int packet_size) @@ -48,6 +49,14 @@ AVFormatContext *ff_rtp_chain_mux_open(AVFormatContext *s, AVStream *st, rtpctx->max_delay = s->max_delay; /* Copy other stream parameters. */ rtpctx->streams[0]->sample_aspect_ratio = st->sample_aspect_ratio; + rtpctx->flags |= s->flags & AVFMT_FLAG_MP4A_LATM; + + av_set_parameters(rtpctx, NULL); + /* Copy the rtpflags values straight through */ + if (s->oformat->priv_class && + av_find_opt(s->priv_data, "rtpflags", NULL, 0, 0)) + av_set_int(rtpctx->priv_data, "rtpflags", + av_get_int(s->priv_data, "rtpflags", NULL)); /* Set the synchronized start time. */ rtpctx->start_time_realtime = s->start_time_realtime; diff --git a/libavformat/rtpenc_h264.c b/libavformat/rtpenc_h264.c index 697def61c2..11074d0d51 100644 --- a/libavformat/rtpenc_h264.c +++ b/libavformat/rtpenc_h264.c @@ -29,6 +29,24 @@ #include "avc.h" #include "rtpenc.h" +static const uint8_t *avc_mp4_find_startcode(const uint8_t *start, const uint8_t *end, int nal_length_size) +{ + int res = 0; + + if (end - start < nal_length_size) { + return NULL; + } + while (nal_length_size--) { + res = (res << 8) | *start++; + } + + if (end - start < res) { + return NULL; + } + + return res + start; +} + static void nal_send(AVFormatContext *s1, const uint8_t *buf, int size, int last) { RTPMuxContext *s = s1->priv_data; @@ -66,12 +84,20 @@ void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size) RTPMuxContext *s = s1->priv_data; s->timestamp = s->cur_timestamp; - r = ff_avc_find_startcode(buf1, buf1 + size); + r = s->nal_length_size ? (avc_mp4_find_startcode(buf1, buf1 + size, s->nal_length_size) ? buf1 : buf1 + size) : ff_avc_find_startcode(buf1, buf1 + size); while (r < buf1 + size) { const uint8_t *r1; - while(!*(r++)); - r1 = ff_avc_find_startcode(r, buf1 + size); + if (s->nal_length_size) { + r1 = avc_mp4_find_startcode(r, buf1 + size, s->nal_length_size); + if (!r1) { + r1 = buf1 + size; + } + r += s->nal_length_size; + } else { + while(!*(r++)); + r1 = ff_avc_find_startcode(r, buf1 + size); + } nal_send(s1, r, r1 - r, (r1 == buf1 + size)); r = r1; } diff --git a/libavformat/rtpenc_latm.c b/libavformat/rtpenc_latm.c new file mode 100644 index 0000000000..4430c44afe --- /dev/null +++ b/libavformat/rtpenc_latm.c @@ -0,0 +1,61 @@ +/* + * RTP Packetization of MPEG-4 Audio (RFC 3016) + * Copyright (c) 2011 Juan Carlos Rodriguez <ing.juancarlosrodriguez@hotmail.com> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "rtpenc.h" + +void ff_rtp_send_latm(AVFormatContext *s1, const uint8_t *buff, int size) +{ + /* MP4A-LATM + * The RTP payload format specification is described in RFC 3016 + * The encoding specifications are provided in ISO/IEC 14496-3 */ + + RTPMuxContext *s = s1->priv_data; + int header_size; + int offset = 0; + int len = 0; + + /* skip ADTS header, if present */ + if ((s1->streams[0]->codec->extradata_size) == 0) { + size -= 7; + buff += 7; + } + + /* PayloadLengthInfo() */ + header_size = size/0xFF + 1; + memset(s->buf, 0xFF, header_size - 1); + s->buf[header_size - 1] = size % 0xFF; + + s->timestamp = s->cur_timestamp; + + /* PayloadMux() */ + while (size > 0) { + len = FFMIN(size, s->max_payload_size - (!offset ? header_size : 0)); + size -= len; + if (!offset) { + memcpy(s->buf + header_size, buff, len); + ff_rtp_send_data(s1, s->buf, header_size + len, !size); + } else { + ff_rtp_send_data(s1, buff + offset, len, !size); + } + offset += len; + } +} diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 74e4b31f43..f5a638423f 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -24,6 +24,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/parseutils.h" #include "libavutil/random_seed.h" +#include "libavutil/dict.h" #include "avformat.h" #include "avio_internal.h" @@ -45,7 +46,6 @@ #include "url.h" //#define DEBUG -//#define DEBUG_RTP_TCP /* Timeout values for socket poll, in ms, * and read_packet(), in seconds */ @@ -282,11 +282,11 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } break; case 's': - av_metadata_set2(&s->metadata, "title", p, 0); + av_dict_set(&s->metadata, "title", p, 0); break; case 'i': if (s->nb_streams == 0) { - av_metadata_set2(&s->metadata, "comment", p, 0); + av_dict_set(&s->metadata, "comment", p, 0); break; } break; @@ -860,9 +860,7 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, q = buf; for (;;) { ret = ffurl_read_complete(rt->rtsp_hd, &ch, 1); -#ifdef DEBUG_RTP_TCP av_dlog(s, "ret=%d c=%02x [%c]\n", ret, ch, ch); -#endif if (ret != 1) return AVERROR_EOF; if (ch == '\n') diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 56160cefc2..6b060923e4 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -28,6 +28,8 @@ #include "network.h" #include "httpauth.h" +#include "libavutil/log.h" + /** * Network layer over which RTP/etc packet data will be transported. */ @@ -196,6 +198,7 @@ enum RTSPServerType { * @todo Use AVIOContext instead of URLContext */ typedef struct RTSPState { + const AVClass *class; /**< Class for private options. */ URLContext *rtsp_hd; /* RTSP TCP connection handle */ /** number of items in the 'rtsp_streams' variable */ @@ -336,6 +339,16 @@ typedef struct RTSPState { * Whether the server supports the GET_PARAMETER method. */ int get_parameter_supported; + + /** + * Do not begin to play the stream immediately. + */ + int initial_pause; + + /** + * Option flags for the chained RTP muxer. + */ + int rtp_muxer_flags; } RTSPState; /** diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 454a31c3f9..cf95915110 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -21,6 +21,7 @@ #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" #include "avformat.h" #include "internal.h" @@ -30,9 +31,6 @@ #include "rdt.h" #include "url.h" -//#define DEBUG -//#define DEBUG_RTP_TCP - static int rtsp_read_play(AVFormatContext *s) { RTSPState *rt = s->priv_data; @@ -165,7 +163,12 @@ static int rtsp_read_header(AVFormatContext *s, return AVERROR(ENOMEM); rt->real_setup = rt->real_setup_cache + s->nb_streams; - if (ap->initial_pause) { +#if FF_API_FORMAT_PARAMETERS + if (ap->initial_pause) + rt->initial_pause = ap->initial_pause; +#endif + + if (rt->initial_pause) { /* do not start immediately */ } else { if (rtsp_read_play(s) < 0) { @@ -185,9 +188,7 @@ int ff_rtsp_tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, int id, len, i, ret; RTSPStream *rtsp_st; -#ifdef DEBUG_RTP_TCP av_dlog(s, "tcp_read_packet:\n"); -#endif redo: for (;;) { RTSPMessageHeader reply; @@ -206,9 +207,7 @@ redo: return -1; id = buf[0]; len = AV_RB16(buf + 1); -#ifdef DEBUG_RTP_TCP av_dlog(s, "id=%d len=%d\n", id, len); -#endif if (len > buf_size || len < 12) goto redo; /* get the data */ @@ -399,6 +398,18 @@ static int rtsp_read_close(AVFormatContext *s) return 0; } +static const AVOption options[] = { + { "initial_pause", "Don't start playing the stream immediately", offsetof(RTSPState, initial_pause), FF_OPT_TYPE_INT, {.dbl = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +const AVClass rtsp_demuxer_class = { + .class_name = "RTSP demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVInputFormat ff_rtsp_demuxer = { "rtsp", NULL_IF_CONFIG_SMALL("RTSP input format"), @@ -411,4 +422,5 @@ AVInputFormat ff_rtsp_demuxer = { .flags = AVFMT_NOFILE, .read_play = rtsp_read_play, .read_pause = rtsp_read_pause, + .priv_class = &rtsp_demuxer_class, }; diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index 1cbcb49750..9120d187b4 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -33,9 +33,23 @@ #include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" #include "url.h" +#include "libavutil/opt.h" +#include "rtpenc.h" #define SDP_MAX_SIZE 16384 +static const AVOption options[] = { + FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags), + { NULL }, +}; + +static const AVClass rtsp_muxer_class = { + .class_name = "RTSP muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr) { RTSPState *rt = s->priv_data; @@ -238,5 +252,6 @@ AVOutputFormat ff_rtsp_muxer = { rtsp_write_packet, rtsp_write_close, .flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER, + .priv_class = &rtsp_muxer_class, }; diff --git a/libavformat/sauce.c b/libavformat/sauce.c index 41e991e3e7..21cc95bccb 100644 --- a/libavformat/sauce.c +++ b/libavformat/sauce.c @@ -25,6 +25,7 @@ */ #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #include "sauce.h" @@ -32,7 +33,7 @@ int ff_sauce_read(AVFormatContext *avctx, uint64_t *fsize, int *got_width, int g { AVIOContext *pb = avctx->pb; char buf[36]; - int datatype, filetype, t1, t2, nb_comments, flags; + int datatype, filetype, t1, t2, nb_comments; uint64_t start_pos = avio_size(pb) - 128; avio_seek(pb, start_pos, SEEK_SET); @@ -44,7 +45,7 @@ int ff_sauce_read(AVFormatContext *avctx, uint64_t *fsize, int *got_width, int g #define GET_SAUCE_META(name,size) \ if (avio_read(pb, buf, size) == size && buf[0]) { \ buf[size] = 0; \ - av_metadata_set2(&avctx->metadata, name, buf, 0); \ + av_dict_set(&avctx->metadata, name, buf, 0); \ } GET_SAUCE_META("title", 35) @@ -57,7 +58,7 @@ int ff_sauce_read(AVFormatContext *avctx, uint64_t *fsize, int *got_width, int g t1 = avio_rl16(pb); t2 = avio_rl16(pb); nb_comments = avio_r8(pb); - flags = avio_r8(pb); + avio_skip(pb, 1); /* flags */ avio_skip(pb, 4); GET_SAUCE_META("encoder", 22); @@ -95,7 +96,7 @@ int ff_sauce_read(AVFormatContext *avctx, uint64_t *fsize, int *got_width, int g str[65*i + 64] = '\n'; } str[65*i] = 0; - av_metadata_set2(&avctx->metadata, "comment", str, AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(&avctx->metadata, "comment", str, AV_DICT_DONT_STRDUP_VAL); } } diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 923c57fbcd..32cef49916 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -21,8 +21,11 @@ #include <string.h> #include "libavutil/avstring.h" #include "libavutil/base64.h" +#include "libavutil/dict.h" #include "libavutil/parseutils.h" +#include "libavutil/opt.h" #include "libavcodec/xiph.h" +#include "libavcodec/mpeg4audio.h" #include "avformat.h" #include "internal.h" #include "avc.h" @@ -299,7 +302,72 @@ xiph_fail: return NULL; } -static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type) +static int latm_context2profilelevel(AVCodecContext *c) +{ + /* MP4A-LATM + * The RTP payload format specification is described in RFC 3016 + * The encoding specifications are provided in ISO/IEC 14496-3 */ + + int profile_level = 0x2B; + + /* TODO: AAC Profile only supports AAC LC Object Type. + * Different Object Types should implement different Profile Levels */ + + if (c->sample_rate <= 24000) { + if (c->channels <= 2) + profile_level = 0x28; // AAC Profile, Level 1 + } else if (c->sample_rate <= 48000) { + if (c->channels <= 2) { + profile_level = 0x29; // AAC Profile, Level 2 + } else if (c->channels <= 5) { + profile_level = 0x2A; // AAC Profile, Level 4 + } + } else if (c->sample_rate <= 96000) { + if (c->channels <= 5) { + profile_level = 0x2B; // AAC Profile, Level 5 + } + } + + return profile_level; +} + +static char *latm_context2config(AVCodecContext *c) +{ + /* MP4A-LATM + * The RTP payload format specification is described in RFC 3016 + * The encoding specifications are provided in ISO/IEC 14496-3 */ + + uint8_t config_byte[6]; + int rate_index; + char *config; + + for (rate_index = 0; rate_index < 16; rate_index++) + if (ff_mpeg4audio_sample_rates[rate_index] == c->sample_rate) + break; + if (rate_index == 16) { + av_log(c, AV_LOG_ERROR, "Unsupported sample rate\n"); + return NULL; + } + + config_byte[0] = 0x40; + config_byte[1] = 0; + config_byte[2] = 0x20 | rate_index; + config_byte[3] = c->channels << 4; + config_byte[4] = 0x3f; + config_byte[5] = 0xc0; + + config = av_malloc(6*2+1); + if (!config) { + av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); + return NULL; + } + ff_data_to_hex(config, config_byte, 6, 1); + config[12] = 0; + + return config; +} + +static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type, AVFormatContext *fmt) { char *config = NULL; @@ -334,24 +402,35 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, payload_type, config ? config : ""); break; case CODEC_ID_AAC: - if (c->extradata_size) { - config = extradata2config(c); + if (fmt && fmt->oformat->priv_class && + av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) { + config = latm_context2config(c); + if (!config) + return NULL; + av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n" + "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n", + payload_type, c->sample_rate, c->channels, + payload_type, latm_context2profilelevel(c), config); } else { - /* FIXME: maybe we can forge config information based on the - * codec parameters... - */ - av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); - return NULL; + if (c->extradata_size) { + config = extradata2config(c); + } else { + /* FIXME: maybe we can forge config information based on the + * codec parameters... + */ + av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); + return NULL; + } + if (config == NULL) { + return NULL; + } + av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n" + "a=fmtp:%d profile-level-id=1;" + "mode=AAC-hbr;sizelength=13;indexlength=3;" + "indexdeltalength=3%s\r\n", + payload_type, c->sample_rate, c->channels, + payload_type, config); } - if (config == NULL) { - return NULL; - } - av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n" - "a=fmtp:%d profile-level-id=1;" - "mode=AAC-hbr;sizelength=13;indexlength=3;" - "indexdeltalength=3%s\r\n", - payload_type, c->sample_rate, c->channels, - payload_type, config); break; case CODEC_ID_PCM_S16BE: if (payload_type >= RTP_PT_PRIVATE) @@ -448,7 +527,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, return buff; } -void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, int port, int ttl) +void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt) { const char *type; int payload_type; @@ -471,12 +550,12 @@ void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *des av_strlcatf(buff, size, "b=AS:%d\r\n", c->bit_rate / 1000); } - sdp_write_media_attributes(buff, size, c, payload_type); + sdp_write_media_attributes(buff, size, c, payload_type, fmt); } int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) { - AVMetadataTag *title = av_metadata_get(ac[0]->metadata, "title", NULL, 0); + AVDictionaryEntry *title = av_dict_get(ac[0]->metadata, "title", NULL, 0); struct sdp_session_level s; int i, j, port, ttl, is_multicast; char dst[32], dst_type[5]; @@ -520,7 +599,8 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) for (j = 0; j < ac[i]->nb_streams; j++) { ff_sdp_write_media(buf, size, ac[i]->streams[j]->codec, dst[0] ? dst : NULL, - dst_type, (port > 0) ? port + j * 2 : 0, ttl); + dst_type, (port > 0) ? port + j * 2 : 0, ttl, + ac[i]); if (port <= 0) { av_strlcatf(buf, size, "a=control:streamid=%d\r\n", i + j); @@ -536,7 +616,7 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) return AVERROR(ENOSYS); } -void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, int port, int ttl) +void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt) { } #endif diff --git a/libavformat/smacker.c b/libavformat/smacker.c index 2603a4d71c..29a66e79fa 100644 --- a/libavformat/smacker.c +++ b/libavformat/smacker.c @@ -233,7 +233,6 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) int i; int frame_size = 0; int palchange = 0; - int pos; if (url_feof(s->pb) || smk->cur_frame >= smk->frames) return AVERROR_EOF; @@ -244,7 +243,6 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) frame_size = smk->frm_size[smk->cur_frame] & (~3); flags = smk->frm_flags[smk->cur_frame]; /* handle palette change event */ - pos = avio_tell(s->pb); if(flags & SMACKER_PAL){ int size, sz, t, off, j, pos; uint8_t *pal = smk->pal; diff --git a/libavformat/sol.c b/libavformat/sol.c index 7ad894e304..c0d2c5d5a2 100644 --- a/libavformat/sol.c +++ b/libavformat/sol.c @@ -85,7 +85,6 @@ static int sol_channels(int magic, int type) static int sol_read_header(AVFormatContext *s, AVFormatParameters *ap) { - int size; unsigned int magic,tag; AVIOContext *pb = s->pb; unsigned int id, channels, rate, type; @@ -99,7 +98,7 @@ static int sol_read_header(AVFormatContext *s, return -1; rate = avio_rl16(pb); type = avio_r8(pb); - size = avio_rl32(pb); + avio_skip(pb, 4); /* size */ if (magic != 0x0B8D) avio_r8(pb); /* newer SOLs contain padding byte */ diff --git a/libavformat/soxdec.c b/libavformat/soxdec.c index 5e1e220f76..16d26ab4a7 100644 --- a/libavformat/soxdec.c +++ b/libavformat/soxdec.c @@ -30,6 +30,7 @@ */ #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #include "pcm.h" #include "sox.h" @@ -101,8 +102,8 @@ static int sox_read_header(AVFormatContext *s, } comment[comment_size] = 0; - av_metadata_set2(&s->metadata, "comment", comment, - AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(&s->metadata, "comment", comment, + AV_DICT_DONT_STRDUP_VAL); } avio_skip(pb, header_size - SOX_FIXED_HDR - comment_size); diff --git a/libavformat/soxenc.c b/libavformat/soxenc.c index c93869c691..a07a2068c3 100644 --- a/libavformat/soxenc.c +++ b/libavformat/soxenc.c @@ -30,6 +30,7 @@ */ #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #include "avio_internal.h" #include "sox.h" @@ -43,10 +44,10 @@ static int sox_write_header(AVFormatContext *s) SoXContext *sox = s->priv_data; AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; - AVMetadataTag *comment; + AVDictionaryEntry *comment; size_t comment_len = 0, comment_size; - comment = av_metadata_get(s->metadata, "comment", NULL, 0); + comment = av_dict_get(s->metadata, "comment", NULL, 0); if (comment) comment_len = strlen(comment->value); comment_size = (comment_len + 7) & ~7; diff --git a/libavformat/spdif.h b/libavformat/spdif.h index ac5be7c31a..4b11de20d1 100644 --- a/libavformat/spdif.h +++ b/libavformat/spdif.h @@ -19,6 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef AVFORMAT_SPDIF_H +#define AVFORMAT_SPDIF_H + #include <stdint.h> #define SYNCWORD1 0xF872 @@ -55,3 +58,5 @@ static const uint16_t spdif_mpeg_pkt_offset[2][3] = { }; void ff_spdif_bswap_buf16(uint16_t *dst, const uint16_t *src, int w); + +#endif /* AVFORMAT_SPDIF_H */ diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 57be430c23..9b344ab98f 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -45,6 +45,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) char buf[256]; int ret; socklen_t optlen; + int timeout = 50; char hostname[1024],proto[1024],path[1024]; char portstr[10]; @@ -57,6 +58,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) listen_socket = 1; + if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { + timeout = strtol(buf, NULL, 10); + } } memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -73,6 +77,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) cur_ai = ai; restart: + ret = AVERROR(EIO); fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) goto fail; @@ -84,29 +89,29 @@ static int tcp_open(URLContext *h, const char *uri, int flags) fd1 = accept(fd, NULL, NULL); closesocket(fd); fd = fd1; + ff_socket_nonblock(fd, 1); } else { redo: + ff_socket_nonblock(fd, 1); ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); } - ff_socket_nonblock(fd, 1); - if (ret < 0) { - int timeout=50; struct pollfd p = {fd, POLLOUT, 0}; - if (ff_neterrno() == AVERROR(EINTR)) { + ret = ff_neterrno(); + if (ret == AVERROR(EINTR)) { if (url_interrupt_cb()) { ret = AVERROR_EXIT; goto fail1; } goto redo; } - if (ff_neterrno() != AVERROR(EINPROGRESS) && - ff_neterrno() != AVERROR(EAGAIN)) + if (ret != AVERROR(EINPROGRESS) && + ret != AVERROR(EAGAIN)) goto fail; /* wait until we are connected or until abort */ - for(;;) { + while(timeout--) { if (url_interrupt_cb()) { ret = AVERROR_EXIT; goto fail1; @@ -114,14 +119,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) ret = poll(&p, 1, 100); if (ret > 0) break; - if(!--timeout){ - av_log(NULL, AV_LOG_ERROR, - "TCP open %s:%d timeout\n", - hostname, port); - goto fail; - } } - + if (ret <= 0) { + ret = AVERROR(ETIMEDOUT); + goto fail; + } /* test error */ optlen = sizeof(ret); getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); @@ -129,6 +131,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) av_log(NULL, AV_LOG_ERROR, "TCP connection to %s:%d failed: %s\n", hostname, port, strerror(ret)); + ret = AVERROR(ret); goto fail; } } @@ -151,7 +154,6 @@ static int tcp_open(URLContext *h, const char *uri, int flags) closesocket(fd); goto restart; } - ret = AVERROR(EIO); fail1: if (fd >= 0) closesocket(fd); diff --git a/libavformat/tta.c b/libavformat/tta.c index d5f8e1ed61..c37039d0da 100644 --- a/libavformat/tta.c +++ b/libavformat/tta.c @@ -22,6 +22,7 @@ #include "libavcodec/get_bits.h" #include "avformat.h" #include "id3v1.h" +#include "libavutil/dict.h" typedef struct { int totalframes, currentframe; @@ -43,7 +44,7 @@ static int tta_read_header(AVFormatContext *s, AVFormatParameters *ap) int i, channels, bps, samplerate, datalen, framelen; uint64_t framepos, start_offset; - if (!av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) + if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); start_offset = avio_tell(s->pb); diff --git a/libavformat/tty.c b/libavformat/tty.c index b288d15393..ddf283d8a3 100644 --- a/libavformat/tty.c +++ b/libavformat/tty.c @@ -26,14 +26,19 @@ #include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" +#include "libavutil/log.h" +#include "libavutil/dict.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" #include "avformat.h" #include "sauce.h" -#define LINE_RATE 6000 /* characters per second */ - typedef struct { + AVClass *class; int chars_per_frame; uint64_t fsize; /**< file size less metadata buffer */ + char *video_size;/**< A string describing video size, set by a private option. */ + char *framerate; /**< Set by a private option. */ } TtyDemuxContext; /** @@ -56,7 +61,7 @@ static int efi_read(AVFormatContext *avctx, uint64_t start_pos) return -1; \ if (avio_read(pb, buf, size) == size) { \ buf[len] = 0; \ - av_metadata_set2(&avctx->metadata, name, buf, 0); \ + av_dict_set(&avctx->metadata, name, buf, 0); \ } GET_EFI_META("filename", 12) @@ -70,23 +75,44 @@ static int read_header(AVFormatContext *avctx, AVFormatParameters *ap) { TtyDemuxContext *s = avctx->priv_data; + int width = 0, height = 0, ret = 0; AVStream *st = av_new_stream(avctx, 0); - if (!st) - return AVERROR(ENOMEM); + AVRational framerate; + + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } st->codec->codec_tag = 0; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_ANSI; - if (ap->width) st->codec->width = ap->width; - if (ap->height) st->codec->height = ap->height; - if (!ap->time_base.num) { - av_set_pts_info(st, 60, 1, 25); - } else { - av_set_pts_info(st, 60, ap->time_base.num, ap->time_base.den); + if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) { + av_log (avctx, AV_LOG_ERROR, "Couldn't parse video size.\n"); + goto fail; } + if ((ret = av_parse_video_rate(&framerate, s->framerate)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s->framerate); + goto fail; + } +#if FF_API_FORMAT_PARAMETERS + if (ap->width > 0) + width = ap->width; + if (ap->height > 0) + height = ap->height; + if (ap->time_base.num) + framerate = (AVRational){ap->time_base.den, ap->time_base.num}; +#endif + st->codec->width = width; + st->codec->height = height; + av_set_pts_info(st, 60, framerate.den, framerate.num); /* simulate tty display speed */ - s->chars_per_frame = FFMAX(av_q2d(st->time_base) * (ap->sample_rate ? ap->sample_rate : LINE_RATE), 1); +#if FF_API_FORMAT_PARAMETERS + if (ap->sample_rate) + s->chars_per_frame = ap->sample_rate; +#endif + s->chars_per_frame = FFMAX(av_q2d(st->time_base)*s->chars_per_frame, 1); if (avctx->pb->seekable) { s->fsize = avio_size(avctx->pb); @@ -98,7 +124,8 @@ static int read_header(AVFormatContext *avctx, avio_seek(avctx->pb, 0, SEEK_SET); } - return 0; +fail: + return ret; } static int read_packet(AVFormatContext *avctx, AVPacket *pkt) @@ -124,6 +151,22 @@ static int read_packet(AVFormatContext *avctx, AVPacket *pkt) return 0; } +#define OFFSET(x) offsetof(TtyDemuxContext, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "chars_per_frame", "", offsetof(TtyDemuxContext, chars_per_frame), FF_OPT_TYPE_INT, {.dbl = 6000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM}, + { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "framerate", "", OFFSET(framerate), FF_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC }, + { NULL }, +}; + +static const AVClass tty_demuxer_class = { + .class_name = "TTY demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVInputFormat ff_tty_demuxer = { .name = "tty", .long_name = NULL_IF_CONFIG_SMALL("Tele-typewriter"), @@ -131,4 +174,5 @@ AVInputFormat ff_tty_demuxer = { .read_header = read_header, .read_packet = read_packet, .extensions = "ans,art,asc,diz,ice,nfo,txt,vt", + .priv_class = &tty_demuxer_class, }; diff --git a/libavformat/udp.c b/libavformat/udp.c index 021f529d64..78077e6595 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -35,7 +35,11 @@ #include "network.h" #include "os_support.h" #include "url.h" + +#if HAVE_PTHREADS #include <pthread.h> +#endif + #include <sys/time.h> #ifndef IPV6_ADD_MEMBERSHIP @@ -57,9 +61,10 @@ typedef struct { /* Circular Buffer variables for use in UDP receive code */ int circular_buffer_size; AVFifoBuffer *fifo; - int circular_buffer_available_max; int circular_buffer_error; +#if HAVE_PTHREADS pthread_t circular_buffer_thread; +#endif } UDPContext; #define UDP_TX_BUF_SIZE 32768 @@ -509,6 +514,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) s->udp_fd = udp_fd; +#if HAVE_PTHREADS if (!is_output && s->circular_buffer_size) { /* start the task going */ s->fifo = av_fifo_alloc(s->circular_buffer_size); @@ -517,12 +523,13 @@ static int udp_open(URLContext *h, const char *uri, int flags) goto fail; } } +#endif return 0; fail: if (udp_fd >= 0) closesocket(udp_fd); - av_fifo_free(s->fifo); + av_fifo_free(s->fifo); av_free(s); return AVERROR(EIO); } @@ -532,7 +539,6 @@ static int udp_read(URLContext *h, uint8_t *buf, int size) UDPContext *s = h->priv_data; int ret; int avail; - int left; fd_set rfds; struct timeval tv; @@ -597,7 +603,6 @@ static int udp_close(URLContext *h) if (s->is_multicast && !(h->flags & AVIO_WRONLY)) udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr); closesocket(s->udp_fd); - av_log( h, AV_LOG_INFO, "circular_buffer_info max:%d%%\r\n", (s->circular_buffer_available_max*100)/s->circular_buffer_size); av_fifo_free(s->fifo); av_free(s); return 0; diff --git a/libavformat/url.h b/libavformat/url.h index 56366644aa..5ef6a21d7b 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -173,4 +173,4 @@ int ffurl_register_protocol(URLProtocol *protocol, int size); int ff_udp_set_remote_url(URLContext *h, const char *uri); int ff_udp_get_local_port(URLContext *h); -#endif //AVFORMAT_URL_H +#endif /* AVFORMAT_URL_H */ diff --git a/libavformat/utils.c b/libavformat/utils.c index 16297af16a..454cd5843a 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -27,6 +27,7 @@ #include "libavcodec/internal.h" #include "libavcodec/raw.h" #include "libavutil/opt.h" +#include "libavutil/dict.h" #include "metadata.h" #include "id3v2.h" #include "libavutil/avstring.h" @@ -743,6 +744,7 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) s->streams[i]->request_probe = -1; continue; } + st= s->streams[pkt->stream_index]; switch(st->codec->codec_type){ @@ -1516,8 +1518,6 @@ int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, wanted_timestamp, flags); } -#define DEBUG_SEEK - int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){ AVInputFormat *avif= s->iformat; int64_t av_uninit(pos_min), av_uninit(pos_max), pos, pos_limit; @@ -1529,9 +1529,7 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts if (stream_index < 0) return -1; -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_DEBUG, "read_seek: %d %"PRId64"\n", stream_index, target_ts); -#endif + av_dlog(s, "read_seek: %d %"PRId64"\n", stream_index, target_ts); ts_max= ts_min= AV_NOPTS_VALUE; @@ -1548,10 +1546,8 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts if(e->timestamp <= target_ts || e->pos == e->min_distance){ pos_min= e->pos; ts_min= e->timestamp; -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_DEBUG, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n", - pos_min,ts_min); -#endif + av_dlog(s, "using cached pos_min=0x%"PRIx64" dts_min=%"PRId64"\n", + pos_min,ts_min); }else{ assert(index==0); } @@ -1564,10 +1560,8 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts pos_max= e->pos; ts_max= e->timestamp; pos_limit= pos_max - e->min_distance; -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_DEBUG, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%"PRId64"\n", - pos_max,pos_limit, ts_max); -#endif + av_dlog(s, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64" dts_max=%"PRId64"\n", + pos_max,pos_limit, ts_max); } } @@ -1589,9 +1583,7 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i int64_t start_pos, filesize; int no_change; -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_DEBUG, "gen_seek: %d %"PRId64"\n", stream_index, target_ts); -#endif + av_dlog(s, "gen_seek: %d %"PRId64"\n", stream_index, target_ts); if(ts_min == AV_NOPTS_VALUE){ pos_min = s->data_offset; @@ -1633,11 +1625,8 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i no_change=0; while (pos_min < pos_limit) { -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_DEBUG, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%"PRId64" dts_max=%"PRId64"\n", - pos_min, pos_max, - ts_min, ts_max); -#endif + av_dlog(s, "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%"PRId64" dts_max=%"PRId64"\n", + pos_min, pos_max, ts_min, ts_max); assert(pos_limit <= pos_max); if(no_change==0){ @@ -1664,11 +1653,9 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i no_change++; else no_change=0; -#ifdef DEBUG_SEEK - av_log(s, AV_LOG_DEBUG, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64" target:%"PRId64" limit:%"PRId64" start:%"PRId64" noc:%d\n", - pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, pos_limit, - start_pos, no_change); -#endif + av_dlog(s, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64" target:%"PRId64" limit:%"PRId64" start:%"PRId64" noc:%d\n", + pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, + pos_limit, start_pos, no_change); if(ts == AV_NOPTS_VALUE){ av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n"); return -1; @@ -1687,14 +1674,12 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max; ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max; -#ifdef DEBUG_SEEK pos_min = pos; ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX); pos_min++; ts_max = read_timestamp(s, stream_index, &pos_min, INT64_MAX); - av_log(s, AV_LOG_DEBUG, "pos=0x%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n", - pos, ts_min, target_ts, ts_max); -#endif + av_dlog(s, "pos=0x%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n", + pos, ts_min, target_ts, ts_max); *ts_ret= ts; return pos; } @@ -1813,10 +1798,12 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f return 0; } - if(s->iformat->read_timestamp) + if(s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) return av_seek_frame_binary(s, stream_index, timestamp, flags); - else + else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) return av_seek_frame_generic(s, stream_index, timestamp, flags); + else + return -1; } int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) @@ -2085,7 +2072,7 @@ static void av_estimate_timings(AVFormatContext *ic, int64_t old_offset) #if 0 { int i; - AVStream *st; + AVStream av_unused *st; for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; printf("%d: start_time: %0.3f duration: %0.3f\n", @@ -2219,7 +2206,7 @@ enum CodecID av_codec_get_id(const AVCodecTag * const *tags, unsigned int tag) static void compute_chapters_end(AVFormatContext *s) { unsigned int i, j; - int64_t max_time = s->duration + (s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time; + int64_t max_time = s->duration + ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time); for (i = 0; i < s->nb_chapters; i++) if (s->chapters[i]->end == AV_NOPTS_VALUE) { @@ -2338,6 +2325,8 @@ int av_find_stream_info(AVFormatContext *ic) the correct fps */ if (av_q2d(st->time_base) > 0.0005) fps_analyze_framecount *= 2; + if (ic->fps_probe_size >= 0) + fps_analyze_framecount = ic->fps_probe_size; /* variable fps and no guess at the real fps */ if( tb_unreliable(st->codec) && !(st->r_frame_rate.num && st->avg_frame_rate.num) && st->info->duration_count < fps_analyze_framecount @@ -2396,8 +2385,9 @@ int av_find_stream_info(AVFormatContext *ic) st = ic->streams[pkt->stream_index]; if (st->codec_info_nb_frames>1) { - if (st->time_base.den > 0 && av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) { - av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n"); + int64_t t; + if (st->time_base.den > 0 && (t=av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q)) >= ic->max_analyze_duration) { + av_log(ic, AV_LOG_WARNING, "max_analyze_duration %d reached at %"PRId64"\n", ic->max_analyze_duration, t); break; } st->info->codec_info_duration += pkt->duration; @@ -2655,6 +2645,10 @@ void avformat_free_context(AVFormatContext *s) int i; AVStream *st; + av_opt_free(s); + if (s->iformat && s->iformat->priv_class && s->priv_data) + av_opt_free(s->priv_data); + for(i=0;i<s->nb_streams;i++) { /* free all data in a stream component */ st = s->streams[i]; @@ -2662,7 +2656,7 @@ void avformat_free_context(AVFormatContext *s) av_parser_close(st->parser); av_free_packet(&st->cur_pkt); } - av_metadata_free(&st->metadata); + av_dict_free(&st->metadata); av_free(st->index_entries); av_free(st->codec->extradata); av_free(st->codec->subtitle_header); @@ -2689,12 +2683,12 @@ void avformat_free_context(AVFormatContext *s) #if FF_API_OLD_METADATA av_free(s->chapters[s->nb_chapters]->title); #endif - av_metadata_free(&s->chapters[s->nb_chapters]->metadata); + av_dict_free(&s->chapters[s->nb_chapters]->metadata); av_free(s->chapters[s->nb_chapters]); } av_freep(&s->chapters); av_metadata_free(&s->metadata); - av_freep(&s->key); +// av_freep(&s->key); av_free(s); } @@ -2770,9 +2764,7 @@ AVProgram *av_new_program(AVFormatContext *ac, int id) AVProgram *program=NULL; int i; -#ifdef DEBUG_SI - av_log(ac, AV_LOG_DEBUG, "new_program: id=0x%04x\n", id); -#endif + av_dlog(ac, "new_program: id=0x%04x\n", id); for(i=0; i<ac->nb_programs; i++) if(ac->programs[i]->id == id) @@ -2808,7 +2800,7 @@ AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, int6 #if FF_API_OLD_METADATA av_free(chapter->title); #endif - av_metadata_set2(&chapter->metadata, "title", title, 0); + av_dict_set(&chapter->metadata, "title", title, 0); chapter->id = id; chapter->time_base= time_base; chapter->start = start; @@ -2836,29 +2828,36 @@ int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap) return 0; } -AVFormatContext *avformat_alloc_output_context(const char *format, AVOutputFormat *oformat, const char *filename){ - AVFormatContext *s= avformat_alloc_context(); - if(!s) +int avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *oformat, + const char *format, const char *filename) +{ + AVFormatContext *s = avformat_alloc_context(); + int ret = 0; + + *avctx = NULL; + if (!s) goto nomem; - if(!oformat){ + if (!oformat) { if (format) { oformat = av_guess_format(format, NULL, NULL); if (!oformat) { av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format); + ret = AVERROR(EINVAL); goto error; } } else { oformat = av_guess_format(NULL, filename, NULL); if (!oformat) { + ret = AVERROR(EINVAL); av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n", - filename); + filename); goto error; } } } - s->oformat= oformat; + s->oformat = oformat; if (s->oformat->priv_data_size > 0) { s->priv_data = av_mallocz(s->oformat->priv_data_size); if (!s->priv_data) @@ -2870,15 +2869,27 @@ AVFormatContext *avformat_alloc_output_context(const char *format, AVOutputForma } else s->priv_data = NULL; - if(filename) + if (filename) av_strlcpy(s->filename, filename, sizeof(s->filename)); - return s; + *avctx = s; + return 0; nomem: av_log(s, AV_LOG_ERROR, "Out of memory\n"); + ret = AVERROR(ENOMEM); error: avformat_free_context(s); - return NULL; + return ret; +} + +#if FF_API_ALLOC_OUTPUT_CONTEXT +AVFormatContext *avformat_alloc_output_context(const char *format, + AVOutputFormat *oformat, const char *filename) +{ + AVFormatContext *avctx; + int ret = avformat_alloc_output_context2(&avctx, oformat, format, filename); + return ret < 0 ? NULL : avctx; } +#endif static int validate_codec_tag(AVFormatContext *s, AVStream *st) { @@ -2988,7 +2999,7 @@ int av_write_header(AVFormatContext *s) /* set muxer identification string */ if (s->nb_streams && !(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { - av_metadata_set2(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0); + av_dict_set(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0); } if(s->oformat->write_header){ @@ -3061,7 +3072,7 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){ pkt->dts= st->pts_buffer[0]; } - if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && st->cur_dts >= pkt->dts){ + if(st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && ((!(s->oformat->flags & AVFMT_TS_NONSTRICT) && st->cur_dts >= pkt->dts) || st->cur_dts > pkt->dts)){ av_log(s, AV_LOG_ERROR, "Application provided invalid, non monotonically increasing dts to muxer in stream %d: %"PRId64" >= %"PRId64"\n", st->index, st->cur_dts, pkt->dts); @@ -3269,6 +3280,8 @@ fail: av_freep(&s->streams[i]->priv_data); av_freep(&s->streams[i]->index_entries); } + if (s->iformat && s->iformat->priv_class) + av_opt_free(s->priv_data); av_freep(&s->priv_data); return ret; } @@ -3308,13 +3321,13 @@ static void print_fps(double d, const char *postfix){ else av_log(NULL, AV_LOG_INFO, ", %1.0fk %s", d/1000, postfix); } -static void dump_metadata(void *ctx, AVMetadata *m, const char *indent) +static void dump_metadata(void *ctx, AVDictionary *m, const char *indent) { - if(m && !(m->count == 1 && av_metadata_get(m, "language", NULL, 0))){ - AVMetadataTag *tag=NULL; + if(m && !(m->count == 1 && av_dict_get(m, "language", NULL, 0))){ + AVDictionaryEntry *tag=NULL; av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent); - while((tag=av_metadata_get(m, "", tag, AV_METADATA_IGNORE_SUFFIX))) { + while((tag=av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) { if(strcmp("language", tag->key)) av_log(ctx, AV_LOG_INFO, "%s %-16s: %s\n", indent, tag->key, tag->value); } @@ -3328,7 +3341,7 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); AVStream *st = ic->streams[i]; int g = av_gcd(st->time_base.num, st->time_base.den); - AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL, 0); + AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); avcodec_string(buf, sizeof(buf), st->codec, is_output); av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i); /* the pid is an important information, so we display it */ @@ -3452,7 +3465,7 @@ void av_dump_format(AVFormatContext *ic, if(ic->nb_programs) { int j, k, total = 0; for(j=0; j<ic->nb_programs; j++) { - AVMetadataTag *name = av_metadata_get(ic->programs[j]->metadata, + AVDictionaryEntry *name = av_dict_get(ic->programs[j]->metadata, "name", NULL, 0); av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id, name ? name->value : ""); diff --git a/libavformat/version.h b/libavformat/version.h index eec52b2363..7292007610 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -24,7 +24,7 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 52 -#define LIBAVFORMAT_VERSION_MINOR 108 +#define LIBAVFORMAT_VERSION_MINOR 109 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -113,5 +113,14 @@ #ifndef FF_API_SDP_CREATE #define FF_API_SDP_CREATE (LIBAVFORMAT_VERSION_MAJOR < 54) #endif +#ifndef FF_API_ALLOC_OUTPUT_CONTEXT +#define FF_API_ALLOC_OUTPUT_CONTEXT (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_FORMAT_PARAMETERS +#define FF_API_FORMAT_PARAMETERS (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_FLAG_RTP_HINT +#define FF_API_FLAG_RTP_HINT (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif -#endif //AVFORMAT_VERSION_H +#endif /* AVFORMAT_VERSION_H */ diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c index 59a403f209..9b38e6a791 100644 --- a/libavformat/vorbiscomment.c +++ b/libavformat/vorbiscomment.c @@ -23,6 +23,7 @@ #include "metadata.h" #include "vorbiscomment.h" #include "libavcodec/bytestream.h" +#include "libavutil/dict.h" /** * VorbisComment metadata conversion mapping. @@ -36,15 +37,15 @@ const AVMetadataConv ff_vorbiscomment_metadata_conv[] = { { 0 } }; -int ff_vorbiscomment_length(AVMetadata *m, const char *vendor_string, +int ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string, unsigned *count) { int len = 8; len += strlen(vendor_string); *count = 0; if (m) { - AVMetadataTag *tag = NULL; - while ((tag = av_metadata_get(m, "", tag, AV_METADATA_IGNORE_SUFFIX))) { + AVDictionaryEntry *tag = NULL; + while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) { len += 4 +strlen(tag->key) + 1 + strlen(tag->value); (*count)++; } @@ -52,15 +53,15 @@ int ff_vorbiscomment_length(AVMetadata *m, const char *vendor_string, return len; } -int ff_vorbiscomment_write(uint8_t **p, AVMetadata **m, +int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m, const char *vendor_string, const unsigned count) { bytestream_put_le32(p, strlen(vendor_string)); bytestream_put_buffer(p, vendor_string, strlen(vendor_string)); if (*m) { - AVMetadataTag *tag = NULL; + AVDictionaryEntry *tag = NULL; bytestream_put_le32(p, count); - while ((tag = av_metadata_get(*m, "", tag, AV_METADATA_IGNORE_SUFFIX))) { + while ((tag = av_dict_get(*m, "", tag, AV_DICT_IGNORE_SUFFIX))) { unsigned int len1 = strlen(tag->key); unsigned int len2 = strlen(tag->value); bytestream_put_le32(p, len1+1+len2); diff --git a/libavformat/vorbiscomment.h b/libavformat/vorbiscomment.h index 3dfe9d226b..b147092071 100644 --- a/libavformat/vorbiscomment.h +++ b/libavformat/vorbiscomment.h @@ -35,13 +35,13 @@ * @param count Pointer to store the number of tags in m because m->count is "not allowed" * @return The length in bytes. */ -int ff_vorbiscomment_length(AVMetadata *m, const char *vendor_string, +int ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string, unsigned *count); /** * Writes a VorbisComment into a buffer. The buffer, p, must have enough * data to hold the whole VorbisComment. The minimum size required can be - * obtained by passing the same AVMetadata and vendor_string to + * obtained by passing the same AVDictionary and vendor_string to * ff_vorbiscomment_length() * * @param p The buffer in which to write. @@ -49,7 +49,7 @@ int ff_vorbiscomment_length(AVMetadata *m, const char *vendor_string, * @param vendor_string The vendor string to write. * @param count The number of tags in m because m->count is "not allowed" */ -int ff_vorbiscomment_write(uint8_t **p, AVMetadata **m, +int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m, const char *vendor_string, const unsigned count); extern const AVMetadataConv ff_vorbiscomment_metadata_conv[]; diff --git a/libavformat/vqf.c b/libavformat/vqf.c index 94ba543ba5..e06f39349b 100644 --- a/libavformat/vqf.c +++ b/libavformat/vqf.c @@ -21,6 +21,7 @@ #include "avformat.h" #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" typedef struct VqfContext { int frame_bit_len; @@ -56,7 +57,7 @@ static void add_metadata(AVFormatContext *s, const char *tag, return; avio_read(s->pb, buf, len); buf[len] = 0; - av_metadata_set2(&s->metadata, tag, buf, AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(&s->metadata, tag, buf, AV_DICT_DONT_STRDUP_VAL); } static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap) diff --git a/libavformat/wav.c b/libavformat/wav.c index 588aff512b..c5dbd631b4 100644 --- a/libavformat/wav.c +++ b/libavformat/wav.c @@ -26,6 +26,7 @@ #include "avio_internal.h" #include "pcm.h" #include "riff.h" +#include "metadata.h" typedef struct { int64_t data; @@ -184,6 +185,115 @@ static int wav_probe(AVProbeData *p) return 0; } +static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st) +{ + AVIOContext *pb = s->pb; + int ret; + + /* parse fmt header */ + *st = av_new_stream(s, 0); + if (!*st) + return AVERROR(ENOMEM); + + ret = ff_get_wav_header(pb, (*st)->codec, size); + if (ret < 0) + return ret; + (*st)->need_parsing = AVSTREAM_PARSE_FULL; + + av_set_pts_info(*st, 64, 1, (*st)->codec->sample_rate); + + return 0; +} + +static inline int wav_parse_bext_string(AVFormatContext *s, const char *key, int length) +{ + char temp[257]; + int ret; + + if ((ret = avio_read(s->pb, temp, length)) < 0) + return ret; + + temp[length] = 0; + + if (strlen(temp)) + return av_dict_set(&s->metadata, key, temp, 0); + + return 0; +} + +static int wav_parse_bext_tag(AVFormatContext *s, int64_t size) +{ + char temp[131], *coding_history; + int ret, x; + uint64_t time_reference; + int64_t umid_parts[8], umid_mask = 0; + + if ((ret = wav_parse_bext_string(s, "description", 256)) < 0 || + (ret = wav_parse_bext_string(s, "originator", 32)) < 0 || + (ret = wav_parse_bext_string(s, "originator_reference", 32)) < 0 || + (ret = wav_parse_bext_string(s, "origination_date", 10)) < 0 || + (ret = wav_parse_bext_string(s, "origination_time", 8)) < 0) + return ret; + + time_reference = avio_rl64(s->pb); + snprintf(temp, sizeof(temp), "%"PRIu64, time_reference); + if ((ret = av_dict_set(&s->metadata, "time_reference", temp, 0)) < 0) + return ret; + + /* check if version is >= 1, in which case an UMID may be present */ + if (avio_rl16(s->pb) >= 1) { + for (x = 0; x < 8; x++) + umid_mask |= umid_parts[x] = avio_rb64(s->pb); + + if (umid_mask) { + /* the string formatting below is per SMPTE 330M-2004 Annex C */ + if (umid_parts[4] == 0 && umid_parts[5] == 0 && umid_parts[6] == 0 && umid_parts[7] == 0) { + /* basic UMID */ + snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, + umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3]); + } else { + /* extended UMID */ + snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64 + "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, + umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3], + umid_parts[4], umid_parts[5], umid_parts[6], umid_parts[7]); + } + + if ((ret = av_dict_set(&s->metadata, "umid", temp, 0)) < 0) + return ret; + } + + avio_skip(s->pb, 190); + } else + avio_skip(s->pb, 254); + + if (size > 602) { + /* CodingHistory present */ + size -= 602; + + if (!(coding_history = av_malloc(size+1))) + return AVERROR(ENOMEM); + + if ((ret = avio_read(s->pb, coding_history, size)) < 0) + return ret; + + coding_history[size] = 0; + if ((ret = av_dict_set(&s->metadata, "coding_history", coding_history, + AV_METADATA_DONT_STRDUP_VAL)) < 0) + return ret; + } + + return 0; +} + +static const AVMetadataConv wav_metadata_conv[] = { + {"description", "comment" }, + {"originator", "encoded_by" }, + {"origination_date", "date" }, + {"origination_time", "creation_time"}, + {0}, +}; + /* wav input */ static int wav_read_header(AVFormatContext *s, AVFormatParameters *ap) @@ -195,7 +305,8 @@ static int wav_read_header(AVFormatContext *s, AVIOContext *pb = s->pb; AVStream *st; WAVContext *wav = s->priv_data; - int ret; + int ret, got_fmt = 0; + int64_t next_tag_ofs, data_ofs = -1; /* check RIFF header */ tag = avio_rl32(pb); @@ -212,54 +323,89 @@ static int wav_read_header(AVFormatContext *s, if (avio_rl32(pb) != MKTAG('d', 's', '6', '4')) return -1; size = avio_rl32(pb); - if (size < 16) + if (size < 24) return -1; avio_rl64(pb); /* RIFF size */ data_size = avio_rl64(pb); sample_count = avio_rl64(pb); - avio_skip(pb, size - 16); /* skip rest of ds64 chunk */ + if (data_size < 0 || sample_count < 0) { + av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in " + "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n", + data_size, sample_count); + return AVERROR_INVALIDDATA; + } + avio_skip(pb, size - 24); /* skip rest of ds64 chunk */ } - /* parse fmt header */ - size = find_tag(pb, MKTAG('f', 'm', 't', ' ')); - if (size < 0) - return -1; - st = av_new_stream(s, 0); - if (!st) - return AVERROR(ENOMEM); + for (;;) { + size = next_tag(pb, &tag); + next_tag_ofs = avio_tell(pb) + size; - ret = ff_get_wav_header(pb, st->codec, size); - if (ret < 0) - return ret; - st->need_parsing = AVSTREAM_PARSE_FULL; + if (url_feof(pb)) + break; - av_set_pts_info(st, 64, 1, st->codec->sample_rate); + switch (tag) { + case MKTAG('f', 'm', 't', ' '): + /* only parse the first 'fmt ' tag found */ + if (!got_fmt && (ret = wav_parse_fmt_tag(s, size, &st) < 0)) { + return ret; + } else if (got_fmt) + av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n"); - for (;;) { - if (url_feof(pb)) - return -1; - size = next_tag(pb, &tag); - if (tag == MKTAG('d', 'a', 't', 'a')){ + got_fmt = 1; + break; + case MKTAG('d', 'a', 't', 'a'): + if (!got_fmt) { + av_log(s, AV_LOG_ERROR, "found no 'fmt ' tag before the 'data' tag\n"); + return AVERROR_INVALIDDATA; + } + + if (rf64) { + next_tag_ofs = wav->data_end = avio_tell(pb) + data_size; + } else { + data_size = size; + next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX; + } + + data_ofs = avio_tell(pb); + + /* don't look for footer metadata if we can't seek or if we don't + * know where the data tag ends + */ + if (!pb->seekable || (!rf64 && !size)) + goto break_loop; + break; + case MKTAG('f','a','c','t'): + if(!sample_count) + sample_count = avio_rl32(pb); + break; + case MKTAG('b','e','x','t'): + if ((ret = wav_parse_bext_tag(s, size)) < 0) + return ret; + break; + } + + /* seek to next tag unless we know that we'll run into EOF */ + if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) || + avio_seek(pb, next_tag_ofs, SEEK_SET) < 0) { break; - }else if (tag == MKTAG('f','a','c','t') && !sample_count){ - sample_count = avio_rl32(pb); - size -= 4; } - avio_skip(pb, size); } - if (rf64) - size = data_size; - if (size < 0) - return -1; - if (!size) { - wav->data_end = INT64_MAX; - } else - wav->data_end= avio_tell(pb) + size; +break_loop: + if (data_ofs < 0) { + av_log(s, AV_LOG_ERROR, "no 'data' tag found\n"); + return AVERROR_INVALIDDATA; + } + + avio_seek(pb, data_ofs, SEEK_SET); if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id)) - sample_count = (size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id)); + sample_count = (data_size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id)); if (sample_count) st->duration = sample_count; + + ff_metadata_conv_ctx(s, NULL, wav_metadata_conv); + return 0; } diff --git a/libavformat/wc3movie.c b/libavformat/wc3movie.c index 0f2e077859..eb2eae1c9c 100644 --- a/libavformat/wc3movie.c +++ b/libavformat/wc3movie.c @@ -28,6 +28,7 @@ */ #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #define FORM_TAG MKTAG('F', 'O', 'R', 'M') @@ -130,8 +131,8 @@ static int wc3_read_header(AVFormatContext *s, if ((ret = avio_read(pb, buffer, size)) != size) return AVERROR(EIO); buffer[size] = 0; - av_metadata_set2(&s->metadata, "title", buffer, - AV_METADATA_DONT_STRDUP_VAL); + av_dict_set(&s->metadata, "title", buffer, + AV_DICT_DONT_STRDUP_VAL); break; case SIZE_TAG: diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c index 5cbec0576a..5fe7e9fe12 100644 --- a/libavformat/wtvdec.c +++ b/libavformat/wtvdec.c @@ -431,7 +431,7 @@ static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length) st = av_new_stream(s, 0); if (!st) goto done; - av_metadata_set2(&st->metadata, "title", description, 0); + av_dict_set(&st->metadata, "title", description, 0); st->codec->codec_id = CODEC_ID_MJPEG; st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; st->codec->extradata = av_mallocz(filesize); @@ -494,7 +494,7 @@ static void get_tag(AVFormatContext *s, AVIOContext *pb, const char *key, int ty return; } - av_metadata_set2(&s->metadata, key, buf, 0); + av_dict_set(&s->metadata, key, buf, 0); av_freep(&buf); } @@ -818,7 +818,7 @@ static int parse_chunks(AVFormatContext *s, int mode, int64_t seekts, int *len_p avio_read(pb, language, 3); if (language[0]) { language[3] = 0; - av_metadata_set2(&st->metadata, "language", language, 0); + av_dict_set(&st->metadata, "language", language, 0); if (!strcmp(language, "nar") || !strcmp(language, "NAR")) st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; } diff --git a/libavformat/wv.c b/libavformat/wv.c index 52ec9264a0..9da416e580 100644 --- a/libavformat/wv.c +++ b/libavformat/wv.c @@ -21,6 +21,7 @@ #include "libavutil/audioconvert.h" #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" #include "apetag.h" #include "id3v1.h" @@ -226,7 +227,7 @@ static int wv_read_header(AVFormatContext *s, if(s->pb->seekable) { int64_t cur = avio_tell(s->pb); ff_ape_parse_tag(s); - if(!av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) + if(!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); avio_seek(s->pb, cur, SEEK_SET); } diff --git a/libavformat/yuv4mpeg.c b/libavformat/yuv4mpeg.c index a852568a64..90b222d1d4 100644 --- a/libavformat/yuv4mpeg.c +++ b/libavformat/yuv4mpeg.c @@ -94,7 +94,7 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) AVPicture *picture; int* first_pkt = s->priv_data; int width, height, h_chroma_shift, v_chroma_shift; - int i, m; + int i; char buf2[Y4M_LINE_MAX+1]; char buf1[20]; uint8_t *ptr, *ptr1, *ptr2; @@ -114,7 +114,7 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) /* construct frame header */ - m = snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC); + snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC); avio_write(pb, buf1, strlen(buf1)); width = st->codec->width; @@ -154,6 +154,12 @@ static int yuv4_write_header(AVFormatContext *s) if (s->nb_streams != 1) return AVERROR(EIO); + if (s->streams[0]->codec->codec_id != CODEC_ID_RAWVIDEO) { + av_log(s, AV_LOG_ERROR, + "A non-rawvideo stream was selected, but yuv4mpeg only handles rawvideo streams\n"); + return AVERROR(EINVAL); + } + if (s->streams[0]->codec->pix_fmt == PIX_FMT_YUV411P) { av_log(s, AV_LOG_ERROR, "Warning: generating rarely used 4:1:1 YUV stream, some mjpegtools might not work.\n"); } |