Web lists-archives.com

[MPlayer-dev-eng] [RFC][PATCH] Replace deprecated get_buffer, buffer_hints, and others




Hi,
 Just joking, I'm not really replacing them.

This is my proposed solution to the problem, that just drops dr for
lavc codecs (except hwaccel).


Why this?

 - modern codecs (eg. h264) are not compatible with the direct
rendering structure of mplayer (IPB frames, 2 IP 1 B). It may be
possible to do direct rendering for non-reference frames, but that also
was already non functional (disabled because of some bugs)

 - dr is already failing today with most codecs, because of missing
buffer_hints and reference flag. It fails also for things like mpeg2.
Nobody complained.

 - dr is functional today for old simple codecs (eg. rpza), but
performance is not relevant for someting written to run on a 386.

 - without buffer hints, I have no idea how to map the lavc frames to
our frames, even when this could be possible (eg. mpeg2)

 - Wrapping our data structures in AVBuffers is a mess


I have a patch that can replicate the behaviour of today (try dr and
fail usually at the 2nd frame) with the new get_buffer2, if anybody is
interested (I just need to clean it up).
But I don't suggest to take this route.


What about hwaccel?

The hwaccel portion of the code is there, and may work.
But I never used hwaccel, and I don't even know if my gpu (integrated
into i7 Sandybridge) is supported by MPlayer hw acceleration.

So somebody who has a clue about hwaccel should review and test it.



This patch is just for comments; there is still a lot of code that is
now useless but not removed yet, but it's late and I want to see what
other MPlayer devels think about it.


As usual it works for me, but I just did limited testing.
If there is agreement on this solution I will clean it up and submit
a proper patch.


Ciao,
 Roberto

Index: vd_ffmpeg.c
===================================================================
--- vd_ffmpeg.c	(revisione 37444)
+++ vd_ffmpeg.c	(copia locale)
@@ -80,7 +80,6 @@
     enum AVPixelFormat pix_fmt;
     int do_slices;
     int do_dr1;
-    int nonref_dr; ///< allow dr only for non-reference frames
     int vo_initialized;
     int best_csp;
     int qp_stat[32];
@@ -95,8 +94,8 @@
 
 #include "m_option.h"
 
-static int get_buffer(AVCodecContext *avctx, AVFrame *pic);
-static void release_buffer(AVCodecContext *avctx, AVFrame *pic);
+static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int fflags);
+static void release_buffer2(void *opaque, uint8_t *data);
 static void draw_slice(struct AVCodecContext *s, const AVFrame *src, int offset[4],
                        int y, int type, int height);
 
@@ -254,31 +253,14 @@
 
     ctx->do_slices = use_slices && (lavc_codec->capabilities & CODEC_CAP_DRAW_HORIZ_BAND);
 
-    ctx->do_dr1 = (lavc_codec->capabilities & CODEC_CAP_DR1) &&
-        lavc_codec->id != AV_CODEC_ID_INTERPLAY_VIDEO &&
-        lavc_codec->id != AV_CODEC_ID_H264 &&
-        lavc_codec->id != AV_CODEC_ID_HEVC;
-    ctx->nonref_dr = 0;
-    // TODO: fix and enable again. This currently causes issues when using filters
-    // and seeking, usually failing with the "Ran out of numbered images" message,
-    // but ticket #2118 might be related as well.
-    if (0 && lavc_codec->id == AV_CODEC_ID_H264) {
-        ctx->do_dr1 = 1;
-        ctx->nonref_dr = 1;
-    }
+    ctx->do_dr1 = 0;
     if (lavc_param_vismv || (lavc_param_debug & (FF_DEBUG_VIS_MB_TYPE|FF_DEBUG_VIS_QP))) {
         ctx->do_slices = ctx->do_dr1 = 0;
     }
     if(ctx->do_dr1){
-        avctx->flags |= CODEC_FLAG_EMU_EDGE;
-        avctx->  reget_buffer =
-        avctx->    get_buffer =     get_buffer;
-        avctx->release_buffer = release_buffer;
+        avctx->get_buffer2 = get_buffer2;
     } else if (lavc_codec->capabilities & CODEC_CAP_DR1) {
-        avctx->flags &= ~CODEC_FLAG_EMU_EDGE;
-        avctx->  reget_buffer = avcodec_default_reget_buffer;
-        avctx->    get_buffer = avcodec_default_get_buffer;
-        avctx->release_buffer = avcodec_default_release_buffer;
+        avctx->get_buffer2 = avcodec_default_get_buffer2;
     }
     avctx->slice_flags = 0;
 }
@@ -305,10 +287,7 @@
 #endif
     if (IMGFMT_IS_HWACCEL(imgfmt)) {
         ctx->do_dr1    = 1;
-        ctx->nonref_dr = 0;
-        avctx->get_buffer      = get_buffer;
-        avctx->release_buffer  = release_buffer;
-        avctx->reget_buffer    = get_buffer;
+        avctx->get_buffer2 = get_buffer2;
         mp_msg(MSGT_DECVIDEO, MSGL_V, IMGFMT_IS_XVMC(imgfmt) ?
                MSGTR_MPCODECS_XVMCAcceleratedMPEG2 :
                "[VD_FFMPEG] VDPAU accelerated decoding\n");
@@ -381,7 +360,6 @@
 #endif
     avctx->flags2|= lavc_param_fast;
     avctx->codec_tag= sh->format;
-    avctx->stream_codec_tag= sh->video.fccHandler;
     avctx->idct_algo= lavc_param_idct_algo;
     avctx->error_concealment= lavc_param_error_concealment;
     avctx->debug= lavc_param_debug;
@@ -672,7 +650,7 @@
     return 0;
 }
 
-static int get_buffer(AVCodecContext *avctx, AVFrame *pic){
+static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int fflags){
     sh_video_t *sh = avctx->opaque;
     vd_ffmpeg_ctx *ctx = sh->context;
     mp_image_t *mpi=NULL;
@@ -681,74 +659,19 @@
     int width = FFMAX(avctx->width,  -(-avctx->coded_width  >> avctx->lowres));
     int height= FFMAX(avctx->height, -(-avctx->coded_height >> avctx->lowres));
     // special case to handle reget_buffer
-    if (pic->opaque && pic->data[0] && (!pic->buffer_hints || pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE))
+    if (pic->opaque && pic->data[0])
         return 0;
     avcodec_align_dimensions(avctx, &width, &height);
 //printf("get_buffer %d %d %d\n", pic->reference, ctx->ip_count, ctx->b_count);
 
-    if (pic->buffer_hints) {
-        mp_msg(MSGT_DECVIDEO, MSGL_DBG2, "Buffer hints: %u\n", pic->buffer_hints);
-        type = MP_IMGTYPE_TEMP;
-        if (pic->buffer_hints & FF_BUFFER_HINTS_READABLE)
-            flags |= MP_IMGFLAG_READABLE;
-        if (pic->buffer_hints & FF_BUFFER_HINTS_PRESERVE ||
-            pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE) {
-            ctx->ip_count++;
-            type = MP_IMGTYPE_IP;
-            flags |= MP_IMGFLAG_PRESERVE;
-        }
-        flags|=(avctx->skip_idct<=AVDISCARD_DEFAULT && avctx->skip_frame<=AVDISCARD_DEFAULT && ctx->do_slices) ?
-                 MP_IMGFLAG_DRAW_CALLBACK:0;
-        mp_msg(MSGT_DECVIDEO, MSGL_DBG2, type == MP_IMGTYPE_IP ? "using IP\n" : "using TEMP\n");
-    } else {
-        if(!pic->reference){
-            ctx->b_count++;
-            flags|=(avctx->skip_idct<=AVDISCARD_DEFAULT && avctx->skip_frame<=AVDISCARD_DEFAULT && ctx->do_slices) ?
-                     MP_IMGFLAG_DRAW_CALLBACK:0;
-        }else{
-            ctx->ip_count++;
-            flags|= MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE
-                      | (ctx->do_slices ? MP_IMGFLAG_DRAW_CALLBACK : 0);
-        }
-        if(avctx->has_b_frames || ctx->b_count){
-            type= MP_IMGTYPE_IPB;
-        }else{
-            type= MP_IMGTYPE_IP;
-        }
-    }
-
-    if (ctx->nonref_dr) {
-        if (flags & MP_IMGFLAG_PRESERVE)
-            return avcodec_default_get_buffer(avctx, pic);
-        // Use NUMBERED since for e.g. TEMP vos assume there will
-        // be no other frames between the get_image and matching put_image.
-        type = MP_IMGTYPE_NUMBERED;
-    }
-
     if(init_vo(sh, avctx->pix_fmt, 1) < 0){
-        avctx->release_buffer= avcodec_default_release_buffer;
-        goto disable_dr1;
+        return -1; // Can this really happen with hwaccel?
     }
 
-    if (IMGFMT_IS_HWACCEL(ctx->best_csp)) {
+    if (IMGFMT_IS_HWACCEL(ctx->best_csp)) { // Always true with hwaccel
         type =  MP_IMGTYPE_NUMBERED;
-    } else if (avctx->has_b_frames) {
-        // HACK/TODO: slices currently do not work properly with B-frames,
-        // causing out-of-order frames or crashes with e.g. -vf scale,unsharp
-        // or -vf screenshot,unsharp.
-        flags &= ~MP_IMGFLAG_DRAW_CALLBACK;
     }
-    if (type == MP_IMGTYPE_IP || type == MP_IMGTYPE_IPB) {
-        if(ctx->b_count>1 || ctx->ip_count>2){
-            mp_msg(MSGT_DECVIDEO, MSGL_WARN, MSGTR_MPCODECS_DRIFailure);
-            goto disable_dr1;
-        }
 
-        mp_msg(MSGT_DECVIDEO, MSGL_DBG2, type== MP_IMGTYPE_IPB ? "using IPB\n" : "using IP\n");
-    }
-
-    if (ctx->best_csp == IMGFMT_RGB8 || ctx->best_csp == IMGFMT_BGR8)
-        flags |= MP_IMGFLAG_RGB_PALETTE;
     mpi= mpcodecs_get_image(sh, type, flags, width, height);
     if (!mpi) return -1;
 
@@ -814,6 +737,11 @@
     pic->linesize[2]= mpi->stride[2];
     pic->linesize[3]= mpi->stride[3];
 
+    pic->buf[0] = av_buffer_create(pic->data[0],pic->linesize[0],&release_buffer2,pic,0);
+    pic->buf[1] = av_buffer_create(pic->data[1],pic->linesize[1],&release_buffer2,pic,0);
+    pic->buf[2] = av_buffer_create(pic->data[2],pic->linesize[2],&release_buffer2,pic,0);
+    pic->buf[3] = av_buffer_create(pic->data[3],pic->linesize[3],&release_buffer2,pic,0);
+
     pic->width  = avctx->width;
     pic->height = avctx->height;
     pic->format = avctx->pix_fmt;
@@ -828,40 +756,19 @@
 else
     printf(".");
 #endif
-    pic->type= FF_BUFFER_TYPE_USER;
     return 0;
 
-disable_dr1:
-    ctx->do_dr1 = 0;
-    // For frame-multithreading these contexts aren't
-    // the same and must both be updated.
-    ctx->avctx->get_buffer   =
-    avctx->get_buffer        = avcodec_default_get_buffer;
-    ctx->avctx->reget_buffer =
-    avctx->reget_buffer      = avcodec_default_reget_buffer;
-    if (pic->data[0])
-        release_buffer(avctx, pic);
-    return avctx->get_buffer(avctx, pic);
 }
 
-static void release_buffer(struct AVCodecContext *avctx, AVFrame *pic){
+//static void release_buffer(struct AVCodecContext *avctx, AVFrame *pic){
+static void release_buffer2(void *opaque, uint8_t *data){
+    AVFrame *pic = opaque;
     mp_image_t *mpi= pic->opaque;
-    sh_video_t *sh = avctx->opaque;
-    vd_ffmpeg_ctx *ctx = sh->context;
-    int i;
-    if (pic->type != FF_BUFFER_TYPE_USER) {
-        avcodec_default_release_buffer(avctx, pic);
-        return;
-    }
+//    int i;
 
     if (mpi) {
 //printf("release buffer %d %d %d\n", mpi ? mpi->flags&MP_IMGFLAG_PRESERVE : -99, ctx->ip_count, ctx->b_count);
 
-        if(mpi->flags&MP_IMGFLAG_PRESERVE)
-            ctx->ip_count--;
-        else
-            ctx->b_count--;
-
         // release mpi (in case MPI_IMGTYPE_NUMBERED is used, e.g. for VDPAU)
         mpi->usage_count--;
         if (mpi->usage_count < 0) {
@@ -869,10 +776,9 @@
             mpi->usage_count = 0;
         }
     }
-
-    for(i=0; i<4; i++){
-        pic->data[i]= NULL;
-    }
+//    for(i=0; i<4; i++){
+//        pic->data[i]= NULL;
+//    }
 //printf("R%X %X\n", pic->linesize[0], pic->data[0]);
 }
 
@@ -966,10 +872,6 @@
     pkt.size = 0;
     av_packet_free_side_data(&pkt);
 
-    // even when we do dr we might actually get a buffer we had
-    // FFmpeg allocate - this mostly happens with nonref_dr.
-    // Ensure we treat it correctly.
-    dr1= ctx->do_dr1 && pic->type == FF_BUFFER_TYPE_USER;
     if(ret<0) mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Error while decoding frame!\n");
 //printf("repeat: %d\n", pic->repeat_pict);
 //-- vstats generation
_______________________________________________
MPlayer-dev-eng mailing list
MPlayer-dev-eng@xxxxxxxxxxxx
https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng