summaryrefslogtreecommitdiff
path: root/ffplay.c
diff options
context:
space:
mode:
authorBobby Bingham <uhmmmm@gmail.com>2010-04-01 06:41:21 +0000
committerBobby Bingham <uhmmmm@gmail.com>2010-04-01 06:41:21 +0000
commitdd0c789be7c5607ed7d21e547246e8481b4211d1 (patch)
tree7289b3378e1bac7a6dd5ab06b5050ff45caebba3 /ffplay.c
parent0fb49b597be60efb84bb39c09576baecc1471eeb (diff)
Hook decoder up to libavfilter's direct rendering for ffplay
Originally committed as revision 22754 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'ffplay.c')
-rw-r--r--ffplay.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/ffplay.c b/ffplay.c
index f3a076b98f..a0d8a18f5b 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -1558,14 +1558,71 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke
typedef struct {
VideoState *is;
AVFrame *frame;
+ int use_dr1;
} FilterPriv;
+static int input_get_buffer(AVCodecContext *codec, AVFrame *pic)
+{
+ AVFilterContext *ctx = codec->opaque;
+ AVFilterPicRef *ref;
+ int perms = AV_PERM_WRITE;
+ int w, h, stride[4];
+ unsigned edge;
+
+ if(pic->buffer_hints & FF_BUFFER_HINTS_VALID) {
+ if(pic->buffer_hints & FF_BUFFER_HINTS_READABLE) perms |= AV_PERM_READ;
+ if(pic->buffer_hints & FF_BUFFER_HINTS_PRESERVE) perms |= AV_PERM_PRESERVE;
+ if(pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE) perms |= AV_PERM_REUSE2;
+ }
+ if(pic->reference) perms |= AV_PERM_READ | AV_PERM_PRESERVE;
+
+ w = codec->width;
+ h = codec->height;
+ avcodec_align_dimensions2(codec, &w, &h, stride);
+ edge = codec->flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width();
+ w += edge << 1;
+ h += edge << 1;
+
+ if(!(ref = avfilter_get_video_buffer(ctx->outputs[0], perms, w, h)))
+ return -1;
+
+ ref->w = codec->width;
+ ref->h = codec->height;
+ for(int i = 0; i < 3; i ++) {
+ unsigned hshift = i == 0 ? 0 : av_pix_fmt_descriptors[ref->pic->format].log2_chroma_w;
+ unsigned vshift = i == 0 ? 0 : av_pix_fmt_descriptors[ref->pic->format].log2_chroma_h;
+
+ ref->data[i] += (edge >> hshift) + ((edge * ref->linesize[i]) >> vshift);
+ pic->data[i] = ref->data[i];
+ pic->linesize[i] = ref->linesize[i];
+ }
+ pic->opaque = ref;
+ pic->age = INT_MAX;
+ pic->type = FF_BUFFER_TYPE_USER;
+ return 0;
+}
+
+static void input_release_buffer(AVCodecContext *codec, AVFrame *pic)
+{
+ memset(pic->data, 0, sizeof(pic->data));
+ avfilter_unref_pic(pic->opaque);
+}
+
static int input_init(AVFilterContext *ctx, const char *args, void *opaque)
{
FilterPriv *priv = ctx->priv;
+ AVCodecContext *codec;
if(!opaque) return -1;
priv->is = opaque;
+ codec = priv->is->video_st->codec;
+ codec->opaque = ctx;
+ if(codec->codec->capabilities & CODEC_CAP_DR1) {
+ priv->use_dr1 = 1;
+ codec->get_buffer = input_get_buffer;
+ codec->release_buffer = input_release_buffer;
+ }
+
priv->frame = avcodec_alloc_frame();
return 0;
@@ -1590,11 +1647,13 @@ static int input_request_frame(AVFilterLink *link)
if (ret < 0)
return -1;
- /* FIXME: until I figure out how to hook everything up to the codec
- * right, we're just copying the entire frame. */
+ if(priv->use_dr1) {
+ picref = priv->frame->opaque;
+ } else {
picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, link->w, link->h);
av_picture_copy((AVPicture *)&picref->data, (AVPicture *)priv->frame,
picref->pic->format, link->w, link->h);
+ }
av_free_packet(&pkt);
picref->pts = pts;
@@ -1603,6 +1662,7 @@ static int input_request_frame(AVFilterLink *link)
avfilter_start_frame(link, avfilter_ref_pic(picref, ~0));
avfilter_draw_slice(link, 0, link->h, 1);
avfilter_end_frame(link);
+ if(!priv->use_dr1)
avfilter_unref_pic(picref);
return 0;