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.
Showing the changes to libavformat (2 of 2 files). Show all
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; |