vd_lavc: remove codec DR

This was buggy and didn't even work in the simplest cases. It was
disabled when multithreading was used, and always disabled for h264.

A better alternative (reference counting) will be added later.

Hardware decoding still uses the ffmpeg DR mechanism, but has been
decoupled from mpv's DR in the previous commit.
This commit is contained in:
wm4 2012-11-05 19:36:26 +01:00
parent 2d8fb838d7
commit dab286a159
3 changed files with 14 additions and 203 deletions

View File

@ -218,13 +218,3 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt)
return 1;
}
// mp_imgtype: buffering type, see mp_image.h
// mp_imgflag: buffer requirements (read/write, preserve, stride limits), see mp_image.h
// returns NULL or allocated mp_image_t*
// Note: buffer allocation may be moved to mpcodecs_config_vo() later...
mp_image_t *mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag,
int w, int h)
{
return vf_get_image(sh->vfilter, sh->outfmt, mp_imgtype, mp_imgflag, w, h);
}

View File

@ -46,10 +46,6 @@ extern const vd_functions_t *const mpcodecs_vd_drivers[];
#define VDCTRL_QUERY_UNSEEN_FRAMES 9 // current decoder lag
#define VDCTRL_RESET_ASPECT 10 // reinit filter/VO chain for new aspect ratio
// callbacks:
int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int outfmt);
mp_image_t *mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag,
int w, int h);
#endif /* MPLAYER_VD_H */

View File

@ -67,6 +67,7 @@ static const vd_info_t info = {
typedef struct {
AVCodecContext *avctx;
AVFrame *pic;
struct mp_image export_mpi;
struct mp_image hwdec_mpi[MAX_NUM_MPI];
enum PixelFormat pix_fmt;
int do_dr1;
@ -75,17 +76,12 @@ typedef struct {
int qp_stat[32];
double qp_sum;
double inv_qp_sum;
int ip_count;
int b_count;
AVRational last_sample_aspect_ratio;
enum AVDiscard skip_frame;
} vd_ffmpeg_ctx;
#include "core/m_option.h"
static int get_buffer(AVCodecContext *avctx, AVFrame *pic);
static void release_buffer(AVCodecContext *avctx, AVFrame *pic);
static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic);
static void release_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic);
static void draw_slice_hwdec(struct AVCodecContext *s, const AVFrame *src,
@ -218,8 +214,6 @@ static int init(sh_video_t *sh)
vd_ffmpeg_ctx *ctx;
AVCodec *lavc_codec = NULL;
enum PixelFormat rawfmt = PIX_FMT_NONE;
int do_vis_debug = lavc_param->vismv ||
(lavc_param->debug & (FF_DEBUG_VIS_MB_TYPE | FF_DEBUG_VIS_QP));
ctx = sh->context = talloc_zero(NULL, vd_ffmpeg_ctx);
@ -254,14 +248,6 @@ static int init(sh_video_t *sh)
if (!sh->codecname)
sh->codecname = lavc_codec->name;
if (lavc_codec->capabilities & CODEC_CAP_DR1 && !do_vis_debug
&& lavc_codec->id != CODEC_ID_H264
&& lavc_codec->id != CODEC_ID_INTERPLAY_VIDEO
&& lavc_codec->id != CODEC_ID_ROQ && lavc_codec->id != CODEC_ID_VP8
&& lavc_codec->id != CODEC_ID_LAGARITH)
ctx->do_dr1 = sh->opts->vd_use_dr1;
ctx->ip_count = ctx->b_count = 0;
ctx->pic = avcodec_alloc_frame();
ctx->avctx = avcodec_alloc_context3(lavc_codec);
avctx = ctx->avctx;
@ -294,20 +280,6 @@ static int init(sh_video_t *sh)
threads = FFMIN(threads, 16);
avctx->thread_count = threads;
}
/* Our get_buffer and draw_horiz_band callbacks are not safe to call
* from other threads. */
if (avctx->thread_count > 1) {
ctx->do_dr1 = false;
mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Asking decoder to use "
"%d threads if supported.\n", avctx->thread_count);
}
if (ctx->do_dr1 && avctx->get_buffer != get_buffer_hwdec) {
avctx->flags |= CODEC_FLAG_EMU_EDGE;
avctx->get_buffer = get_buffer;
avctx->release_buffer = release_buffer;
avctx->reget_buffer = get_buffer;
}
avctx->flags |= lavc_param->bitexact;
@ -588,141 +560,6 @@ static void release_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
pic->data[i] = NULL;
}
static int get_buffer(AVCodecContext *avctx, AVFrame *pic)
{
sh_video_t *sh = avctx->opaque;
vd_ffmpeg_ctx *ctx = sh->context;
mp_image_t *mpi = NULL;
int flags = MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE |
MP_IMGFLAG_PREFER_ALIGNED_STRIDE;
int type = MP_IMGTYPE_IPB;
int width = avctx->width;
int height = avctx->height;
// special case to handle reget_buffer without buffer hints
if (pic->opaque && pic->data[0] && !pic->buffer_hints)
return 0;
avcodec_align_dimensions(avctx, &width, &height);
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) {
type = MP_IMGTYPE_STATIC;
flags |= MP_IMGFLAG_PRESERVE;
}
if (pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE) {
type = MP_IMGTYPE_STATIC;
flags |= MP_IMGFLAG_PRESERVE;
}
mp_msg(MSGT_DECVIDEO, MSGL_DBG2,
type == MP_IMGTYPE_STATIC ? "using STATIC\n" : "using TEMP\n");
} else {
if (!pic->reference) {
ctx->b_count++;
} else {
ctx->ip_count++;
flags |= MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE;
}
}
if (init_vo(sh, avctx->pix_fmt) < 0) {
avctx->release_buffer = avcodec_default_release_buffer;
avctx->get_buffer = avcodec_default_get_buffer;
avctx->reget_buffer = avcodec_default_reget_buffer;
if (pic->data[0])
release_buffer(avctx, pic);
return avctx->get_buffer(avctx, pic);
}
if (IMGFMT_IS_HWACCEL(ctx->best_csp))
type = MP_IMGTYPE_NUMBERED | (0xffff << 16);
else if (!pic->buffer_hints) {
if (ctx->b_count > 1 || ctx->ip_count > 2) {
mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "[VD_FFMPEG] DRI failure.\n");
ctx->do_dr1 = 0; //FIXME
avctx->get_buffer = avcodec_default_get_buffer;
avctx->reget_buffer = avcodec_default_reget_buffer;
if (pic->data[0])
release_buffer(avctx, pic);
return avctx->get_buffer(avctx, pic);
}
if (avctx->has_b_frames || ctx->b_count)
type = MP_IMGTYPE_IPB;
else
type = MP_IMGTYPE_IP;
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;
pic->data[0] = mpi->planes[0];
pic->data[1] = mpi->planes[1];
pic->data[2] = mpi->planes[2];
pic->data[3] = mpi->planes[3];
/* Note: some (many) codecs in libavcodec require
* linesize[1] == linesize[2] and no changes between frames.
* Lavc will check that and die with an error message if it's not true.
*/
pic->linesize[0] = mpi->stride[0];
pic->linesize[1] = mpi->stride[1];
pic->linesize[2] = mpi->stride[2];
pic->linesize[3] = mpi->stride[3];
pic->opaque = mpi;
pic->type = FF_BUFFER_TYPE_USER;
/* The libavcodec reordered_opaque functionality is implemented by
* a similar copy in avcodec_default_get_buffer() and without a
* workaround like this it'd stop working when a custom buffer
* callback is used.
*/
pic->reordered_opaque = avctx->reordered_opaque;
return 0;
}
static void release_buffer(struct AVCodecContext *avctx, AVFrame *pic)
{
mp_image_t *mpi = pic->opaque;
sh_video_t *sh = avctx->opaque;
vd_ffmpeg_ctx *ctx = sh->context;
if (ctx->ip_count <= 2 && ctx->b_count <= 1) {
if (mpi->flags & MP_IMGFLAG_PRESERVE)
ctx->ip_count--;
else
ctx->b_count--;
}
if (mpi) {
// release mpi (in case MPI_IMGTYPE_NUMBERED is used, e.g. for VDPAU)
mpi->usage_count--;
if (mpi->usage_count < 0) {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Bad mp_image usage count, please report!\n");
mpi->usage_count = 0;
}
}
if (pic->type != FF_BUFFER_TYPE_USER) {
avcodec_default_release_buffer(avctx, pic);
return;
}
for (int i = 0; i < 4; i++)
pic->data[i] = NULL;
}
static av_unused void swap_palette(void *pal)
{
int i;
@ -740,7 +577,6 @@ static struct mp_image *decode(struct sh_video *sh, struct demux_packet *packet,
vd_ffmpeg_ctx *ctx = sh->context;
AVFrame *pic = ctx->pic;
AVCodecContext *avctx = ctx->avctx;
mp_image_t *mpi = NULL;
AVPacket pkt;
if (flags & 2)
@ -779,27 +615,22 @@ static struct mp_image *decode(struct sh_video *sh, struct demux_packet *packet,
if (init_vo(sh, avctx->pix_fmt) < 0)
return NULL;
struct mp_image *mpi = NULL;
if (dr1 && pic->opaque)
mpi = (mp_image_t *)pic->opaque;
if (!mpi)
mpi = mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, MP_IMGFLAG_PRESERVE,
avctx->width, avctx->height);
if (!mpi) { // temporary error?
mp_tmsg(MSGT_DECVIDEO, MSGL_WARN,
"[VD_FFMPEG] Couldn't allocate image for codec.\n");
return NULL;
if (!mpi) {
mpi = &ctx->export_mpi;
*mpi = (struct mp_image) {0};
mpi->type = MP_IMGTYPE_EXPORT;
mpi->flags = MP_IMGFLAG_PRESERVE;
mpi->w = mpi->width = avctx->width;
mpi->h = mpi->height = avctx->height;
mp_image_setfmt(mpi, ctx->best_csp);
for (int i = 0; i < 4; i++) {
mpi->planes[i] = pic->data[i];
mpi->stride[i] = pic->linesize[i];
}
if (!dr1) {
mpi->planes[0] = pic->data[0];
mpi->planes[1] = pic->data[1];
mpi->planes[2] = pic->data[2];
mpi->planes[3] = pic->data[3];
mpi->stride[0] = pic->linesize[0];
mpi->stride[1] = pic->linesize[1];
mpi->stride[2] = pic->linesize[2];
mpi->stride[3] = pic->linesize[3];
}
if (!mpi->planes[0])
@ -807,12 +638,6 @@ static struct mp_image *decode(struct sh_video *sh, struct demux_packet *packet,
assert(mpi->imgfmt == pixfmt2imgfmt(avctx->pix_fmt));
if (ctx->best_csp == IMGFMT_422P && mpi->chroma_y_shift == 1) {
// we have 422p but user wants 420p
mpi->stride[1] *= 2;
mpi->stride[2] *= 2;
}
#if BYTE_ORDER == BIG_ENDIAN
// FIXME: this might cause problems for buffers with FF_BUFFER_HINTS_PRESERVE
if (mpi->bpp == 8)