#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"
{ "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "use_metadata_tags", "Use mdta atom for metadata.", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "skip_trailer", "Skip writing the mfra/tfra/mfro trailer for fragmented files", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_TRAILER}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+ { "negative_cts_offsets", "Use negative CTS offsets (reducing the need for edit lists)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
{ "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
{ "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
return AVERROR_INVALIDDATA;
if (!info->num_blocks) {
- int ret;
- if ((ret = av_copy_packet(&info->pkt, pkt)) < 0)
+ int ret = av_packet_ref(&info->pkt, pkt);
+ if (ret < 0)
return ret;
info->num_blocks = num_blocks;
return 0;
if (info->num_blocks != 6)
return 0;
av_packet_unref(pkt);
- if ((ret = av_copy_packet(pkt, &info->pkt)) < 0)
+ ret = av_packet_ref(pkt, &info->pkt);
+ if (ret < 0)
return ret;
av_packet_unref(&info->pkt);
info->num_blocks = 0;
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);
}
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;
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);
return update_size(pb, pos);
}
+static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track)
+{
+ int64_t pos = avio_tell(pb);
+ avio_wb32(pb, 0); /* size */
+ ffio_wfourcc(pb, "gpmd");
+ avio_wb32(pb, 0); /* Reserved */
+ avio_wb16(pb, 0); /* Reserved */
+ avio_wb16(pb, 1); /* Data-reference index */
+ avio_wb32(pb, 0); /* Reserved */
+ return update_size(pb, pos);
+}
+
static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
{
int64_t pos = avio_tell(pb);
mov_write_rtp_tag(pb, track);
else if (track->par->codec_tag == MKTAG('t','m','c','d'))
mov_write_tmcd_tag(pb, track);
+ else if (track->par->codec_tag == MKTAG('g','p','m','d'))
+ mov_write_gpmd_tag(pb, track);
return update_size(pb, pos);
}
-static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
{
+ MOVMuxContext *mov = s->priv_data;
MOVStts *ctts_entries;
uint32_t entries = 0;
uint32_t atom_size;
atom_size = 16 + (entries * 8);
avio_wb32(pb, atom_size); /* size */
ffio_wfourcc(pb, "ctts");
- avio_wb32(pb, 0); /* version & flags */
+ if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
+ avio_w8(pb, 1); /* version */
+ else
+ avio_w8(pb, 0); /* version */
+ avio_wb24(pb, 0); /* flags */
avio_wb32(pb, entries); /* entry count */
for (i = 0; i < entries; i++) {
avio_wb32(pb, ctts_entries[i].count);
(AVRational){1, 1000},
(AVRational){1, 48000});
- if (track->entry) {
- sgpd_entries = av_malloc_array(track->entry, sizeof(*sgpd_entries));
- if (!sgpd_entries)
- return AVERROR(ENOMEM);
- }
+ if (!track->entry)
+ return 0;
- av_assert0(track->par->codec_id == AV_CODEC_ID_OPUS);
+ sgpd_entries = av_malloc_array(track->entry, sizeof(*sgpd_entries));
+ if (!sgpd_entries)
+ return AVERROR(ENOMEM);
- for (i = 0; i < track->entry; i++) {
- int roll_samples_remaining = roll_samples;
- int distance = 0;
- for (j = i - 1; j >= 0; j--) {
- roll_samples_remaining -= get_cluster_duration(track, j);
- distance++;
- if (roll_samples_remaining <= 0)
- break;
- }
- /* We don't have enough preceeding samples to compute a valid
- roll_distance here, so this sample can't be independently
- decoded. */
- if (roll_samples_remaining > 0)
- distance = 0;
- /* Verify distance is a minimum of 2 (60ms) packets and a maximum of
- 32 (2.5ms) packets. */
- av_assert0(distance == 0 || (distance >= 2 && distance <= 32));
- if (i && distance == sgpd_entries[entries].roll_distance) {
- sgpd_entries[entries].count++;
- } else {
- entries++;
- sgpd_entries[entries].count = 1;
- sgpd_entries[entries].roll_distance = distance;
- sgpd_entries[entries].group_description_index = distance ? ++group : 0;
+ av_assert0(track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC);
+
+ if (track->par->codec_id == AV_CODEC_ID_OPUS) {
+ for (i = 0; i < track->entry; i++) {
+ int roll_samples_remaining = roll_samples;
+ int distance = 0;
+ for (j = i - 1; j >= 0; j--) {
+ roll_samples_remaining -= get_cluster_duration(track, j);
+ distance++;
+ if (roll_samples_remaining <= 0)
+ break;
+ }
+ /* We don't have enough preceeding samples to compute a valid
+ roll_distance here, so this sample can't be independently
+ decoded. */
+ if (roll_samples_remaining > 0)
+ distance = 0;
+ /* Verify distance is a minimum of 2 (60ms) packets and a maximum of
+ 32 (2.5ms) packets. */
+ av_assert0(distance == 0 || (distance >= 2 && distance <= 32));
+ if (i && distance == sgpd_entries[entries].roll_distance) {
+ sgpd_entries[entries].count++;
+ } else {
+ entries++;
+ sgpd_entries[entries].count = 1;
+ sgpd_entries[entries].roll_distance = distance;
+ sgpd_entries[entries].group_description_index = distance ? ++group : 0;
+ }
}
+ } else {
+ entries++;
+ sgpd_entries[entries].count = track->sample_count;
+ sgpd_entries[entries].roll_distance = 1;
+ sgpd_entries[entries].group_description_index = ++group;
}
entries++;
if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
track->flags & MOV_TRACK_CTTS && track->entry) {
- if ((ret = mov_write_ctts_tag(pb, track)) < 0)
+ if ((ret = mov_write_ctts_tag(s, pb, track)) < 0)
return ret;
}
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) {
+ if (track->par->codec_id == AV_CODEC_ID_OPUS || track->par->codec_id == AV_CODEC_ID_AAC) {
mov_preroll_write_stbl_atoms(pb, track);
}
return update_size(pb, pos);
ffio_wfourcc(pb, "tmcd");
mov_write_tcmi_tag(pb, track);
update_size(pb, tmcd_pos);
+ } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
+ int64_t gpmd_pos = avio_tell(pb);
+ avio_wb32(pb, 0); /* size */
+ ffio_wfourcc(pb, "gpmd");
+ avio_wb32(pb, 0); /* version */
+ update_size(pb, gpmd_pos);
}
return update_size(pb, pos);
}
} else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
hdlr_type = "tmcd";
descr = "TimeCodeHandler";
+ } else if (track->par->codec_tag == MKTAG('g','p','m','d')) {
+ hdlr_type = "meta";
+ descr = "GoPro MET"; // GoPro Metadata
} else {
av_log(s, AV_LOG_WARNING,
"Unknown hldr_type for %s, writing dummy values\n",
mov_write_nmhd_tag(pb);
else
mov_write_gmhd_tag(pb, track);
+ } else if (track->tag == MKTAG('g','p','m','d')) {
+ mov_write_gmhd_tag(pb, track);
}
if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
mov_write_hdlr_tag(s, pb, NULL);
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);
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 */
avio_wb32(pb, 0); /* size placeholder */
ffio_wfourcc(pb, "trun");
- avio_w8(pb, 0); /* version */
+ if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
+ avio_w8(pb, 1); /* version */
+ else
+ avio_w8(pb, 0); /* version */
avio_wb24(pb, flags);
avio_wb32(pb, end - first); /* sample count */
ffio_wfourcc(pb, "MSNV");
else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
+ else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)
+ ffio_wfourcc(pb, "iso4");
else if (mov->mode == MODE_MP4)
ffio_wfourcc(pb, "isom");
else if (mov->mode == MODE_IPOD)
if (!track->end_reliable) {
AVPacket pkt;
if (!ff_interleaved_peek(s, i, &pkt, 1)) {
+ if (track->dts_shift != AV_NOPTS_VALUE)
+ pkt.dts += track->dts_shift;
track->track_duration = pkt.dts - track->start_dts;
if (pkt.pts != AV_NOPTS_VALUE)
track->end_pts = pkt.pts;
&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;
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);
mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
}
+ if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) {
+ if (trk->dts_shift == AV_NOPTS_VALUE)
+ trk->dts_shift = pkt->pts - pkt->dts;
+ pkt->dts += trk->dts_shift;
+ }
+
+ 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;
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 */
}
track->start_dts = AV_NOPTS_VALUE;
track->start_cts = AV_NOPTS_VALUE;
track->end_pts = AV_NOPTS_VALUE;
+ track->dts_shift = AV_NOPTS_VALUE;
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
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 = {
.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,
};
.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,
};
.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,
};