mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-29 22:00:58 +02:00
avformat/matroskaenc: Avoid swapping codecpar->extradata temporarily
Instead pass extradata and extradata_size explicitly. (It is not perfect, as ff_put_(wav|bmp)_header() still uses the extradata embedded in codecpar, but this is not an issue as long as their CodecPrivate isn't updated.) Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
parent
1056f9a21e
commit
3a00a1a800
@ -990,7 +990,8 @@ static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp,
|
||||
}
|
||||
|
||||
static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb,
|
||||
const AVCodecParameters *par)
|
||||
const AVCodecParameters *par,
|
||||
const uint8_t *extradata, int extradata_size)
|
||||
{
|
||||
const uint8_t *header_start[3];
|
||||
int header_len[3];
|
||||
@ -1002,7 +1003,7 @@ static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb,
|
||||
else
|
||||
first_header_size = 42;
|
||||
|
||||
err = avpriv_split_xiph_headers(par->extradata, par->extradata_size,
|
||||
err = avpriv_split_xiph_headers(extradata, extradata_size,
|
||||
first_header_size, header_start, header_len);
|
||||
if (err < 0) {
|
||||
av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
|
||||
@ -1020,22 +1021,23 @@ static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb,
|
||||
}
|
||||
|
||||
#if CONFIG_MATROSKA_MUXER
|
||||
static int put_wv_codecpriv(AVIOContext *pb, const AVCodecParameters *par)
|
||||
static int put_wv_codecpriv(AVIOContext *pb, const uint8_t *extradata, int extradata_size)
|
||||
{
|
||||
if (par->extradata && par->extradata_size == 2)
|
||||
avio_write(pb, par->extradata, 2);
|
||||
if (extradata && extradata_size == 2)
|
||||
avio_write(pb, extradata, 2);
|
||||
else
|
||||
avio_wl16(pb, 0x410); // fallback to the most recent version
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb,
|
||||
const AVCodecParameters *par)
|
||||
const AVCodecParameters *par,
|
||||
const uint8_t *extradata, int extradata_size)
|
||||
{
|
||||
int write_comment = (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE &&
|
||||
!(par->ch_layout.u.mask & ~0x3ffffULL) &&
|
||||
!ff_flac_is_native_layout(par->ch_layout.u.mask));
|
||||
int ret = ff_flac_write_header(pb, par->extradata, par->extradata_size,
|
||||
int ret = ff_flac_write_header(pb, extradata, extradata_size,
|
||||
!write_comment);
|
||||
|
||||
if (ret < 0)
|
||||
@ -1101,43 +1103,45 @@ static int get_aac_sample_rates(AVFormatContext *s, MatroskaMuxContext *mkv,
|
||||
|
||||
static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp,
|
||||
const AVCodecParameters *par,
|
||||
const uint8_t *extradata,
|
||||
int extradata_size,
|
||||
unsigned *size_to_reserve)
|
||||
{
|
||||
switch (par->codec_id) {
|
||||
case AV_CODEC_ID_VORBIS:
|
||||
case AV_CODEC_ID_THEORA:
|
||||
return put_xiph_codecpriv(s, dyn_cp, par);
|
||||
return put_xiph_codecpriv(s, dyn_cp, par, extradata, extradata_size);
|
||||
case AV_CODEC_ID_AV1:
|
||||
if (par->extradata_size)
|
||||
return ff_isom_write_av1c(dyn_cp, par->extradata,
|
||||
par->extradata_size, 1);
|
||||
if (extradata_size)
|
||||
return ff_isom_write_av1c(dyn_cp, extradata,
|
||||
extradata_size, 1);
|
||||
else
|
||||
*size_to_reserve = 4 + 3;
|
||||
break;
|
||||
#if CONFIG_MATROSKA_MUXER
|
||||
case AV_CODEC_ID_FLAC:
|
||||
return put_flac_codecpriv(s, dyn_cp, par);
|
||||
return put_flac_codecpriv(s, dyn_cp, par, extradata, extradata_size);
|
||||
case AV_CODEC_ID_WAVPACK:
|
||||
return put_wv_codecpriv(dyn_cp, par);
|
||||
return put_wv_codecpriv(dyn_cp, extradata, extradata_size);
|
||||
case AV_CODEC_ID_H264:
|
||||
return ff_isom_write_avcc(dyn_cp, par->extradata,
|
||||
par->extradata_size);
|
||||
return ff_isom_write_avcc(dyn_cp, extradata,
|
||||
extradata_size);
|
||||
case AV_CODEC_ID_HEVC:
|
||||
return ff_isom_write_hvcc(dyn_cp, par->extradata,
|
||||
par->extradata_size, 0);
|
||||
return ff_isom_write_hvcc(dyn_cp, extradata,
|
||||
extradata_size, 0);
|
||||
case AV_CODEC_ID_ALAC:
|
||||
if (par->extradata_size < 36) {
|
||||
if (extradata_size < 36) {
|
||||
av_log(s, AV_LOG_ERROR,
|
||||
"Invalid extradata found, ALAC expects a 36-byte "
|
||||
"QuickTime atom.");
|
||||
return AVERROR_INVALIDDATA;
|
||||
} else
|
||||
avio_write(dyn_cp, par->extradata + 12,
|
||||
par->extradata_size - 12);
|
||||
avio_write(dyn_cp, extradata + 12,
|
||||
extradata_size - 12);
|
||||
break;
|
||||
case AV_CODEC_ID_AAC:
|
||||
if (par->extradata_size)
|
||||
avio_write(dyn_cp, par->extradata, par->extradata_size);
|
||||
if (extradata_size)
|
||||
avio_write(dyn_cp, extradata, extradata_size);
|
||||
else
|
||||
*size_to_reserve = 4 + MAX_PCE_SIZE + 2;
|
||||
break;
|
||||
@ -1146,8 +1150,8 @@ static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn
|
||||
if (CONFIG_MATROSKA_MUXER && par->codec_id == AV_CODEC_ID_PRORES &&
|
||||
ff_codec_get_id(ff_codec_movvideo_tags, par->codec_tag) == AV_CODEC_ID_PRORES) {
|
||||
avio_wl32(dyn_cp, par->codec_tag);
|
||||
} else if (par->extradata_size && par->codec_id != AV_CODEC_ID_TTA)
|
||||
avio_write(dyn_cp, par->extradata, par->extradata_size);
|
||||
} else if (extradata_size && par->codec_id != AV_CODEC_ID_TTA)
|
||||
avio_write(dyn_cp, extradata, extradata_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1155,6 +1159,7 @@ static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn
|
||||
|
||||
static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp,
|
||||
AVCodecParameters *par,
|
||||
const uint8_t *extradata, int extradata_size,
|
||||
int native_id, int qt_id,
|
||||
uint8_t **codecpriv, int *codecpriv_size,
|
||||
unsigned *size_to_reserve)
|
||||
@ -1165,7 +1170,9 @@ static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp,
|
||||
*size_to_reserve = 0;
|
||||
|
||||
if (native_id) {
|
||||
ret = mkv_assemble_native_codecprivate(s, dyn_cp, par, size_to_reserve);
|
||||
ret = mkv_assemble_native_codecprivate(s, dyn_cp, par,
|
||||
extradata, extradata_size,
|
||||
size_to_reserve);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#if CONFIG_MATROSKA_MUXER
|
||||
@ -1175,13 +1182,13 @@ static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp,
|
||||
par->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags,
|
||||
par->codec_id);
|
||||
if ( ff_codec_get_id(ff_codec_movvideo_tags, par->codec_tag) == par->codec_id
|
||||
&& (!par->extradata_size || ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(par->extradata + 4)) != par->codec_id)
|
||||
&& (!extradata_size || ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(extradata + 4)) != par->codec_id)
|
||||
) {
|
||||
avio_wb32(dyn_cp, 0x5a + par->extradata_size);
|
||||
avio_wb32(dyn_cp, 0x5a + extradata_size);
|
||||
avio_wl32(dyn_cp, par->codec_tag);
|
||||
ffio_fill(dyn_cp, 0, 0x5a - 8);
|
||||
}
|
||||
avio_write(dyn_cp, par->extradata, par->extradata_size);
|
||||
avio_write(dyn_cp, extradata, extradata_size);
|
||||
} else {
|
||||
if (!ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id))
|
||||
av_log(s, AV_LOG_WARNING, "codec %s is not supported by this format\n",
|
||||
@ -1196,6 +1203,8 @@ static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp,
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
/* If vfw extradata updates are supported, this will have
|
||||
* to be updated to pass extradata(_size) explicitly. */
|
||||
ff_put_bmp_header(dyn_cp, par, 0, 0, mkv->flipped_raw_rgb);
|
||||
}
|
||||
} else if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
@ -1209,6 +1218,7 @@ static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp,
|
||||
if (!par->codec_tag)
|
||||
par->codec_tag = tag;
|
||||
|
||||
/* Same comment as for ff_put_bmp_header applies here. */
|
||||
ff_put_wav_header(s, dyn_cp, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
|
||||
#endif
|
||||
}
|
||||
@ -1221,6 +1231,7 @@ static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp,
|
||||
|
||||
static int mkv_write_codecprivate(AVFormatContext *s, MatroskaMuxContext *mkv,
|
||||
AVCodecParameters *par,
|
||||
const uint8_t *extradata, int extradata_size,
|
||||
int native_id, int qt_id, AVIOContext *pb)
|
||||
{
|
||||
AVIOContext *const dyn_bc = mkv->tmp_bc;
|
||||
@ -1228,7 +1239,8 @@ static int mkv_write_codecprivate(AVFormatContext *s, MatroskaMuxContext *mkv,
|
||||
unsigned size_to_reserve;
|
||||
int ret, codecpriv_size;
|
||||
|
||||
ret = mkv_assemble_codecprivate(s, dyn_bc, par, native_id, qt_id,
|
||||
ret = mkv_assemble_codecprivate(s, dyn_bc, par, extradata, extradata_size,
|
||||
native_id, qt_id,
|
||||
&codecpriv, &codecpriv_size, &size_to_reserve);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
@ -1851,7 +1863,8 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
|
||||
|
||||
if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) {
|
||||
track->codecpriv_offset = avio_tell(pb);
|
||||
ret = mkv_write_codecprivate(s, mkv, par, native_id, qt_id, pb);
|
||||
ret = mkv_write_codecprivate(s, mkv, par, par->extradata, par->extradata_size,
|
||||
native_id, qt_id, pb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@ -2644,7 +2657,8 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt)
|
||||
return ret;
|
||||
memcpy(par->extradata, side_data, side_data_size);
|
||||
avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET);
|
||||
mkv_write_codecprivate(s, mkv, par, 1, 0, mkv->track.bc);
|
||||
mkv_write_codecprivate(s, mkv, par, side_data, side_data_size,
|
||||
1, 0, mkv->track.bc);
|
||||
filler = MAX_PCE_SIZE + 2 + 4 - (avio_tell(mkv->track.bc) - track->codecpriv_offset);
|
||||
if (filler)
|
||||
put_ebml_void(mkv->track.bc, filler);
|
||||
@ -2659,16 +2673,14 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt)
|
||||
break;
|
||||
case AV_CODEC_ID_FLAC:
|
||||
if (side_data_size && mkv->track.bc) {
|
||||
uint8_t *old_extradata = par->extradata;
|
||||
if (side_data_size != par->extradata_size) {
|
||||
av_log(s, AV_LOG_ERROR, "Invalid FLAC STREAMINFO metadata for output stream %d\n",
|
||||
pkt->stream_index);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
par->extradata = side_data;
|
||||
avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET);
|
||||
mkv_write_codecprivate(s, mkv, par, 1, 0, mkv->track.bc);
|
||||
par->extradata = old_extradata;
|
||||
mkv_write_codecprivate(s, mkv, par, side_data, side_data_size,
|
||||
1, 0, mkv->track.bc);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user