Don't blindly copy all bytes in extradata past ChannelMappingFamily. Instead check if ChannelMappingFamily is not 0 and then only write the correct amount of bytes from ChannelMappingTable, as defined in the spec[1]. Fixes part of ticket #9190. [1] https://opus-codec.org/docs/opus_in_isobmff.html#4.3.2
Unified · Split
| @@ -797,6 +797,7 @@ static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track) · 796 unmodified lines | |||
| 797 | static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) | 797 | static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) |
| 798 | { | 798 | { |
| 799 | int64_t pos = avio_tell(pb); | 799 | int64_t pos = avio_tell(pb); |
| 800 | int channels, channel_map; | ||
| 800 | avio_wb32(pb, 0); | 801 | avio_wb32(pb, 0); |
| 801 | ffio_wfourcc(pb, "dOps"); | 802 | ffio_wfourcc(pb, "dOps"); |
| 802 | avio_w8(pb, 0); /* Version */ | 803 | avio_w8(pb, 0); /* Version */ |
| @@ -807,12 +808,22 @@ static int mov_write_dops_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra · 4 unmodified lines | |||
| 807 | /* extradata contains an Ogg OpusHead, other than byte-ordering and | 808 | /* extradata contains an Ogg OpusHead, other than byte-ordering and |
| 808 | OpusHead's preceeding magic/version, OpusSpecificBox is currently | 809 | OpusHead's preceeding magic/version, OpusSpecificBox is currently |
| 809 | identical. */ | 810 | identical. */ |
| 810 | avio_w8(pb, AV_RB8(track->par->extradata + 9)); /* OuputChannelCount */ | 811 | channels = AV_RB8(track->par->extradata + 9); |
| 812 | channel_map = AV_RB8(track->par->extradata + 18); | ||
| 813 | |||
| 814 | avio_w8(pb, channels); /* OuputChannelCount */ | ||
| 811 | avio_wb16(pb, AV_RL16(track->par->extradata + 10)); /* PreSkip */ | 815 | avio_wb16(pb, AV_RL16(track->par->extradata + 10)); /* PreSkip */ |
| 812 | avio_wb32(pb, AV_RL32(track->par->extradata + 12)); /* InputSampleRate */ | 816 | avio_wb32(pb, AV_RL32(track->par->extradata + 12)); /* InputSampleRate */ |
| 813 | avio_wb16(pb, AV_RL16(track->par->extradata + 16)); /* OutputGain */ | 817 | avio_wb16(pb, AV_RL16(track->par->extradata + 16)); /* OutputGain */ |
| 818 | avio_w8(pb, channel_map); /* ChannelMappingFamily */ | ||
| 814 | /* Write the rest of the header out without byte-swapping. */ | 819 | /* Write the rest of the header out without byte-swapping. */ |
| 815 | avio_write(pb, track->par->extradata + 18, track->par->extradata_size - 18); | 820 | if (channel_map) { |
| 821 | if (track->par->extradata_size < 21 + channels) { | ||
| 822 | av_log(s, AV_LOG_ERROR, "invalid extradata size\n"); | ||
| 823 | return AVERROR_INVALIDDATA; | ||
| 824 | } | ||
| 825 | avio_write(pb, track->par->extradata + 19, 2 + channels); /* ChannelMappingTable */ | ||
| 826 | } | ||
| 816 | 827 | ||
| 817 | return update_size(pb, pos); | 828 | return update_size(pb, pos); |
| 818 | } | 829 | } |