X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmovenc.c;h=3989ac167e1b3b1d7327b96189886a3c107df4d4;hb=a27c412795c2147e71c5b10782c97a15bf9dc81f;hp=d20d272f89faecf8d76e000e3e164b19a1403d83;hpb=2eb8fcff0f998e20e5b3e67eb9de4d805eb71380;p=ffmpeg diff --git a/libavformat/movenc.c b/libavformat/movenc.c index d20d272f89f..3989ac167e1 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -35,6 +35,8 @@ #include "libavcodec/dnxhddata.h" #include "libavcodec/flac.h" #include "libavcodec/get_bits.h" + +#include "libavcodec/internal.h" #include "libavcodec/put_bits.h" #include "libavcodec/vc1_common.h" #include "libavcodec/raw.h" @@ -1112,7 +1114,8 @@ static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra avio_wb32(pb, 0); ffio_wfourcc(pb, "vpcC"); - avio_wb32(pb, 0); /* version & flags */ + avio_w8(pb, 1); /* version */ + avio_wb24(pb, 0); /* flags */ ff_isom_write_vpcc(s, pb, track->par); return update_size(pb, pos); } @@ -1123,7 +1126,10 @@ static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); ffio_wfourcc(pb, "hvcC"); - ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0); + if (track->tag == MKTAG('h','v','c','1')) + ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1); + else + ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0); return update_size(pb, pos); } @@ -1224,60 +1230,6 @@ static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track) return 0; } -static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track) -{ - int tag = track->par->codec_tag; - - if (!ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id)) - return 0; - - if (track->par->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1'); - else if (track->par->codec_id == AV_CODEC_ID_HEVC) tag = MKTAG('h','e','v','1'); - else if (track->par->codec_id == AV_CODEC_ID_VP9) tag = MKTAG('v','p','0','9'); - else if (track->par->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3'); - else if (track->par->codec_id == AV_CODEC_ID_EAC3) tag = MKTAG('e','c','-','3'); - else if (track->par->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); - else if (track->par->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g'); - else if (track->par->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1'); - else if (track->par->codec_id == AV_CODEC_ID_FLAC) tag = MKTAG('f','L','a','C'); - else if (track->par->codec_id == AV_CODEC_ID_OPUS) tag = MKTAG('O','p','u','s'); - else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); - else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); - else if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) tag = MKTAG('m','p','4','s'); - - return tag; -} - -static const AVCodecTag codec_ipod_tags[] = { - { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, - { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, - { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, - { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') }, - { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') }, - { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, - { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') }, - { AV_CODEC_ID_NONE, 0 }, -}; - -static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track) -{ - int tag = track->par->codec_tag; - - // keep original tag for subs, ipod supports both formats - if (!(track->par->codec_type == AVMEDIA_TYPE_SUBTITLE && - (tag == MKTAG('t', 'x', '3', 'g') || - tag == MKTAG('t', 'e', 'x', 't')))) - tag = ff_codec_get_tag(codec_ipod_tags, track->par->codec_id); - - if (!av_match_ext(s->filename, "m4a") && - !av_match_ext(s->filename, "m4b") && - !av_match_ext(s->filename, "m4v")) - av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a, .m4v nor .m4b " - "Quicktime/Ipod might not play the file\n"); - - return tag; -} - static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag; @@ -1554,42 +1506,25 @@ static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track) return tag; } -static const AVCodecTag codec_3gp_tags[] = { - { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, - { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, - { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, - { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, - { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, - { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') }, - { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, - { AV_CODEC_ID_NONE, 0 }, -}; - -static const AVCodecTag codec_f4v_tags[] = { // XXX: add GIF/PNG/JPEG? - { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') }, - { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, - { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, - { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') }, - { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') }, - { AV_CODEC_ID_NONE, 0 }, -}; - static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) { int tag; if (track->mode == MODE_MP4 || track->mode == MODE_PSP) - tag = mp4_get_codec_tag(s, track); - else if (track->mode == MODE_ISM) { - tag = mp4_get_codec_tag(s, track); - if (!tag && track->par->codec_id == AV_CODEC_ID_WMAPRO) - tag = MKTAG('w', 'm', 'a', ' '); - } else if (track->mode == MODE_IPOD) - tag = ipod_get_codec_tag(s, track); - else if (track->mode & MODE_3GP) - tag = ff_codec_get_tag(codec_3gp_tags, track->par->codec_id); + tag = track->par->codec_tag; + else if (track->mode == MODE_ISM) + tag = track->par->codec_tag; + else if (track->mode == MODE_IPOD) { + if (!av_match_ext(s->filename, "m4a") && + !av_match_ext(s->filename, "m4v") && + !av_match_ext(s->filename, "m4b")) + av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor .m4v " + "Quicktime/Ipod might not play the file\n"); + tag = track->par->codec_tag; + } else if (track->mode & MODE_3GP) + tag = track->par->codec_tag; else if (track->mode == MODE_F4V) - tag = ff_codec_get_tag(codec_f4v_tags, track->par->codec_id); + tag = track->par->codec_tag; else tag = mov_get_codec_tag(s, track); @@ -2352,7 +2287,7 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext mov_write_stsc_tag(pb, track); mov_write_stsz_tag(pb, track); mov_write_stco_tag(pb, track); - if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { + if (track->cenc.aes_ctr) { ff_mov_cenc_write_stbl_atoms(&track->cenc, pb); } if (track->par->codec_id == AV_CODEC_ID_OPUS) { @@ -3386,6 +3321,7 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_string_metadata(s, pb, "tvsh", "show" , 1); mov_write_string_metadata(s, pb, "tven", "episode_id",1); mov_write_string_metadata(s, pb, "tvnn", "network" , 1); + mov_write_string_metadata(s, pb, "keyw", "keywords" , 1); mov_write_int8_metadata (s, pb, "tves", "episode_sort",4); mov_write_int8_metadata (s, pb, "tvsn", "season_number",4); mov_write_int8_metadata (s, pb, "stik", "media_type",1); @@ -3608,6 +3544,7 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_string_metadata(s, pb_buf, "\251mak", "make", 0); mov_write_string_metadata(s, pb_buf, "\251mod", "model", 0); mov_write_string_metadata(s, pb_buf, "\251xyz", "location", 0); + mov_write_string_metadata(s, pb_buf, "\251key", "keywords", 0); mov_write_raw_metadata_tag(s, pb_buf, "XMP_", "xmp"); } else { /* iTunes meta data */ @@ -5113,7 +5050,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) &size); avio_write(pb, reformatted_data, size); } else { - if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { + if (trk->cenc.aes_ctr) { size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size); if (size < 0) { ret = size; @@ -5142,7 +5079,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) avio_write(pb, pkt->data, size); #endif } else { - if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { + if (trk->cenc.aes_ctr) { if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) { int nal_size_length = (par->extradata[4] & 0x3) + 1; ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size); @@ -5312,6 +5249,24 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT; } + if (trk->par->codec_id == AV_CODEC_ID_MP4ALS || + trk->par->codec_id == AV_CODEC_ID_AAC || + trk->par->codec_id == AV_CODEC_ID_FLAC) { + int side_size = 0; + uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); + if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { + void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!newextra) + return AVERROR(ENOMEM); + av_free(par->extradata); + par->extradata = newextra; + memcpy(par->extradata, side, side_size); + par->extradata_size = side_size; + if (!pkt->size) // Flush packet + mov->need_rewrite_extradata = 1; + } + } + if (!pkt->size) { if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) { trk->start_dts = pkt->dts; @@ -5321,22 +5276,6 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) trk->start_cts = 0; } - if (trk->par->codec_id == AV_CODEC_ID_MP4ALS || - trk->par->codec_id == AV_CODEC_ID_FLAC) { - int side_size = 0; - uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); - if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { - void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!newextra) - return AVERROR(ENOMEM); - av_free(par->extradata); - par->extradata = newextra; - memcpy(par->extradata, side, side_size); - par->extradata_size = side_size; - mov->need_rewrite_extradata = 1; - } - } - return 0; /* Discard 0 sized packets */ } @@ -5995,13 +5934,6 @@ static int mov_init(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "VP9 only supported in MP4.\n"); return AVERROR(EINVAL); } - if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { - av_log(s, AV_LOG_ERROR, - "VP9 in MP4 support is experimental, add " - "'-strict %d' if you want to use it.\n", - FF_COMPLIANCE_EXPERIMENTAL); - return AVERROR_EXPERIMENTAL; - } } } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { track->timescale = st->codecpar->sample_rate; @@ -6492,6 +6424,73 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) return ret; } +static const AVCodecTag codec_3gp_tags[] = { + { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, + { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, + { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, + { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, + { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, + { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') }, + { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, + { AV_CODEC_ID_NONE, 0 }, +}; + +const AVCodecTag codec_mp4_tags[] = { + { AV_CODEC_ID_MPEG4 , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_H264 , MKTAG('a', 'v', 'c', '1') }, + { AV_CODEC_ID_HEVC , MKTAG('h', 'e', 'v', '1') }, + { AV_CODEC_ID_HEVC , MKTAG('h', 'v', 'c', '1') }, + { AV_CODEC_ID_MPEG2VIDEO , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_MPEG1VIDEO , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_MJPEG , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_PNG , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_JPEG2000 , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_VC1 , MKTAG('v', 'c', '-', '1') }, + { AV_CODEC_ID_DIRAC , MKTAG('d', 'r', 'a', 'c') }, + { AV_CODEC_ID_TSCC2 , MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_VP9 , MKTAG('v', 'p', '0', '9') }, + { AV_CODEC_ID_AAC , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_MP4ALS , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_MP3 , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_MP2 , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_AC3 , MKTAG('a', 'c', '-', '3') }, + { AV_CODEC_ID_EAC3 , MKTAG('e', 'c', '-', '3') }, + { AV_CODEC_ID_DTS , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_FLAC , MKTAG('f', 'L', 'a', 'C') }, + { AV_CODEC_ID_OPUS , MKTAG('O', 'p', 'u', 's') }, + { AV_CODEC_ID_VORBIS , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_QCELP , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_EVRC , MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') }, + { AV_CODEC_ID_MOV_TEXT , MKTAG('t', 'x', '3', 'g') }, + { AV_CODEC_ID_NONE , 0 }, +}; + +const AVCodecTag codec_ism_tags[] = { + { AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') }, + { AV_CODEC_ID_NONE , 0 }, +}; + +static const AVCodecTag codec_ipod_tags[] = { + { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, + { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, + { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, + { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') }, + { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') }, + { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, + { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') }, + { AV_CODEC_ID_NONE, 0 }, +}; + +static const AVCodecTag codec_f4v_tags[] = { + { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') }, + { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, + { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, + { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') }, + { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') }, + { AV_CODEC_ID_NONE, 0 }, +}; + #if CONFIG_MOV_MUXER MOV_CLASS(mov) AVOutputFormat ff_mov_muxer = { @@ -6552,7 +6551,7 @@ AVOutputFormat ff_mp4_muxer = { .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .codec_tag = (const AVCodecTag* const []){ codec_mp4_tags, 0 }, .check_bitstream = mov_check_bitstream, .priv_class = &mp4_muxer_class, }; @@ -6573,7 +6572,7 @@ AVOutputFormat ff_psp_muxer = { .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .codec_tag = (const AVCodecTag* const []){ codec_mp4_tags, 0 }, .check_bitstream = mov_check_bitstream, .priv_class = &psp_muxer_class, }; @@ -6635,7 +6634,8 @@ AVOutputFormat ff_ismv_muxer = { .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, + .codec_tag = (const AVCodecTag* const []){ + codec_mp4_tags, codec_ism_tags, 0 }, .check_bitstream = mov_check_bitstream, .priv_class = &ismv_muxer_class, };