summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-03-09 20:21:12 +0100
committerwm4 <wm4@nowhere>2013-03-13 23:51:30 +0100
commit71b09be04056d9a505f32c71375ebc327d842ae4 (patch)
treee3751ded26018df86d8d76f172b77a7e0286cdb1 /video
parentdfe7b3898da2e6f9036de0c5c13dccf4a8ca45f7 (diff)
downloadmpv-71b09be04056d9a505f32c71375ebc327d842ae4.tar.bz2
mpv-71b09be04056d9a505f32c71375ebc327d842ae4.tar.xz
video: prepare for libavcodec refcounting
Some minor refactoring and moving code around. There should be no functional changes.
Diffstat (limited to 'video')
-rw-r--r--video/decode/vd_lavc.c86
-rw-r--r--video/mp_image.c53
-rw-r--r--video/mp_image.h7
3 files changed, 84 insertions, 62 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 4922f57387..874dd12694 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -61,8 +61,7 @@
static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec);
static void uninit_avctx(sh_video_t *sh);
-static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic);
-static void release_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic);
+static void setup_refcounting_hw(struct AVCodecContext *s);
static void draw_slice_hwdec(struct AVCodecContext *s, const AVFrame *src,
int offset[4], int y, int type, int height);
@@ -274,17 +273,18 @@ static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
ctx->do_hw_dr1 = true;
avctx->thread_count = 1;
avctx->get_format = get_format_hwdec;
- avctx->get_buffer = get_buffer_hwdec;
- avctx->release_buffer = release_buffer_hwdec;
+ setup_refcounting_hw(avctx);
if (ctx->hwdec->api == HWDEC_VDPAU) {
avctx->draw_horiz_band = draw_slice_hwdec;
avctx->slice_flags =
SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
}
- } else if (lavc_codec->capabilities & CODEC_CAP_DR1) {
- ctx->do_dr1 = true;
- avctx->get_buffer = mp_codec_get_buffer;
- avctx->release_buffer = mp_codec_release_buffer;
+ } else {
+ if (lavc_codec->capabilities & CODEC_CAP_DR1) {
+ ctx->do_dr1 = true;
+ avctx->get_buffer = mp_codec_get_buffer;
+ avctx->release_buffer = mp_codec_release_buffer;
+ }
}
if (avctx->thread_count == 0) {
@@ -525,6 +525,12 @@ static void release_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
pic->data[i] = NULL;
}
+static void setup_refcounting_hw(AVCodecContext *avctx)
+{
+ avctx->get_buffer = get_buffer_hwdec;
+ avctx->release_buffer = release_buffer_hwdec;
+}
+
static void fb_ref(void *b)
{
mp_buffer_ref(b);
@@ -540,6 +546,31 @@ static bool fb_is_unique(void *b)
return mp_buffer_is_unique(b);
}
+static struct mp_image *image_from_decoder(struct sh_video *sh)
+{
+ vd_ffmpeg_ctx *ctx = sh->context;
+ AVFrame *pic = ctx->pic;
+
+ struct mp_image new = {0};
+ mp_image_copy_fields_from_av_frame(&new, pic);
+
+ struct mp_image *mpi;
+ if (ctx->do_hw_dr1 && pic->opaque) {
+ mpi = pic->opaque; // reordered frame
+ assert(mpi);
+ mpi = mp_image_new_ref(mpi);
+ mp_image_copy_attributes(mpi, &new);
+ } else if (ctx->do_dr1 && pic->opaque) {
+ struct FrameBuffer *fb = pic->opaque;
+ mp_buffer_ref(fb); // initial reference for mpi
+ mpi = mp_image_new_external_ref(&new, fb, fb_ref, fb_unref,
+ fb_is_unique, NULL);
+ } else {
+ mpi = mp_image_pool_new_copy(ctx->non_dr1_pool, &new);
+ }
+ return mpi;
+}
+
static int decode(struct sh_video *sh, struct demux_packet *packet, void *data,
int len, int flags, double *reordered_pts,
struct mp_image **out_image)
@@ -585,48 +616,11 @@ static int decode(struct sh_video *sh, struct demux_packet *packet, void *data,
if (init_vo(sh, pic) < 0)
return -1;
- struct mp_image *mpi = NULL;
- if (ctx->do_hw_dr1 && pic->opaque) {
- mpi = pic->opaque; // reordered frame
- assert(mpi);
- mpi = mp_image_new_ref(mpi);
- }
-
- if (!mpi) {
- struct mp_image new = {0};
- mp_image_set_size(&new, pic->width, pic->height);
- mp_image_setfmt(&new, ctx->best_csp);
- for (int i = 0; i < 4; i++) {
- new.planes[i] = pic->data[i];
- new.stride[i] = pic->linesize[i];
- }
- if (ctx->do_dr1 && pic->opaque) {
- struct FrameBuffer *fb = pic->opaque;
- mp_buffer_ref(fb); // initial reference for mpi
- mpi = mp_image_new_external_ref(&new, fb, fb_ref, fb_unref,
- fb_is_unique);
- } else {
- mpi = mp_image_pool_get(ctx->non_dr1_pool, new.imgfmt,
- new.w, new.h);
- mp_image_copy(mpi, &new);
- }
- }
-
+ struct mp_image *mpi = image_from_decoder(sh);
assert(mpi->planes[0]);
mpi->colorspace = sh->colorspace;
mpi->levels = sh->color_range;
- mpi->qscale = pic->qscale_table;
- mpi->qstride = pic->qstride;
- mpi->pict_type = pic->pict_type;
- mpi->qscale_type = pic->qscale_type;
- mpi->fields = MP_IMGFIELD_ORDERED;
- if (pic->interlaced_frame)
- mpi->fields |= MP_IMGFIELD_INTERLACED;
- if (pic->top_field_first)
- mpi->fields |= MP_IMGFIELD_TOP_FIRST;
- if (pic->repeat_pict == 1)
- mpi->fields |= MP_IMGFIELD_REPEAT_FIRST;
*out_image = mpi;
return 1;
diff --git a/video/mp_image.c b/video/mp_image.c
index 78becf28ea..57124eab11 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -29,10 +29,11 @@
#include "talloc.h"
-#include "video/img_format.h"
-#include "video/mp_image.h"
-#include "video/sws_utils.h"
-#include "video/memcpy_pic.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "sws_utils.h"
+#include "memcpy_pic.h"
+#include "fmt-conversion.h"
struct m_refcount {
void *arg;
@@ -41,7 +42,7 @@ struct m_refcount {
// External refcounted object (such as libavcodec DR buffers). This assumes
// that the actual data is managed by the external object, not by
// m_refcount. The .ext_* calls use that external object's refcount
- // primitives. It usually doesn't make sense to set both .free and .ext_*.
+ // primitives.
void (*ext_ref)(void *arg);
void (*ext_unref)(void *arg);
bool (*ext_is_unique)(void *arg);
@@ -236,23 +237,18 @@ struct mp_image *mp_image_new_ref(struct mp_image *img)
struct mp_image *mp_image_new_custom_ref(struct mp_image *img, void *free_arg,
void (*free)(void *arg))
{
- struct mp_image *new = talloc_ptrtype(NULL, new);
- talloc_set_destructor(new, mp_image_destructor);
- *new = *img;
-
- new->refcount = m_refcount_new();
- new->refcount->free = free;
- new->refcount->arg = free_arg;
- return new;
+ return mp_image_new_external_ref(img, free_arg, NULL, NULL, NULL, free);
}
// Return a reference counted reference to img. ref/unref/is_unique are used to
// connect to an external refcounting API. It is assumed that the new object
-// has an initial reference to that external API.
+// has an initial reference to that external API. If free is given, that is
+// called after the last unref. All function pointers are optional.
struct mp_image *mp_image_new_external_ref(struct mp_image *img, void *arg,
void (*ref)(void *arg),
void (*unref)(void *arg),
- bool (*is_unique)(void *arg))
+ bool (*is_unique)(void *arg),
+ void (*free)(void *arg))
{
struct mp_image *new = talloc_ptrtype(NULL, new);
talloc_set_destructor(new, mp_image_destructor);
@@ -262,6 +258,7 @@ struct mp_image *mp_image_new_external_ref(struct mp_image *img, void *arg,
new->refcount->ext_ref = ref;
new->refcount->ext_unref = unref;
new->refcount->ext_is_unique = is_unique;
+ new->refcount->free = free;
new->refcount->arg = arg;
return new;
}
@@ -436,3 +433,29 @@ void mp_image_set_colorspace_details(struct mp_image *image,
image->levels = MP_CSP_LEVELS_PC;
}
}
+
+// Copy properties and data of the AVFrame into the mp_image, without taking
+// care of memory management issues.
+void mp_image_copy_fields_from_av_frame(struct mp_image *dst,
+ struct AVFrame *src)
+{
+ mp_image_setfmt(dst, pixfmt2imgfmt(src->format));
+ mp_image_set_size(dst, src->width, src->height);
+
+ for (int i = 0; i < 4; i++) {
+ dst->planes[i] = src->data[i];
+ dst->stride[i] = src->linesize[i];
+ }
+
+ dst->qscale = src->qscale_table;
+ dst->qstride = src->qstride;
+ dst->pict_type = src->pict_type;
+ dst->qscale_type = src->qscale_type;
+ dst->fields = MP_IMGFIELD_ORDERED;
+ if (src->interlaced_frame)
+ dst->fields |= MP_IMGFIELD_INTERLACED;
+ if (src->top_field_first)
+ dst->fields |= MP_IMGFIELD_TOP_FIRST;
+ if (src->repeat_pict == 1)
+ dst->fields |= MP_IMGFIELD_REPEAT_FIRST;
+}
diff --git a/video/mp_image.h b/video/mp_image.h
index 6ba9393671..3fe2429445 100644
--- a/video/mp_image.h
+++ b/video/mp_image.h
@@ -117,7 +117,8 @@ struct mp_image *mp_image_new_custom_ref(struct mp_image *img, void *arg,
struct mp_image *mp_image_new_external_ref(struct mp_image *img, void *arg,
void (*ref)(void *arg),
void (*unref)(void *arg),
- bool (*is_unique)(void *arg));
+ bool (*is_unique)(void *arg),
+ void (*free)(void *arg));
enum mp_csp mp_image_csp(struct mp_image *img);
enum mp_csp_levels mp_image_levels(struct mp_image *img);
@@ -126,6 +127,10 @@ struct mp_csp_details;
void mp_image_set_colorspace_details(struct mp_image *image,
struct mp_csp_details *csp);
+struct AVFrame;
+void mp_image_copy_fields_from_av_frame(struct mp_image *dst,
+ struct AVFrame *src);
+
// align must be a power of two (align >= 1), v >= 0
#define MP_ALIGN_UP(v, align) FFALIGN(v, align)
#define MP_ALIGN_DOWN(v, align) ((v) & ~((align) - 1))