diff --git a/libavformat/movenc.c b/libavformat/movenc.c index bb0af11863..96fb31655d 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -654,8 +654,8 @@ static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra */ static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track) { - avio_write(pb, track->par->extradata, track->par->extradata_size); - return track->par->extradata_size; + avio_write(pb, track->extradata[track->last_stsd_index], track->extradata_size[track->last_stsd_index]); + return track->extradata_size[track->last_stsd_index]; } static int mov_write_enda_tag(AVIOContext *pb) @@ -749,7 +749,8 @@ static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic { struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track); int64_t pos = avio_tell(pb); - int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0; + int decoder_specific_info_len = track->extradata_size[track->last_stsd_index] ? + 5 + track->extradata_size[track->last_stsd_index] : 0; avio_wb32(pb, 0); // size ffio_wfourcc(pb, "esds"); @@ -784,10 +785,11 @@ static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic avio_wb32(pb, bit_rates.max_bit_rate); // maxbitrate avio_wb32(pb, bit_rates.avg_bit_rate); - if (track->vos_len) { + if (track->extradata_size[track->last_stsd_index]) { // DecoderSpecific info descriptor - put_descr(pb, 0x05, track->vos_len); - avio_write(pb, track->vos_data, track->vos_len); + put_descr(pb, 0x05, track->extradata_size[track->last_stsd_index]); + avio_write(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index]); } // SL descriptor @@ -844,13 +846,13 @@ static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track) avio_wb24(pb, 0); /* flags */ /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */ - if (track->par->extradata_size != FLAC_STREAMINFO_SIZE) + if (track->extradata_size[track->last_stsd_index] != FLAC_STREAMINFO_SIZE) return AVERROR_INVALIDDATA; /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */ avio_w8(pb, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */ - avio_wb24(pb, track->par->extradata_size); /* Length */ - avio_write(pb, track->par->extradata, track->par->extradata_size); /* BlockData[Length] */ + avio_wb24(pb, track->extradata_size[track->last_stsd_index]); /* Length */ + avio_write(pb, track->extradata[track->last_stsd_index], track->extradata_size[track->last_stsd_index]); /* BlockData[Length] */ return update_size(pb, pos); } @@ -862,28 +864,28 @@ static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra avio_wb32(pb, 0); ffio_wfourcc(pb, "dOps"); avio_w8(pb, 0); /* Version */ - if (track->par->extradata_size < 19) { + if (track->extradata_size[track->last_stsd_index] < 19) { av_log(s, AV_LOG_ERROR, "invalid extradata size\n"); return AVERROR_INVALIDDATA; } /* extradata contains an Ogg OpusHead, other than byte-ordering and OpusHead's preceeding magic/version, OpusSpecificBox is currently identical. */ - channels = AV_RB8(track->par->extradata + 9); - channel_map = AV_RB8(track->par->extradata + 18); + channels = AV_RB8(track->extradata[track->last_stsd_index] + 9); + channel_map = AV_RB8(track->extradata[track->last_stsd_index] + 18); avio_w8(pb, channels); /* OuputChannelCount */ - avio_wb16(pb, AV_RL16(track->par->extradata + 10)); /* PreSkip */ - avio_wb32(pb, AV_RL32(track->par->extradata + 12)); /* InputSampleRate */ - avio_wb16(pb, AV_RL16(track->par->extradata + 16)); /* OutputGain */ + avio_wb16(pb, AV_RL16(track->extradata[track->last_stsd_index] + 10)); /* PreSkip */ + avio_wb32(pb, AV_RL32(track->extradata[track->last_stsd_index] + 12)); /* InputSampleRate */ + avio_wb16(pb, AV_RL16(track->extradata[track->last_stsd_index] + 16)); /* OutputGain */ avio_w8(pb, channel_map); /* ChannelMappingFamily */ /* Write the rest of the header out without byte-swapping. */ if (channel_map) { - if (track->par->extradata_size < 21 + channels) { + if (track->extradata_size[track->last_stsd_index] < 21 + channels) { av_log(s, AV_LOG_ERROR, "invalid extradata size\n"); return AVERROR_INVALIDDATA; } - avio_write(pb, track->par->extradata + 19, 2 + channels); /* ChannelMappingTable */ + avio_write(pb, track->extradata[track->last_stsd_index] + 19, 2 + channels); /* ChannelMappingTable */ } return update_size(pb, pos); @@ -896,23 +898,23 @@ static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra avio_wb32(pb, 0); ffio_wfourcc(pb, "dmlp"); - if (track->vos_len < 20) { + if (track->extradata_size[track->last_stsd_index] < 20) { av_log(s, AV_LOG_ERROR, "Cannot write moov atom before TrueHD packets." " Set the delay_moov flag to fix this.\n"); return AVERROR(EINVAL); } - length = (AV_RB16(track->vos_data) & 0xFFF) * 2; - if (length < 20 || length > track->vos_len) + length = (AV_RB16(track->extradata[track->last_stsd_index]) & 0xFFF) * 2; + if (length < 20 || length > track->extradata_size[track->last_stsd_index]) return AVERROR_INVALIDDATA; // Only TrueHD is supported - if (AV_RB32(track->vos_data + 4) != 0xF8726FBA) + if (AV_RB32(track->extradata[track->last_stsd_index] + 4) != 0xF8726FBA) return AVERROR_INVALIDDATA; - avio_wb32(pb, AV_RB32(track->vos_data + 8)); /* format_info */ - avio_wb16(pb, AV_RB16(track->vos_data + 18) << 1); /* peak_data_rate */ + avio_wb32(pb, AV_RB32(track->extradata[track->last_stsd_index] + 8)); /* format_info */ + avio_wb16(pb, AV_RB16(track->extradata[track->last_stsd_index] + 18) << 1); /* peak_data_rate */ avio_wb32(pb, 0); /* reserved */ return update_size(pb, pos); @@ -1078,7 +1080,8 @@ static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf) { uint8_t *unescaped; - const uint8_t *start, *next, *end = track->vos_data + track->vos_len; + const uint8_t *start, *next, *end = track->extradata[track->last_stsd_index] + + track->extradata_size[track->last_stsd_index]; int unescaped_size, seq_found = 0; int level = 0, interlace = 0; int packet_seq = track->vc1_info.packet_seq; @@ -1095,10 +1098,10 @@ static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf) "dvc1 atom. Set the delay_moov flag to fix this.\n"); } - unescaped = av_mallocz(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE); + unescaped = av_mallocz(track->extradata_size[track->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE); if (!unescaped) return AVERROR(ENOMEM); - start = find_next_marker(track->vos_data, end); + start = find_next_marker(track->extradata[track->last_stsd_index], end); for (next = start; next < end; start = next) { GetBitContext gb; int size; @@ -1166,20 +1169,22 @@ static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track) if ((ret = mov_write_dvc1_structs(track, buf)) < 0) return ret; - avio_wb32(pb, track->vos_len + 8 + sizeof(buf)); + avio_wb32(pb, track->extradata_size[track->last_stsd_index] + 8 + sizeof(buf)); ffio_wfourcc(pb, "dvc1"); avio_write(pb, buf, sizeof(buf)); - avio_write(pb, track->vos_data, track->vos_len); + avio_write(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index]); return 0; } static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track) { - avio_wb32(pb, track->vos_len + 8); + avio_wb32(pb, track->extradata_size[track->last_stsd_index] + 8); ffio_wfourcc(pb, "glbl"); - avio_write(pb, track->vos_data, track->vos_len); - return 8 + track->vos_len; + avio_write(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index]); + return 8 + track->extradata_size[track->last_stsd_index]; } /** @@ -1476,7 +1481,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex if (ret < 0) return ret; ret = mov_write_pcmc_tag(s, pb, track); - } else if (track->vos_len > 0) + } else if (track->extradata_size[track->last_stsd_index] > 0) ret = mov_write_glbl_tag(pb, track); if (ret < 0) @@ -1523,7 +1528,8 @@ static int mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); ffio_wfourcc(pb, "av1C"); - ff_isom_write_av1c(pb, track->vos_data, track->vos_len, track->mode != MODE_AVIF); + ff_isom_write_av1c(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], track->mode != MODE_AVIF); return update_size(pb, pos); } @@ -1533,7 +1539,8 @@ static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); ffio_wfourcc(pb, "avcC"); - ff_isom_write_avcc(pb, track->vos_data, track->vos_len); + ff_isom_write_avcc(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index]); return update_size(pb, pos); } @@ -1565,7 +1572,8 @@ static int mov_write_av3c_tag(AVIOContext *pb, MOVTrack *track) int64_t pos = avio_tell(pb); avio_wb32(pb, 0); ffio_wfourcc(pb, "av3c"); - mov_write_av3c(pb, track->vos_data, track->vos_len); + mov_write_av3c(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index]); return update_size(pb, pos); } @@ -1575,7 +1583,8 @@ static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra avio_wb32(pb, 0); ffio_wfourcc(pb, "vpcC"); - ff_isom_write_vpcc(s, pb, track->vos_data, track->vos_len, track->par); + ff_isom_write_vpcc(s, pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], track->par); return update_size(pb, pos); } @@ -1586,9 +1595,11 @@ static int mov_write_hvcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra avio_wb32(pb, 0); ffio_wfourcc(pb, "hvcC"); if (track->tag == MKTAG('h','v','c','1')) - ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1, s); + ff_isom_write_hvcc(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], 1, s); else - ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0, s); + ff_isom_write_hvcc(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], 0, s); return update_size(pb, pos); } @@ -1600,9 +1611,11 @@ static int mov_write_lhvc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra avio_wb32(pb, 0); ffio_wfourcc(pb, "lhvC"); if (track->tag == MKTAG('h','v','c','1')) - ret = ff_isom_write_lhvc(pb, track->vos_data, track->vos_len, 1, s); + ret = ff_isom_write_lhvc(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], 1, s); else - ret = ff_isom_write_lhvc(pb, track->vos_data, track->vos_len, 0, s); + ret = ff_isom_write_lhvc(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], 0, s); if (ret < 0) { avio_seek(pb, pos, SEEK_SET); @@ -1620,9 +1633,11 @@ static int mov_write_evcc_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "evcC"); if (track->tag == MKTAG('e','v','c','1')) - ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 1); + ff_isom_write_evcc(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], 1); else - ff_isom_write_evcc(pb, track->vos_data, track->vos_len, 0); + ff_isom_write_evcc(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], 0); return update_size(pb, pos); } @@ -1638,9 +1653,11 @@ static int mov_write_vvcc_tag(AVIOContext *pb, MOVTrack *track) avio_wb24(pb, 0); /* flags */ if (track->tag == MKTAG('v','v','c','1')) - ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 1); + ff_isom_write_vvcc(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], 1); else - ff_isom_write_vvcc(pb, track->vos_data, track->vos_len, 0); + ff_isom_write_vvcc(pb, track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index], 0); return update_size(pb, pos); } @@ -1666,11 +1683,11 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) int cid; int display_width = track->par->width; - if (track->vos_data && track->vos_len > 0x29) { - if (ff_dnxhd_parse_header_prefix(track->vos_data) != 0) { + if (track->extradata[track->last_stsd_index] && track->extradata_size[track->last_stsd_index] > 0x29) { + if (ff_dnxhd_parse_header_prefix(track->extradata[track->last_stsd_index]) != 0) { /* looks like a DNxHD bit stream */ - interlaced = (track->vos_data[5] & 2); - cid = AV_RB32(track->vos_data + 0x28); + interlaced = (track->extradata[track->last_stsd_index][5] & 2); + cid = AV_RB32(track->extradata[track->last_stsd_index] + 0x28); } else { av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n"); return 0; @@ -1745,9 +1762,9 @@ static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track) { avio_wb32(pb, 12); ffio_wfourcc(pb, "DpxE"); - if (track->par->extradata_size >= 12 && - !memcmp(&track->par->extradata[4], "DpxE", 4)) { - avio_wb32(pb, track->par->extradata[11]); + if (track->extradata_size[track->last_stsd_index] >= 12 && + !memcmp(&track->extradata[track->last_stsd_index][4], "DpxE", 4)) { + avio_wb32(pb, track->extradata[track->last_stsd_index][11]); } else { avio_wb32(pb, 1); } @@ -2158,8 +2175,8 @@ static int mov_write_subtitle_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack track->track_id); return AVERROR(EINVAL); } - } else if (track->par->extradata_size) - avio_write(pb, track->par->extradata, track->par->extradata_size); + } else if (track->extradata_size[track->last_stsd_index]) + avio_write(pb, track->extradata[track->last_stsd_index], track->extradata_size[track->last_stsd_index]); if (mov->write_btrt && ((ret = mov_write_btrt_tag(pb, track)) < 0)) @@ -2788,7 +2805,7 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex mov_write_vpcc_tag(mov->fc, pb, track); } else if (track->par->codec_id == AV_CODEC_ID_AV1) { mov_write_av1c_tag(pb, track); - } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0) + } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->extradata_size[track->last_stsd_index] > 0) mov_write_dvc1_tag(pb, track); else if (track->par->codec_id == AV_CODEC_ID_VP6F || track->par->codec_id == AV_CODEC_ID_VP6A) { @@ -2799,7 +2816,7 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex mov_write_dpxe_tag(pb, track); } else if (track->par->codec_id == AV_CODEC_ID_AVS3) { mov_write_av3c_tag(pb, track); - } else if (track->vos_len > 0) + } else if (track->extradata_size[track->last_stsd_index] > 0) mov_write_glbl_tag(pb, track); if (track->par->codec_id != AV_CODEC_ID_H264 && @@ -3037,6 +3054,7 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext ffio_wfourcc(pb, "stsd"); avio_wb32(pb, 0); /* version & flags */ avio_wb32(pb, 1); /* entry count */ + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) ret = mov_write_video_tag(s, pb, mov, track); else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) @@ -5253,19 +5271,19 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormat if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { if (track->par->codec_id == AV_CODEC_ID_H264) { uint8_t *ptr; - int size = track->par->extradata_size; - if (!ff_avc_write_annexb_extradata(track->par->extradata, &ptr, + int size = track->extradata_size[track->last_stsd_index]; + if (!ff_avc_write_annexb_extradata(track->extradata[track->last_stsd_index], &ptr, &size)) { param_write_hex(pb, "CodecPrivateData", - ptr ? ptr : track->par->extradata, + ptr ? ptr : track->extradata[track->last_stsd_index], size); av_free(ptr); } param_write_string(pb, "FourCC", "H264"); } else if (track->par->codec_id == AV_CODEC_ID_VC1) { param_write_string(pb, "FourCC", "WVC1"); - param_write_hex(pb, "CodecPrivateData", track->par->extradata, - track->par->extradata_size); + param_write_hex(pb, "CodecPrivateData", track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index]); } param_write_int(pb, "MaxWidth", track->par->width); param_write_int(pb, "MaxHeight", track->par->height); @@ -5286,8 +5304,8 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormat } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) { param_write_string(pb, "FourCC", "WMAP"); } - param_write_hex(pb, "CodecPrivateData", track->par->extradata, - track->par->extradata_size); + param_write_hex(pb, "CodecPrivateData", track->extradata[track->last_stsd_index], + track->extradata_size[track->last_stsd_index]); param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id)); param_write_int(pb, "Channels", track->par->ch_layout.nb_channels); @@ -6713,17 +6731,15 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) } /* copy extradata if it exists */ - if (trk->vos_len == 0 && par->extradata_size > 0 && + if (trk->extradata_size[0] == 0 && par->extradata_size > 0 && !TAG_IS_AVCI(trk->tag) && (par->codec_id != AV_CODEC_ID_DNXHD)) { - trk->vos_len = par->extradata_size; - trk->vos_data = av_malloc(trk->vos_len + AV_INPUT_BUFFER_PADDING_SIZE); - if (!trk->vos_data) { + trk->extradata[0] = av_memdup(par->extradata, par->extradata_size); + if (!trk->extradata[0]) { ret = AVERROR(ENOMEM); goto err; } - memcpy(trk->vos_data, par->extradata, trk->vos_len); - memset(trk->vos_data + trk->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE); + trk->extradata_size[0] = par->extradata_size; } if ((par->codec_id == AV_CODEC_ID_DNXHD || @@ -6732,17 +6748,17 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) par->codec_id == AV_CODEC_ID_VVC || par->codec_id == AV_CODEC_ID_VP9 || par->codec_id == AV_CODEC_ID_EVC || - par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len && + par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->extradata_size[0] && !TAG_IS_AVCI(trk->tag)) { /* copy frame to create needed atoms */ - trk->vos_len = size; - trk->vos_data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!trk->vos_data) { + trk->extradata_size[0] = size; + trk->extradata[0] = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!trk->extradata[0]) { ret = AVERROR(ENOMEM); goto err; } - memcpy(trk->vos_data, pkt->data, size); - memset(trk->vos_data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + memcpy(trk->extradata[0], pkt->data, size); + memset(trk->extradata[0] + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); } if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && @@ -6755,7 +6771,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) } av_log(s, AV_LOG_WARNING, "aac bitstream error\n"); } - if (par->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1 && !TAG_IS_AVCI(trk->tag)) { + if (par->codec_id == AV_CODEC_ID_H264 && trk->extradata_size[trk->last_stsd_index] > 0 && + *(uint8_t *)trk->extradata[trk->last_stsd_index] != 1 && !TAG_IS_AVCI(trk->tag)) { /* from x264 or from bytestream H.264 */ /* NAL reformatting needed */ if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) { @@ -6775,8 +6792,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) size = ff_nal_parse_units(pb, pkt->data, pkt->size); } } - } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 && - (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) { + } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->extradata_size[trk->last_stsd_index] > 6 && + (AV_RB24(trk->extradata[trk->last_stsd_index]) == 1 || AV_RB32(trk->extradata[trk->last_stsd_index]) == 1)) { /* extradata is Annex B, assume the bitstream is too and convert it */ int filter_ps = (trk->tag == MKTAG('h','v','c','1')); if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) { @@ -6796,8 +6813,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, filter_ps, NULL); } } - } else if (par->codec_id == AV_CODEC_ID_VVC && trk->vos_len > 6 && - (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) { + } else if (par->codec_id == AV_CODEC_ID_VVC && trk->extradata_size[trk->last_stsd_index] > 6 && + (AV_RB24(trk->extradata[trk->last_stsd_index]) == 1 || AV_RB32(trk->extradata[trk->last_stsd_index]) == 1)) { /* extradata is Annex B, assume the bitstream is too and convert it */ if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) { ret = ff_vvc_annexb2mp4_buf(pkt->data, &reformatted_data, @@ -6854,11 +6871,13 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) avio_write(s->pb, pkt->data, pkt->size); } else { 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; + uint8_t *extradata = trk->extradata[trk->last_stsd_index]; + int extradata_size = trk->extradata_size[trk->last_stsd_index]; + if (par->codec_id == AV_CODEC_ID_H264 && extradata_size > 4) { + int nal_size_length = (extradata[4] & 0x3) + 1; ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size); - } else if(par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 21) { - int nal_size_length = (par->extradata[21] & 0x3) + 1; + } else if(par->codec_id == AV_CODEC_ID_HEVC && extradata_size > 21) { + int nal_size_length = (extradata[21] & 0x3) + 1; ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size); } else if(par->codec_id == AV_CODEC_ID_VVC) { ret = AVERROR_PATCHWELCOME; @@ -7050,16 +7069,14 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) trk->par->codec_id == AV_CODEC_ID_FLAC) { size_t side_size; 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); + /* Overwrite extradata only on flush packets or when no extradata was available during init */ + if (side_size > 0 && (!pkt->size || !trk->extradata_size[trk->last_stsd_index])) { + void *newextra = av_memdup(side, side_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; + av_free(trk->extradata[trk->last_stsd_index]); + trk->extradata[trk->last_stsd_index] = newextra; + trk->extradata_size[trk->last_stsd_index] = side_size; } } @@ -7398,6 +7415,11 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum) return ret; memcpy(track->par->extradata, stub_header, sizeof(stub_header)); + track->extradata[0] = av_memdup(stub_header, sizeof(stub_header)); + if (!track->extradata[0]) + return AVERROR(ENOMEM); + track->extradata_size[0] = sizeof(stub_header); + pkt->stream_index = tracknum; pkt->flags = AV_PKT_FLAG_KEY; @@ -7569,8 +7591,9 @@ static void mov_free(AVFormatContext *s) av_packet_free(&info->pkt); av_freep(&track->eac3_priv); } - if (track->vos_len) - av_freep(&track->vos_data); + for (int j = 0; j < track->stsd_count; j++) + av_freep(&track->extradata[j]); + av_freep(&track->extradata); ff_mov_cenc_free(&track->cenc); ffio_free_dyn_buf(&track->mdat_buf); @@ -7612,7 +7635,7 @@ static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, int i, width = 720, height = 480; int have_palette = 0, have_size = 0; uint32_t palette[16]; - char *cur = st->codecpar->extradata; + char *cur = track->extradata[track->last_stsd_index]; while (cur && *cur) { if (strncmp("palette:", cur, 8) == 0) { @@ -7641,14 +7664,14 @@ static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, cur += strspn(cur, "\n\r"); } if (have_palette) { - track->vos_data = av_malloc(16*4 + AV_INPUT_BUFFER_PADDING_SIZE); - if (!track->vos_data) + track->extradata[track->last_stsd_index] = av_malloc(16*4 + AV_INPUT_BUFFER_PADDING_SIZE); + if (!track->extradata[track->last_stsd_index]) return AVERROR(ENOMEM); for (i = 0; i < 16; i++) { - AV_WB32(track->vos_data + i * 4, palette[i]); + AV_WB32(track->extradata[track->last_stsd_index] + i * 4, palette[i]); } - memset(track->vos_data + 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE); - track->vos_len = 16 * 4; + memset(track->extradata[track->last_stsd_index] + 16*4, 0, AV_INPUT_BUFFER_PADDING_SIZE); + track->extradata_size[track->last_stsd_index] = 16 * 4; } st->codecpar->width = width; st->codecpar->height = track->height = height; @@ -7963,6 +7986,16 @@ static int mov_init(AVFormatContext *s) if (!mov->tracks) return AVERROR(ENOMEM); + for (i = 0; i < mov->nb_tracks; i++) { + MOVTrack *track = &mov->tracks[i]; + + track->stsd_count = 1; + track->extradata = av_calloc(track->stsd_count, sizeof(*track->extradata)); + track->extradata_size = av_calloc(track->stsd_count, sizeof(*track->extradata_size)); + if (!track->extradata || !track->extradata_size) + return AVERROR(ENOMEM); + } + if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) { if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) { mov->encryption_scheme = MOV_ENC_CENC_AES_CTR; @@ -8240,13 +8273,16 @@ static int mov_write_header(AVFormatContext *s) if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) mov_create_dvd_sub_decoder_specific_info(track, st); else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) { - track->vos_len = st->codecpar->extradata_size; - track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE); - if (!track->vos_data) { + track->extradata_size[track->last_stsd_index] = st->codecpar->extradata_size; + track->extradata[track->last_stsd_index] = + av_malloc(track->extradata_size[track->last_stsd_index] + AV_INPUT_BUFFER_PADDING_SIZE); + if (!track->extradata[track->last_stsd_index]) { return AVERROR(ENOMEM); } - memcpy(track->vos_data, st->codecpar->extradata, track->vos_len); - memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE); + memcpy(track->extradata[track->last_stsd_index], + st->codecpar->extradata, track->extradata_size[track->last_stsd_index]); + memset(track->extradata[track->last_stsd_index] + track->extradata_size[track->last_stsd_index], + 0, AV_INPUT_BUFFER_PADDING_SIZE); } } @@ -8467,22 +8503,6 @@ static int mov_write_trailer(AVFormatContext *s) int i; int64_t moov_pos; - if (mov->need_rewrite_extradata) { - for (i = 0; i < mov->nb_streams; i++) { - MOVTrack *track = &mov->tracks[i]; - AVCodecParameters *par = track->par; - - track->vos_len = par->extradata_size; - av_freep(&track->vos_data); - track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE); - if (!track->vos_data) - return AVERROR(ENOMEM); - memcpy(track->vos_data, par->extradata, track->vos_len); - memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE); - } - mov->need_rewrite_extradata = 0; - } - /* * Before actually writing the trailer, make sure that there are no * dangling subtitles, that need a terminating sample. diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 2b81d38982..4c20571e67 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -90,6 +90,13 @@ typedef struct MOVTrack { uint64_t time; int64_t track_duration; int last_sample_is_subtitle_end; + + /* multiple stsd */ + int stsd_count; + int last_stsd_index; + uint8_t **extradata; + int *extradata_size; + long sample_count; long sample_size; long chunkCount; @@ -111,8 +118,6 @@ typedef struct MOVTrack { int mono_as_fc; int multichannel_as_mono; - int vos_len; - uint8_t *vos_data; MOVIentry *cluster; MOVIentry *cluster_written; unsigned cluster_capacity; @@ -245,8 +250,6 @@ typedef struct MOVMuxContext { uint8_t *encryption_kid; int encryption_kid_len; - int need_rewrite_extradata; - int use_stream_ids_as_track_ids; int track_ids_ok; int write_btrt;