If a packet contains new extradata within a side data entry, save for specific cases it means the coded stream changed. If ignored, upon demuxing every packet from then onwards may be undecodable.
Unified · Split
| @@ -247,7 +247,7 @@ static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track) · 246 unmodified lines | |||
| 247 | /* Sample to chunk atom */ | 247 | /* Sample to chunk atom */ |
| 248 | static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track) | 248 | static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track) |
| 249 | { | 249 | { |
| 250 | int index = 0, oldval = -1, i; | 250 | int index = 0, oldidx = -1, oldval = -1, i; |
| 251 | int64_t entryPos, curpos; | 251 | int64_t entryPos, curpos; |
| 252 | 252 | ||
| 253 | int64_t pos = avio_tell(pb); | 253 | int64_t pos = avio_tell(pb); |
| @@ -257,11 +257,13 @@ static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track) · 3 unmodified lines | |||
| 257 | entryPos = avio_tell(pb); | 257 | entryPos = avio_tell(pb); |
| 258 | avio_wb32(pb, track->chunkCount); // entry count | 258 | avio_wb32(pb, track->chunkCount); // entry count |
| 259 | for (i = 0; i < track->entry; i++) { | 259 | for (i = 0; i < track->entry; i++) { |
| 260 | if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) { | 260 | if ((oldval != track->cluster[i].samples_in_chunk || |
| 261 | oldidx != track->cluster[i].stsd_index) && track->cluster[i].chunkNum) { | ||
| 261 | avio_wb32(pb, track->cluster[i].chunkNum); // first chunk | 262 | avio_wb32(pb, track->cluster[i].chunkNum); // first chunk |
| 262 | avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk | 263 | avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk |
| 263 | avio_wb32(pb, 0x1); // sample description index | 264 | avio_wb32(pb, track->cluster[i].stsd_index + 1); // sample description index |
| 264 | oldval = track->cluster[i].samples_in_chunk; | 265 | oldval = track->cluster[i].samples_in_chunk; |
| 266 | oldidx = track->cluster[i].stsd_index; | ||
| 265 | index++; | 267 | index++; |
| 266 | } | 268 | } |
| 267 | } | 269 | } |
| @@ -3053,8 +3055,12 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext · 2785 unmodified lines | |||
| 3053 | avio_wb32(pb, 0); /* size */ | 3055 | avio_wb32(pb, 0); /* size */ |
| 3054 | ffio_wfourcc(pb, "stsd"); | 3056 | ffio_wfourcc(pb, "stsd"); |
| 3055 | avio_wb32(pb, 0); /* version & flags */ | 3057 | avio_wb32(pb, 0); /* version & flags */ |
| 3056 | avio_wb32(pb, 1); /* entry count */ | 3058 | avio_wb32(pb, track->stsd_count); |
| 3057 | 3059 | ||
| 3060 | int stsd_index_back = track->last_stsd_index; | ||
| 3061 | for (track->last_stsd_index = 0; | ||
| 3062 | track->last_stsd_index < track->stsd_count; | ||
| 3063 | track->last_stsd_index++) { | ||
| 3058 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) | 3064 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) |
| 3059 | ret = mov_write_video_tag(s, pb, mov, track); | 3065 | ret = mov_write_video_tag(s, pb, mov, track); |
| 3060 | else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) | 3066 | else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) |
| @@ -3070,6 +3076,9 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext · 9 unmodified lines | |||
| 3070 | 3076 | ||
| 3071 | if (ret < 0) | 3077 | if (ret < 0) |
| 3072 | return ret; | 3078 | return ret; |
| 3079 | } | ||
| 3080 | |||
| 3081 | track->last_stsd_index = stsd_index_back; | ||
| 3073 | 3082 | ||
| 3074 | return update_size(pb, pos); | 3083 | return update_size(pb, pos); |
| 3075 | } | 3084 | } |
| @@ -5040,6 +5049,7 @@ static void build_chunks(MOVTrack *trk) · 1964 unmodified lines | |||
| 5040 | trk->chunkCount = 1; | 5049 | trk->chunkCount = 1; |
| 5041 | for (i = 1; i<trk->entry; i++){ | 5050 | for (i = 1; i<trk->entry; i++){ |
| 5042 | if (chunk->pos + chunkSize == trk->cluster[i].pos && | 5051 | if (chunk->pos + chunkSize == trk->cluster[i].pos && |
| 5052 | chunk->stsd_index == trk->cluster[i].stsd_index && | ||
| 5043 | chunkSize + trk->cluster[i].size < (1<<20)){ | 5053 | chunkSize + trk->cluster[i].size < (1<<20)){ |
| 5044 | chunkSize += trk->cluster[i].size; | 5054 | chunkSize += trk->cluster[i].size; |
| 5045 | chunk->samples_in_chunk += trk->cluster[i].entries; | 5055 | chunk->samples_in_chunk += trk->cluster[i].entries; |
| @@ -6761,6 +6771,39 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) · 1715 unmodified lines | |||
| 6761 | memset(trk->extradata[0] + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); | 6771 | memset(trk->extradata[0] + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
| 6762 | } | 6772 | } |
| 6763 | 6773 | ||
| 6774 | const AVPacketSideData *sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_NEW_EXTRADATA); | ||
| 6775 | if (pkt->size && sd && sd->size > 0) { | ||
| 6776 | int i; | ||
| 6777 | for (i = 0; i < trk->stsd_count; i++) { | ||
| 6778 | if (trk->extradata_size[i] == sd->size && !memcmp(trk->extradata[i], sd->data, sd->size)) | ||
| 6779 | break; | ||
| 6780 | } | ||
| 6781 | |||
| 6782 | if (i < trk->stsd_count) | ||
| 6783 | trk->last_stsd_index = i; | ||
| 6784 | else if (trk->stsd_count <= INT_MAX - 1) { | ||
| 6785 | int new_count = trk->stsd_count + 1; | ||
| 6786 | uint8_t **extradata = av_realloc_array(trk->extradata, new_count, sizeof(*trk->extradata)); | ||
| 6787 | if (!extradata) | ||
| 6788 | return AVERROR(ENOMEM); | ||
| 6789 | trk->extradata = extradata; | ||
| 6790 | |||
| 6791 | int *extradata_size = av_realloc_array(trk->extradata_size, new_count, sizeof(*trk->extradata_size)); | ||
| 6792 | if (!extradata_size) | ||
| 6793 | return AVERROR(ENOMEM); | ||
| 6794 | trk->extradata_size = extradata_size; | ||
| 6795 | |||
| 6796 | trk->extradata[trk->stsd_count] = av_memdup(sd->data, sd->size); | ||
| 6797 | if (!trk->extradata[trk->stsd_count]) | ||
| 6798 | return AVERROR(ENOMEM); | ||
| 6799 | |||
| 6800 | trk->extradata_size[trk->stsd_count] = sd->size; | ||
| 6801 | trk->last_stsd_index = trk->stsd_count; | ||
| 6802 | trk->stsd_count = new_count; | ||
| 6803 | } else | ||
| 6804 | return AVERROR(ENOMEM); | ||
| 6805 | } | ||
| 6806 | |||
| 6764 | if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && | 6807 | if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && |
| 6765 | (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { | 6808 | (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { |
| 6766 | if (!trk->st->nb_frames) { | 6809 | if (!trk->st->nb_frames) { |
| @@ -6912,6 +6955,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) · 145 unmodified lines | |||
| 6912 | } | 6955 | } |
| 6913 | 6956 | ||
| 6914 | trk->cluster[trk->entry].pos = avio_tell(pb) - size; | 6957 | trk->cluster[trk->entry].pos = avio_tell(pb) - size; |
| 6958 | trk->cluster[trk->entry].stsd_index = trk->last_stsd_index; | ||
| 6915 | trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk; | 6959 | trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk; |
| 6916 | trk->cluster[trk->entry].chunkNum = 0; | 6960 | trk->cluster[trk->entry].chunkNum = 0; |
| 6917 | trk->cluster[trk->entry].size = size; | 6961 | trk->cluster[trk->entry].size = size; |
| @@ -7594,6 +7638,7 @@ static void mov_free(AVFormatContext *s) · 676 unmodified lines | |||
| 7594 | for (int j = 0; j < track->stsd_count; j++) | 7638 | for (int j = 0; j < track->stsd_count; j++) |
| 7595 | av_freep(&track->extradata[j]); | 7639 | av_freep(&track->extradata[j]); |
| 7596 | av_freep(&track->extradata); | 7640 | av_freep(&track->extradata); |
| 7641 | av_freep(&track->extradata_size); | ||
| 7597 | 7642 | ||
| 7598 | ff_mov_cenc_free(&track->cenc); | 7643 | ff_mov_cenc_free(&track->cenc); |
| 7599 | ffio_free_dyn_buf(&track->mdat_buf); | 7644 | ffio_free_dyn_buf(&track->mdat_buf); |
| @@ -50,6 +50,7 @@ typedef struct MOVIentry { · 49 unmodified lines | |||
| 50 | int64_t dts; | 50 | int64_t dts; |
| 51 | int64_t pts; | 51 | int64_t pts; |
| 52 | unsigned int size; | 52 | unsigned int size; |
| 53 | unsigned int stsd_index; | ||
| 53 | unsigned int samples_in_chunk; | 54 | unsigned int samples_in_chunk; |
| 54 | unsigned int chunkNum; ///< Chunk number if the current entry is a chunk start otherwise 0 | 55 | unsigned int chunkNum; ///< Chunk number if the current entry is a chunk start otherwise 0 |
| 55 | unsigned int entries; | 56 | unsigned int entries; |