summaryrefslogtreecommitdiffstats
path: root/common/av_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/av_common.c')
-rw-r--r--common/av_common.c128
1 files changed, 81 insertions, 47 deletions
diff --git a/common/av_common.c b/common/av_common.c
index f2f43498e3..5c58f3fea8 100644
--- a/common/av_common.c
+++ b/common/av_common.c
@@ -33,6 +33,7 @@
#include "common/msg.h"
#include "demux/packet.h"
#include "demux/stheader.h"
+#include "video/fmt-conversion.h"
#include "av_common.h"
#include "codecs.h"
@@ -41,7 +42,7 @@ 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 + FF_INPUT_BUFFER_PADDING_SIZE);
+ avctx->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!avctx->extradata)
return -1;
avctx->extradata_size = size;
@@ -50,35 +51,81 @@ int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size)
return 0;
}
-// Copy the codec-related fields from st into avctx. This does not set the
-// codec itself, only codec related header data provided by libavformat.
-// The goal is to initialize a new decoder with the header data provided by
-// libavformat, and unlike avcodec_copy_context(), allow the user to create
-// a clean AVCodecContext for a manually selected AVCodec.
-// This is strictly for decoding only.
-void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st)
+enum AVMediaType mp_to_av_stream_type(int type)
{
- mp_lavc_set_extradata(avctx, st->extradata, st->extradata_size);
- avctx->codec_tag = st->codec_tag;
- avctx->bit_rate = st->bit_rate;
- avctx->width = st->width;
- avctx->height = st->height;
- avctx->pix_fmt = st->pix_fmt;
- avctx->chroma_sample_location = st->chroma_sample_location;
- avctx->sample_rate = st->sample_rate;
- avctx->channels = st->channels;
- avctx->block_align = st->block_align;
- avctx->channel_layout = st->channel_layout;
- avctx->bits_per_coded_sample = st->bits_per_coded_sample;
- avctx->has_b_frames = st->has_b_frames;
+ switch (type) {
+ case STREAM_VIDEO: return AVMEDIA_TYPE_VIDEO;
+ case STREAM_AUDIO: return AVMEDIA_TYPE_AUDIO;
+ case STREAM_SUB: return AVMEDIA_TYPE_SUBTITLE;
+ default: return AVMEDIA_TYPE_UNKNOWN;
+ }
}
-// This only copies ffmpeg-native codec parameters. Parameters produced by
-// other demuxers must be handled manually.
-void mp_set_lav_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c)
+AVCodecParameters *mp_codec_params_to_av(struct mp_codec_params *c)
{
- if (c->lav_codecpar)
- avcodec_parameters_to_context(avctx, c->lav_codecpar);
+ AVCodecParameters *avp = avcodec_parameters_alloc();
+ if (!avp)
+ return NULL;
+
+ // If we have lavf demuxer params, they overwrite by definition any others.
+ if (c->lav_codecpar) {
+ if (avcodec_parameters_copy(avp, c->lav_codecpar) < 0)
+ goto error;
+ return avp;
+ }
+
+ avp->codec_type = mp_to_av_stream_type(c->type);
+ 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);
+ if (!avp->extradata)
+ goto error;
+ avp->extradata_size = c->extradata_size;
+ memcpy(avp->extradata, c->extradata, avp->extradata_size);
+ }
+ avp->bits_per_coded_sample = c->bits_per_coded_sample;
+
+ // Video only
+ avp->width = c->disp_w;
+ avp->height = c->disp_h;
+ if (c->codec && strcmp(c->codec, "mp-rawvideo") == 0) {
+ avp->format = imgfmt2pixfmt(c->codec_tag);
+ avp->codec_tag = 0;
+ }
+
+ // Audio only
+ avp->sample_rate = c->samplerate;
+ avp->bit_rate = c->bitrate;
+ avp->block_align = c->block_align;
+ avp->channels = c->channels.num;
+ if (!mp_chmap_is_unknown(&c->channels))
+ avp->channel_layout = mp_chmap_to_lavc(&c->channels);
+
+ return avp;
+error:
+ avcodec_parameters_free(&avp);
+ return NULL;
+}
+
+// Set avctx codec headers for decoding. Returns <0 on failure.
+int mp_set_avctx_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c)
+{
+ enum AVMediaType codec_type = avctx->codec_type;
+ enum AVCodecID codec_id = avctx->codec_id;
+ AVCodecParameters *avp = mp_codec_params_to_av(c);
+ if (!avp)
+ return -1;
+
+ int r = avcodec_parameters_to_context(avctx, avp) < 0 ? -1 : 0;
+ avcodec_parameters_free(&avp);
+
+ if (avctx->codec_type != AVMEDIA_TYPE_UNKNOWN)
+ avctx->codec_type = codec_type;
+ if (avctx->codec_id != AV_CODEC_ID_NONE)
+ avctx->codec_id = codec_id;
+ return r;
}
// Pick a "good" timebase, which will be used to convert double timestamps
@@ -108,37 +155,24 @@ AVRational mp_get_codec_timebase(struct mp_codec_params *c)
return tb;
}
-// We merely pass-through our PTS/DTS as an int64_t; libavcodec won't use it.
-union pts { int64_t i; double d; };
+static AVRational get_def_tb(AVRational *tb)
+{
+ return tb && tb->num > 0 && tb->den > 0 ? *tb : AV_TIME_BASE_Q;
+}
// Convert the mpv style timestamp (seconds as double) to a libavcodec style
// timestamp (integer units in a given timebase).
-//
-// If the given timebase is NULL or invalid, pass through the mpv timestamp by
-// reinterpret casting them to int64_t. In this case, the timestamps will be
-// non-sense for libavcodec, but we expect that it doesn't interpret them,
-// and treats them as opaque.
int64_t mp_pts_to_av(double mp_pts, AVRational *tb)
{
- assert(sizeof(int64_t) >= sizeof(double));
- if (tb && tb->num > 0 && tb->den > 0) {
- return mp_pts == MP_NOPTS_VALUE ?
- AV_NOPTS_VALUE : llrint(mp_pts / av_q2d(*tb));
- }
- // The + 0.0 is to squash possible negative zero mp_pts, which would
- // happen to end up as AV_NOPTS_VALUE.
- return (union pts){.d = mp_pts + 0.0}.i;
+ AVRational b = get_def_tb(tb);
+ return mp_pts == MP_NOPTS_VALUE ? AV_NOPTS_VALUE : llrint(mp_pts / av_q2d(b));
}
// Inverse of mp_pts_to_av(). (The timebases must be exactly the same.)
double mp_pts_from_av(int64_t av_pts, AVRational *tb)
{
- assert(sizeof(int64_t) >= sizeof(double));
- if (tb && tb->num > 0 && tb->den > 0)
- return av_pts == AV_NOPTS_VALUE ? MP_NOPTS_VALUE : av_pts * av_q2d(*tb);
- // Should libavcodec set the PTS to AV_NOPTS_VALUE, it would end up as
- // non-sense (usually negative zero) when unwrapped to double.
- return av_pts == AV_NOPTS_VALUE ? MP_NOPTS_VALUE : (union pts){.i = av_pts}.d;
+ AVRational b = get_def_tb(tb);
+ return av_pts == AV_NOPTS_VALUE ? MP_NOPTS_VALUE : av_pts * av_q2d(b);
}
// Set dst from mpkt. Note that dst is not refcountable.