mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
lavf/ffm: use AVOption API to store/restore stream properties
This is a generic solution that will not reqiore modifications when new options are added. This also fixes problem with current implementation when qmin or qmax=-1. Only 8 bits was sent and read back as 255. Fixes #1275 Fixes #1461 Signed-off-by: Lukasz Marek <lukasz.m.luki2@gmail.com>
This commit is contained in:
parent
a38e06c1aa
commit
745730c9c2
@ -240,6 +240,7 @@ static int ffm2_read_header(AVFormatContext *s)
|
||||
int ret;
|
||||
int f_main = 0, f_cprv, f_stvi, f_stau;
|
||||
AVCodec *enc;
|
||||
char *buffer;
|
||||
|
||||
ffm->packet_size = avio_rb32(pb);
|
||||
if (ffm->packet_size != FFM_PACKET_SIZE) {
|
||||
@ -375,6 +376,34 @@ static int ffm2_read_header(AVFormatContext *s)
|
||||
avio_get_str(pb, size, st->recommended_encoder_configuration, size + 1);
|
||||
}
|
||||
break;
|
||||
case MKBETAG('S', '2', 'V', 'I'):
|
||||
if (f_stvi++) {
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
buffer = av_malloc(size);
|
||||
if (!buffer) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
avio_get_str(pb, INT_MAX, buffer, size);
|
||||
av_set_options_string(codec, buffer, "=", ",");
|
||||
av_freep(&buffer);
|
||||
break;
|
||||
case MKBETAG('S', '2', 'A', 'U'):
|
||||
if (f_stau++) {
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
buffer = av_malloc(size);
|
||||
if (!buffer) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
avio_get_str(pb, INT_MAX, buffer, size);
|
||||
av_set_options_string(codec, buffer, "=", ",");
|
||||
av_freep(&buffer);
|
||||
break;
|
||||
}
|
||||
avio_seek(pb, next, SEEK_SET);
|
||||
}
|
||||
|
@ -120,6 +120,48 @@ static int ffm_write_header_codec_private_ctx(AVIOContext *pb, AVCodecContext *c
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecContext *ctx, unsigned tag, int type)
|
||||
{
|
||||
AVIOContext *tmp;
|
||||
char *buf = NULL;
|
||||
uint8_t *p = NULL;
|
||||
int ret, need_coma = 0;
|
||||
|
||||
#define SKIP_DEFAULTS AV_OPT_SERIALIZE_SKIP_DEFAULTS
|
||||
#define OPT_FLAGS_EXACT AV_OPT_SERIALIZE_OPT_FLAGS_EXACT
|
||||
#define ENC AV_OPT_FLAG_ENCODING_PARAM
|
||||
|
||||
if (avio_open_dyn_buf(&tmp) < 0)
|
||||
return AVERROR(ENOMEM);
|
||||
if ((ret = av_opt_serialize(ctx, ENC | type, SKIP_DEFAULTS, &buf, '=', ',')) < 0)
|
||||
goto fail;
|
||||
if (buf && strlen(buf)) {
|
||||
avio_write(tmp, buf, strlen(buf));
|
||||
av_free(buf);
|
||||
need_coma = 1;
|
||||
}
|
||||
if ((ret = av_opt_serialize(ctx, 0, SKIP_DEFAULTS | OPT_FLAGS_EXACT, &buf, '=', ',')) < 0)
|
||||
goto fail;
|
||||
if (buf && strlen(buf)) {
|
||||
if (need_coma)
|
||||
avio_w8(tmp, ',');
|
||||
avio_write(tmp, buf, strlen(buf));
|
||||
av_free(buf);
|
||||
}
|
||||
avio_w8(tmp, 0);
|
||||
write_header_chunk(pb, tmp, tag);
|
||||
return 0;
|
||||
fail:
|
||||
av_free(buf);
|
||||
avio_close_dyn_buf(tmp, &p);
|
||||
av_free(p);
|
||||
return ret;
|
||||
|
||||
#undef SKIP_DEFAULTS
|
||||
#undef OPT_FLAGS_EXACT
|
||||
#undef ENC
|
||||
}
|
||||
|
||||
static int ffm_write_header(AVFormatContext *s)
|
||||
{
|
||||
FFMContext *ffm = s->priv_data;
|
||||
@ -180,59 +222,13 @@ static int ffm_write_header(AVFormatContext *s)
|
||||
/* specific info */
|
||||
switch(codec->codec_type) {
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
avio_wb32(pb, codec->time_base.num);
|
||||
avio_wb32(pb, codec->time_base.den);
|
||||
avio_wb16(pb, codec->width);
|
||||
avio_wb16(pb, codec->height);
|
||||
avio_wb16(pb, codec->gop_size);
|
||||
avio_wb32(pb, codec->pix_fmt);
|
||||
avio_w8(pb, codec->qmin);
|
||||
avio_w8(pb, codec->qmax);
|
||||
avio_w8(pb, codec->max_qdiff);
|
||||
avio_wb16(pb, (int) (codec->qcompress * 10000.0));
|
||||
avio_wb16(pb, (int) (codec->qblur * 10000.0));
|
||||
avio_wb32(pb, codec->bit_rate_tolerance);
|
||||
avio_put_str(pb, codec->rc_eq ? codec->rc_eq : "tex^qComp");
|
||||
avio_wb32(pb, codec->rc_max_rate);
|
||||
avio_wb32(pb, codec->rc_min_rate);
|
||||
avio_wb32(pb, codec->rc_buffer_size);
|
||||
avio_wb64(pb, av_double2int(codec->i_quant_factor));
|
||||
avio_wb64(pb, av_double2int(codec->b_quant_factor));
|
||||
avio_wb64(pb, av_double2int(codec->i_quant_offset));
|
||||
avio_wb64(pb, av_double2int(codec->b_quant_offset));
|
||||
avio_wb32(pb, codec->dct_algo);
|
||||
avio_wb32(pb, codec->strict_std_compliance);
|
||||
avio_wb32(pb, codec->max_b_frames);
|
||||
avio_wb32(pb, codec->mpeg_quant);
|
||||
avio_wb32(pb, codec->intra_dc_precision);
|
||||
avio_wb32(pb, codec->me_method);
|
||||
avio_wb32(pb, codec->mb_decision);
|
||||
avio_wb32(pb, codec->nsse_weight);
|
||||
avio_wb32(pb, codec->frame_skip_cmp);
|
||||
avio_wb64(pb, av_double2int(codec->rc_buffer_aggressivity));
|
||||
avio_wb32(pb, codec->codec_tag);
|
||||
avio_w8(pb, codec->thread_count);
|
||||
avio_wb32(pb, codec->coder_type);
|
||||
avio_wb32(pb, codec->me_cmp);
|
||||
avio_wb32(pb, codec->me_subpel_quality);
|
||||
avio_wb32(pb, codec->me_range);
|
||||
avio_wb32(pb, codec->keyint_min);
|
||||
avio_wb32(pb, codec->scenechange_threshold);
|
||||
avio_wb32(pb, codec->b_frame_strategy);
|
||||
avio_wb64(pb, av_double2int(codec->qcompress));
|
||||
avio_wb64(pb, av_double2int(codec->qblur));
|
||||
avio_wb32(pb, codec->max_qdiff);
|
||||
avio_wb32(pb, codec->refs);
|
||||
write_header_chunk(s->pb, pb, MKBETAG('S', 'T', 'V', 'I'));
|
||||
if ((ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_VIDEO_PARAM)) < 0)
|
||||
if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'V', 'I'), AV_OPT_FLAG_VIDEO_PARAM)) < 0 ||
|
||||
(ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_VIDEO_PARAM)) < 0)
|
||||
return ret;
|
||||
break;
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
avio_wb32(pb, codec->sample_rate);
|
||||
avio_wl16(pb, codec->channels);
|
||||
avio_wl16(pb, codec->frame_size);
|
||||
write_header_chunk(s->pb, pb, MKBETAG('S', 'T', 'A', 'U'));
|
||||
if ((ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_AUDIO_PARAM)) < 0)
|
||||
if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'A', 'U'), AV_OPT_FLAG_AUDIO_PARAM)) < 0 ||
|
||||
(ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_AUDIO_PARAM)) < 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
|
@ -1,3 +1,3 @@
|
||||
16cc0ee04b036c210b2fc85182d748e1 *./tests/data/lavf/lavf.ffm
|
||||
d5d4e5e3eec336ae6680dde035870564 *./tests/data/lavf/lavf.ffm
|
||||
376832 ./tests/data/lavf/lavf.ffm
|
||||
./tests/data/lavf/lavf.ffm CRC=0x000e23ae
|
||||
|
Loading…
x
Reference in New Issue
Block a user