diff options
Diffstat (limited to 'common/av_common.c')
-rw-r--r-- | common/av_common.c | 80 |
1 files changed, 58 insertions, 22 deletions
diff --git a/common/av_common.c b/common/av_common.c index 2eae8c4e3e..277601d2fc 100644 --- a/common/av_common.c +++ b/common/av_common.c @@ -30,6 +30,7 @@ #include "config.h" +#include "audio/chmap_avchannel.h" #include "common/common.h" #include "common/msg.h" #include "demux/packet.h" @@ -39,20 +40,6 @@ #include "av_common.h" #include "codecs.h" -int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size) -{ - if (size) { - av_free(avctx->extradata); - avctx->extradata_size = 0; - avctx->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) - return -1; - avctx->extradata_size = size; - memcpy(avctx->extradata, ptr, size); - } - return 0; -} - enum AVMediaType mp_to_av_stream_type(int type) { switch (type) { @@ -63,7 +50,7 @@ enum AVMediaType mp_to_av_stream_type(int type) } } -AVCodecParameters *mp_codec_params_to_av(struct mp_codec_params *c) +AVCodecParameters *mp_codec_params_to_av(const struct mp_codec_params *c) { AVCodecParameters *avp = avcodec_parameters_alloc(); if (!avp) @@ -80,12 +67,23 @@ AVCodecParameters *mp_codec_params_to_av(struct mp_codec_params *c) avp->codec_id = mp_codec_to_av_codec_id(c->codec); avp->codec_tag = c->codec_tag; if (c->extradata_size) { - avp->extradata = - av_mallocz(c->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + uint8_t *extradata = c->extradata; + int size = c->extradata_size; + + if (avp->codec_id == AV_CODEC_ID_FLAC) { + // ffmpeg expects FLAC extradata to be just the STREAMINFO, + // so grab only that (and assume it'll be the first block) + if (size >= 8 && !memcmp(c->extradata, "fLaC", 4)) { + extradata += 8; + size = MPMIN(34, size - 8); // FLAC_STREAMINFO_SIZE + } + } + + avp->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avp->extradata) goto error; - avp->extradata_size = c->extradata_size; - memcpy(avp->extradata, c->extradata, avp->extradata_size); + avp->extradata_size = size; + memcpy(avp->extradata, extradata, size); } avp->bits_per_coded_sample = c->bits_per_coded_sample; @@ -97,9 +95,14 @@ AVCodecParameters *mp_codec_params_to_av(struct mp_codec_params *c) avp->sample_rate = c->samplerate; avp->bit_rate = c->bitrate; avp->block_align = c->block_align; + +#if !HAVE_AV_CHANNEL_LAYOUT avp->channels = c->channels.num; if (!mp_chmap_is_unknown(&c->channels)) avp->channel_layout = mp_chmap_to_lavc(&c->channels); +#else + mp_chmap_to_av_layout(&avp->ch_layout, &c->channels); +#endif return avp; error: @@ -108,7 +111,7 @@ error: } // Set avctx codec headers for decoding. Returns <0 on failure. -int mp_set_avctx_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c) +int mp_set_avctx_codec_headers(AVCodecContext *avctx, const struct mp_codec_params *c) { enum AVMediaType codec_type = avctx->codec_type; enum AVCodecID codec_id = avctx->codec_id; @@ -128,7 +131,7 @@ int mp_set_avctx_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c) // Pick a "good" timebase, which will be used to convert double timestamps // back to fractions for passing them through libavcodec. -AVRational mp_get_codec_timebase(struct mp_codec_params *c) +AVRational mp_get_codec_timebase(const struct mp_codec_params *c) { AVRational tb = {c->native_tb_num, c->native_tb_den}; if (tb.num < 1 || tb.den < 1) { @@ -179,7 +182,11 @@ double mp_pts_from_av(int64_t av_pts, AVRational *tb) // Set duration field only if tb is set. void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb) { - av_init_packet(dst); + dst->side_data = NULL; + dst->side_data_elems = 0; + dst->buf = NULL; + av_packet_unref(dst); + dst->data = mpkt ? mpkt->buffer : NULL; dst->size = mpkt ? mpkt->len : 0; /* Some codecs (ZeroCodec, some cases of PNG) may want keyframe info @@ -377,3 +384,32 @@ int mp_set_avopts_pos(struct mp_log *log, void *avobj, void *posargs, char **kv) } return success; } + +/** + * Must be used to free an AVPacket that was used with mp_set_av_packet(). + * + * We have a particular pattern where we "borrow" buffers and set them + * into an AVPacket to pass data to ffmpeg without extra copies. + * This applies to buf and side_data, so this function clears them before + * freeing. + */ +void mp_free_av_packet(AVPacket **pkt) +{ + if (*pkt) { + (*pkt)->side_data = NULL; + (*pkt)->side_data_elems = 0; + (*pkt)->buf = NULL; + } + av_packet_free(pkt); +} + +void mp_codec_info_from_av(const AVCodecContext *avctx, struct mp_codec_params *c) +{ + c->codec_profile = av_get_profile_name(avctx->codec, avctx->profile); + if (!c->codec_profile) + c->codec_profile = avcodec_profile_name(avctx->codec_id, avctx->profile); + c->codec = avctx->codec_descriptor->name; + c->codec_desc = avctx->codec_descriptor->long_name; + c->decoder = avctx->codec->name; + c->decoder_desc = avctx->codec->long_name; +} |