X-Git-Url: https://git.piment-noir.org/?p=deb_ffmpeg.git;a=blobdiff_plain;f=ffmpeg%2Flibavformat%2Fffmdec.c;h=987f419c96ba8bd593d9c6b5e57a4fbeb3b5852b;hp=448762b02628c982d708fa89b035558dcf520ec7;hb=f6fa7814ccfe3e76514b36cf04f5cd3cb657c8cf;hpb=2ba45a602cbfa7b771effba9b11bb4245c21bc00 diff --git a/ffmpeg/libavformat/ffmdec.c b/ffmpeg/libavformat/ffmdec.c index 448762b..987f419 100644 --- a/ffmpeg/libavformat/ffmdec.c +++ b/ffmpeg/libavformat/ffmdec.c @@ -23,6 +23,9 @@ #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" +#include "libavutil/opt.h" +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" #include "avformat.h" #include "internal.h" #include "ffm.h" @@ -230,6 +233,27 @@ static int ffm_close(AVFormatContext *s) return 0; } +static int ffm_append_recommended_configuration(AVStream *st, char **conf) +{ + int ret; + size_t newsize; + av_assert0(conf && st); + if (!*conf) + return 0; + if (!st->recommended_encoder_configuration) { + st->recommended_encoder_configuration = *conf; + *conf = 0; + return 0; + } + newsize = strlen(*conf) + strlen(st->recommended_encoder_configuration) + 2; + if ((ret = av_reallocp(&st->recommended_encoder_configuration, newsize)) < 0) + return ret; + av_strlcat(st->recommended_encoder_configuration, ",", newsize); + av_strlcat(st->recommended_encoder_configuration, *conf, newsize); + av_freep(conf); + return 0; +} + static int ffm2_read_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; @@ -237,6 +261,9 @@ static int ffm2_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; AVCodecContext *codec; 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) { @@ -267,10 +294,15 @@ static int ffm2_read_header(AVFormatContext *s) switch(id) { case MKBETAG('M', 'A', 'I', 'N'): + if (f_main++) { + ret = AVERROR(EINVAL); + goto fail; + } avio_rb32(pb); /* nb_streams */ avio_rb32(pb); /* total bitrate */ break; case MKBETAG('C', 'O', 'M', 'M'): + f_cprv = f_stvi = f_stau = 0; st = avformat_new_stream(s, NULL); if (!st) { ret = AVERROR(ENOMEM); @@ -291,63 +323,111 @@ static int ffm2_read_header(AVFormatContext *s) if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0) return AVERROR(ENOMEM); } - avio_seek(pb, next, SEEK_SET); - id = avio_rb32(pb); - size = avio_rb32(pb); - next = avio_tell(pb) + size; - switch(id) { - case MKBETAG('S', 'T', 'V', 'I'): - codec->time_base.num = avio_rb32(pb); - codec->time_base.den = avio_rb32(pb); - codec->width = avio_rb16(pb); - codec->height = avio_rb16(pb); - codec->gop_size = avio_rb16(pb); - codec->pix_fmt = avio_rb32(pb); - codec->qmin = avio_r8(pb); - codec->qmax = avio_r8(pb); - codec->max_qdiff = avio_r8(pb); - codec->qcompress = avio_rb16(pb) / 10000.0; - codec->qblur = avio_rb16(pb) / 10000.0; - codec->bit_rate_tolerance = avio_rb32(pb); - avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf)); - codec->rc_eq = av_strdup(rc_eq_buf); - codec->rc_max_rate = avio_rb32(pb); - codec->rc_min_rate = avio_rb32(pb); - codec->rc_buffer_size = avio_rb32(pb); - codec->i_quant_factor = av_int2double(avio_rb64(pb)); - codec->b_quant_factor = av_int2double(avio_rb64(pb)); - codec->i_quant_offset = av_int2double(avio_rb64(pb)); - codec->b_quant_offset = av_int2double(avio_rb64(pb)); - codec->dct_algo = avio_rb32(pb); - codec->strict_std_compliance = avio_rb32(pb); - codec->max_b_frames = avio_rb32(pb); - codec->mpeg_quant = avio_rb32(pb); - codec->intra_dc_precision = avio_rb32(pb); - codec->me_method = avio_rb32(pb); - codec->mb_decision = avio_rb32(pb); - codec->nsse_weight = avio_rb32(pb); - codec->frame_skip_cmp = avio_rb32(pb); - codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb)); - codec->codec_tag = avio_rb32(pb); - codec->thread_count = avio_r8(pb); - codec->coder_type = avio_rb32(pb); - codec->me_cmp = avio_rb32(pb); - codec->me_subpel_quality = avio_rb32(pb); - codec->me_range = avio_rb32(pb); - codec->keyint_min = avio_rb32(pb); - codec->scenechange_threshold = avio_rb32(pb); - codec->b_frame_strategy = avio_rb32(pb); - codec->qcompress = av_int2double(avio_rb64(pb)); - codec->qblur = av_int2double(avio_rb64(pb)); - codec->max_qdiff = avio_rb32(pb); - codec->refs = avio_rb32(pb); - break; - case MKBETAG('S', 'T', 'A', 'U'): - codec->sample_rate = avio_rb32(pb); - codec->channels = avio_rl16(pb); - codec->frame_size = avio_rl16(pb); - break; + break; + case MKBETAG('S', 'T', 'V', 'I'): + if (f_stvi++) { + ret = AVERROR(EINVAL); + goto fail; + } + codec->time_base.num = avio_rb32(pb); + codec->time_base.den = avio_rb32(pb); + codec->width = avio_rb16(pb); + codec->height = avio_rb16(pb); + codec->gop_size = avio_rb16(pb); + codec->pix_fmt = avio_rb32(pb); + codec->qmin = avio_r8(pb); + codec->qmax = avio_r8(pb); + codec->max_qdiff = avio_r8(pb); + codec->qcompress = avio_rb16(pb) / 10000.0; + codec->qblur = avio_rb16(pb) / 10000.0; + codec->bit_rate_tolerance = avio_rb32(pb); + avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf)); + codec->rc_eq = av_strdup(rc_eq_buf); + codec->rc_max_rate = avio_rb32(pb); + codec->rc_min_rate = avio_rb32(pb); + codec->rc_buffer_size = avio_rb32(pb); + codec->i_quant_factor = av_int2double(avio_rb64(pb)); + codec->b_quant_factor = av_int2double(avio_rb64(pb)); + codec->i_quant_offset = av_int2double(avio_rb64(pb)); + codec->b_quant_offset = av_int2double(avio_rb64(pb)); + codec->dct_algo = avio_rb32(pb); + codec->strict_std_compliance = avio_rb32(pb); + codec->max_b_frames = avio_rb32(pb); + codec->mpeg_quant = avio_rb32(pb); + codec->intra_dc_precision = avio_rb32(pb); + codec->me_method = avio_rb32(pb); + codec->mb_decision = avio_rb32(pb); + codec->nsse_weight = avio_rb32(pb); + codec->frame_skip_cmp = avio_rb32(pb); + codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb)); + codec->codec_tag = avio_rb32(pb); + codec->thread_count = avio_r8(pb); + codec->coder_type = avio_rb32(pb); + codec->me_cmp = avio_rb32(pb); + codec->me_subpel_quality = avio_rb32(pb); + codec->me_range = avio_rb32(pb); + codec->keyint_min = avio_rb32(pb); + codec->scenechange_threshold = avio_rb32(pb); + codec->b_frame_strategy = avio_rb32(pb); + codec->qcompress = av_int2double(avio_rb64(pb)); + codec->qblur = av_int2double(avio_rb64(pb)); + codec->max_qdiff = avio_rb32(pb); + codec->refs = avio_rb32(pb); + break; + case MKBETAG('S', 'T', 'A', 'U'): + if (f_stau++) { + ret = AVERROR(EINVAL); + goto fail; + } + codec->sample_rate = avio_rb32(pb); + codec->channels = avio_rl16(pb); + codec->frame_size = avio_rl16(pb); + break; + case MKBETAG('C', 'P', 'R', 'V'): + if (f_cprv++) { + ret = AVERROR(EINVAL); + goto fail; + } + enc = avcodec_find_encoder(codec->codec_id); + if (enc && enc->priv_data_size && enc->priv_class) { + buffer = av_malloc(size + 1); + if (!buffer) { + ret = AVERROR(ENOMEM); + goto fail; + } + avio_get_str(pb, size, buffer, size + 1); + if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0) + goto fail; + } + 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, "=", ","); + if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0) + goto fail; + 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, "=", ","); + ffm_append_recommended_configuration(st, &buffer); break; } avio_seek(pb, next, SEEK_SET);