summaryrefslogtreecommitdiffstats
path: root/libmpcodecs/vd_ffmpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmpcodecs/vd_ffmpeg.c')
-rw-r--r--libmpcodecs/vd_ffmpeg.c325
1 files changed, 135 insertions, 190 deletions
diff --git a/libmpcodecs/vd_ffmpeg.c b/libmpcodecs/vd_ffmpeg.c
index a54254b80b..27cb4134cc 100644
--- a/libmpcodecs/vd_ffmpeg.c
+++ b/libmpcodecs/vd_ffmpeg.c
@@ -20,18 +20,23 @@
#include <stdlib.h>
#include <assert.h>
#include <time.h>
+#include <stdbool.h>
#include "config.h"
#include "mp_msg.h"
#include "help_mp.h"
+#include "options.h"
#include "av_opts.h"
#include "libavutil/common.h"
-#include "libavutil/intreadwrite.h"
+#include "ffmpeg_files/intreadwrite.h"
#include "mpbswap.h"
#include "fmt-conversion.h"
-#include "vd_internal.h"
+#include "vd.h"
+#include "img_format.h"
+#include "libmpdemux/stheader.h"
+#include "codec-cfg.h"
static const vd_info_t info = {
"FFmpeg's libavcodec codec family",
@@ -41,8 +46,6 @@ static const vd_info_t info = {
"native codecs"
};
-LIBVD_EXTERN(ffmpeg)
-
#include "libavcodec/avcodec.h"
#if AVPALETTE_SIZE > 1024
@@ -71,57 +74,39 @@ typedef struct {
int ip_count;
int b_count;
AVRational last_sample_aspect_ratio;
+ int lowres;
} vd_ffmpeg_ctx;
#include "m_option.h"
static int get_buffer(AVCodecContext *avctx, AVFrame *pic);
static void release_buffer(AVCodecContext *avctx, AVFrame *pic);
-static void draw_slice(struct AVCodecContext *s, const AVFrame *src, int offset[4],
- int y, int type, int height);
+static void draw_slice(struct AVCodecContext *s, const AVFrame *src,
+ int offset[4], int y, int type, int height);
static enum PixelFormat get_format(struct AVCodecContext *avctx,
const enum PixelFormat *pix_fmt);
-
-static int lavc_param_workaround_bugs= FF_BUG_AUTODETECT;
-static int lavc_param_error_resilience=2;
-static int lavc_param_error_concealment=3;
-static int lavc_param_gray=0;
-static int lavc_param_vstats=0;
-static int lavc_param_idct_algo=0;
-static int lavc_param_debug=0;
-static int lavc_param_vismv=0;
-static int lavc_param_skip_top=0;
-static int lavc_param_skip_bottom=0;
-static int lavc_param_fast=0;
-static int lavc_param_lowres=0;
-static char *lavc_param_lowres_str=NULL;
-static char *lavc_param_skip_loop_filter_str = NULL;
-static char *lavc_param_skip_idct_str = NULL;
-static char *lavc_param_skip_frame_str = NULL;
-static int lavc_param_threads=1;
-static int lavc_param_bitexact=0;
-static char *lavc_avopt = NULL;
+static void uninit(struct sh_video *sh);
const m_option_t lavc_decode_opts_conf[]={
- {"bug", &lavc_param_workaround_bugs, CONF_TYPE_INT, CONF_RANGE, -1, 999999, NULL},
- {"er", &lavc_param_error_resilience, CONF_TYPE_INT, CONF_RANGE, 0, 99, NULL},
- {"gray", &lavc_param_gray, CONF_TYPE_FLAG, 0, 0, CODEC_FLAG_PART, NULL},
- {"idct", &lavc_param_idct_algo, CONF_TYPE_INT, CONF_RANGE, 0, 99, NULL},
- {"ec", &lavc_param_error_concealment, CONF_TYPE_INT, CONF_RANGE, 0, 99, NULL},
- {"vstats", &lavc_param_vstats, CONF_TYPE_FLAG, 0, 0, 1, NULL},
- {"debug", &lavc_param_debug, CONF_TYPE_INT, CONF_RANGE, 0, 9999999, NULL},
- {"vismv", &lavc_param_vismv, CONF_TYPE_INT, CONF_RANGE, 0, 9999999, NULL},
- {"st", &lavc_param_skip_top, CONF_TYPE_INT, CONF_RANGE, 0, 999, NULL},
- {"sb", &lavc_param_skip_bottom, CONF_TYPE_INT, CONF_RANGE, 0, 999, NULL},
- {"fast", &lavc_param_fast, CONF_TYPE_FLAG, 0, 0, CODEC_FLAG2_FAST, NULL},
- {"lowres", &lavc_param_lowres_str, CONF_TYPE_STRING, 0, 0, 0, NULL},
- {"skiploopfilter", &lavc_param_skip_loop_filter_str, CONF_TYPE_STRING, 0, 0, 0, NULL},
- {"skipidct", &lavc_param_skip_idct_str, CONF_TYPE_STRING, 0, 0, 0, NULL},
- {"skipframe", &lavc_param_skip_frame_str, CONF_TYPE_STRING, 0, 0, 0, NULL},
- {"threads", &lavc_param_threads, CONF_TYPE_INT, CONF_RANGE, 1, 8, NULL},
- {"bitexact", &lavc_param_bitexact, CONF_TYPE_FLAG, 0, 0, CODEC_FLAG_BITEXACT, NULL},
- {"o", &lavc_avopt, CONF_TYPE_STRING, 0, 0, 0, NULL},
+ OPT_INTRANGE("bug", lavc_param.workaround_bugs, 0, -1, 999999),
+ OPT_INTRANGE("er", lavc_param.error_resilience, 0, 0, 99),
+ OPT_FLAG_ON("gray", lavc_param.gray, 0),
+ OPT_INTRANGE("idct", lavc_param.idct_algo, 0, 0, 99),
+ OPT_INTRANGE("ec", lavc_param.error_concealment, 0, 0, 99),
+ OPT_FLAG_ON("vstats", lavc_param.vstats, 0),
+ OPT_INTRANGE("debug", lavc_param.debug, 0, 0, 9999999),
+ OPT_INTRANGE("vismv", lavc_param.vismv, 0, 0, 9999999),
+ OPT_INTRANGE("st", lavc_param.skip_top, 0, 0, 999),
+ OPT_INTRANGE("sb", lavc_param.skip_bottom, 0, 0, 999),
+ OPT_FLAG_CONSTANTS("fast", lavc_param.fast, 0, 0, CODEC_FLAG2_FAST),
+ OPT_STRING("lowres", lavc_param.lowres_str, 0),
+ OPT_STRING("skiploopfilter", lavc_param.skip_loop_filter_str, 0),
+ OPT_STRING("skipidct", lavc_param.skip_idct_str, 0),
+ OPT_STRING("skipframe", lavc_param.skip_frame_str, 0),
+ OPT_INTRANGE("threads", lavc_param.threads, 0, 1, 8),
+ OPT_FLAG_CONSTANTS("bitexact", lavc_param.bitexact, 0, 0, CODEC_FLAG_BITEXACT),
+ OPT_STRING("o", lavc_param.avopt, 0),
{NULL, NULL, 0, 0, 0, 0, NULL}
};
@@ -166,97 +151,32 @@ static int control(sh_video_t *sh, int cmd, void *arg, ...){
case VDCTRL_RESYNC_STREAM:
avcodec_flush_buffers(avctx);
return CONTROL_TRUE;
- case VDCTRL_QUERY_UNSEEN_FRAMES:
- return avctx->has_b_frames + 10;
- }
- return CONTROL_UNKNOWN;
-}
-
-static void mp_msp_av_log_callback(void *ptr, int level, const char *fmt,
- va_list vl)
-{
- static int print_prefix=1;
- AVClass *avc= ptr ? *(AVClass **)ptr : NULL;
- int type= MSGT_FIXME;
- int mp_level;
- char buf[256];
-
- switch(level){
- case AV_LOG_VERBOSE: mp_level = MSGL_V ; break;
- case AV_LOG_DEBUG: mp_level= MSGL_V ; break;
- case AV_LOG_INFO : mp_level= MSGL_INFO; break;
- case AV_LOG_ERROR: mp_level= MSGL_ERR ; break;
- default : mp_level= MSGL_ERR ; break;
- }
-
- if (!mp_msg_test(type, mp_level)) return;
-
- if(ptr){
- if(!strcmp(avc->class_name, "AVCodecContext")){
- AVCodecContext *s= ptr;
- if(s->codec){
- if(s->codec->type == CODEC_TYPE_AUDIO){
- if(s->codec->decode)
- type= MSGT_DECAUDIO;
- }else if(s->codec->type == CODEC_TYPE_VIDEO){
- if(s->codec->decode)
- type= MSGT_DECVIDEO;
- }
- //FIXME subtitles, encoders (what msgt for them? there is no appropriate ...)
- }
- }else if(!strcmp(avc->class_name, "AVFormatContext")){
-#if 0 //needs libavformat include FIXME iam too lazy to do this cleanly, probably the whole should be moved out of this file ...
- AVFormatContext *s= ptr;
- if(s->iformat)
- type= MSGT_DEMUXER;
- else if(s->oformat)
- type= MSGT_MUXER;
+ case VDCTRL_QUERY_UNSEEN_FRAMES:;
+ int delay = avctx->has_b_frames;
+#if defined(FF_THREAD_FRAME) && LIBAVCODEC_VERSION_MAJOR <= 52 && LIBAVCODEC_VERSION_MINOR < 49
+ // FFmpeg-mt has extra delay when using frame threading
+ // In newer versions that is included in has_b_frames
+ if (avctx->thread_type & FF_THREAD_FRAME)
+ delay += avctx->thread_count - 1;
#endif
- }
- }
-
- if(print_prefix && avc) {
- mp_msg(type, mp_level, "[%s @ %p]", avc->item_name(ptr), avc);
- }
-
- print_prefix= strchr(fmt, '\n') != NULL;
- vsnprintf(buf, sizeof(buf), fmt, vl);
- mp_msg(type, mp_level, buf);
-}
-
-static void set_format_params(struct AVCodecContext *avctx, enum PixelFormat fmt){
- int imgfmt;
- if (fmt == PIX_FMT_NONE)
- return;
- imgfmt = pixfmt2imgfmt(fmt);
- if (IMGFMT_IS_XVMC(imgfmt) || IMGFMT_IS_VDPAU(imgfmt)) {
- sh_video_t *sh = avctx->opaque;
- vd_ffmpeg_ctx *ctx = sh->context;
- ctx->do_dr1 = 1;
- ctx->do_slices = 1;
- avctx->thread_count = 1;
- avctx->get_buffer = get_buffer;
- avctx->release_buffer = release_buffer;
- avctx->reget_buffer = get_buffer;
- avctx->draw_horiz_band = draw_slice;
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_XVMCAcceleratedMPEG2);
- avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
+ return delay + 10;
}
+ return CONTROL_UNKNOWN;
}
// init driver
static int init(sh_video_t *sh){
+ struct lavc_param *lavc_param = &sh->opts->lavc_param;
AVCodecContext *avctx;
vd_ffmpeg_ctx *ctx;
AVCodec *lavc_codec;
int lowres_w=0;
- int do_vis_debug= lavc_param_vismv || (lavc_param_debug&(FF_DEBUG_VIS_MB_TYPE|FF_DEBUG_VIS_QP));
+ int do_vis_debug= lavc_param->vismv || (lavc_param->debug&(FF_DEBUG_VIS_MB_TYPE|FF_DEBUG_VIS_QP));
if(!avcodec_initialized){
avcodec_init();
avcodec_register_all();
avcodec_initialized=1;
- av_log_set_callback(mp_msp_av_log_callback);
}
ctx = sh->context = malloc(sizeof(vd_ffmpeg_ctx));
@@ -266,12 +186,12 @@ static int init(sh_video_t *sh){
lavc_codec = (AVCodec *)avcodec_find_decoder_by_name(sh->codec->dll);
if(!lavc_codec){
- mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_MissingLAVCcodec, sh->codec->dll);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Cannot find codec '%s' in libavcodec...\n", sh->codec->dll);
uninit(sh);
return 0;
}
- if(vd_use_slices && (lavc_codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND) && !do_vis_debug)
+ if(sh->opts->vd_use_slices && (lavc_codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND) && !do_vis_debug)
ctx->do_slices=1;
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)
@@ -286,19 +206,32 @@ static int init(sh_video_t *sh){
avctx->codec_type = CODEC_TYPE_VIDEO;
avctx->codec_id = lavc_codec->id;
-#if CONFIG_VDPAU
- if(lavc_codec->capabilities & CODEC_CAP_HWACCEL_VDPAU){
- avctx->get_format = get_format;
+ if (lavc_codec->capabilities & CODEC_CAP_HWACCEL // XvMC
+ || lavc_codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) {
+ ctx->do_dr1 = true;
+ ctx->do_slices = true;
+ lavc_param->threads = 1;
+ avctx->get_format = get_format;
+ avctx->get_buffer = get_buffer;
+ avctx->release_buffer = release_buffer;
+ avctx->reget_buffer = get_buffer;
+ avctx->draw_horiz_band = draw_slice;
+ if (lavc_codec->capabilities & CODEC_CAP_HWACCEL)
+ mp_msg(MSGT_DECVIDEO, MSGL_V, "[VD_FFMPEG] XVMC-accelerated "
+ "MPEG-2.\n");
+ if (lavc_codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)
+ mp_msg(MSGT_DECVIDEO, MSGL_V, "[VD_FFMPEG] VDPAU hardware "
+ "decoding.\n");
+ avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
}
-#endif /* CONFIG_VDPAU */
-#if CONFIG_XVMC
- if(lavc_codec->capabilities & CODEC_CAP_HWACCEL){
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_XVMCAcceleratedCodec);
- avctx->get_format= get_format;//for now only this decoder will use it
- // HACK around badly placed checks in mpeg_mc_decode_init
- set_format_params(avctx, PIX_FMT_XVMC_MPEG2_IDCT);
+
+ /* Our get_buffer and draw_horiz_band callbacks are not safe to call
+ * from other threads. */
+ if (lavc_param->threads > 1) {
+ ctx->do_dr1 = false;
+ ctx->do_slices = false;
}
-#endif /* CONFIG_XVMC */
+
if(ctx->do_dr1){
avctx->flags|= CODEC_FLAG_EMU_EDGE;
avctx->get_buffer= get_buffer;
@@ -306,38 +239,38 @@ static int init(sh_video_t *sh){
avctx->reget_buffer= get_buffer;
}
- avctx->flags|= lavc_param_bitexact;
+ avctx->flags|= lavc_param->bitexact;
avctx->width = sh->disp_w;
avctx->height= sh->disp_h;
- avctx->workaround_bugs= lavc_param_workaround_bugs;
- avctx->error_recognition= lavc_param_error_resilience;
- if(lavc_param_gray) avctx->flags|= CODEC_FLAG_GRAY;
- avctx->flags2|= lavc_param_fast;
+ avctx->workaround_bugs= lavc_param->workaround_bugs;
+ avctx->error_recognition= lavc_param->error_resilience;
+ if(lavc_param->gray) avctx->flags|= CODEC_FLAG_GRAY;
+ 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;
- if (lavc_param_debug)
+ avctx->idct_algo= lavc_param->idct_algo;
+ avctx->error_concealment= lavc_param->error_concealment;
+ avctx->debug= lavc_param->debug;
+ if (lavc_param->debug)
av_log_set_level(AV_LOG_DEBUG);
- avctx->debug_mv= lavc_param_vismv;
- avctx->skip_top = lavc_param_skip_top;
- avctx->skip_bottom= lavc_param_skip_bottom;
- if(lavc_param_lowres_str != NULL)
+ avctx->debug_mv= lavc_param->vismv;
+ avctx->skip_top = lavc_param->skip_top;
+ avctx->skip_bottom= lavc_param->skip_bottom;
+ if(lavc_param->lowres_str != NULL)
{
- sscanf(lavc_param_lowres_str, "%d,%d", &lavc_param_lowres, &lowres_w);
- if(lavc_param_lowres < 1 || lavc_param_lowres > 16 || (lowres_w > 0 && avctx->width < lowres_w))
- lavc_param_lowres = 0;
- avctx->lowres = lavc_param_lowres;
- }
- avctx->skip_loop_filter = str2AVDiscard(lavc_param_skip_loop_filter_str);
- avctx->skip_idct = str2AVDiscard(lavc_param_skip_idct_str);
- avctx->skip_frame = str2AVDiscard(lavc_param_skip_frame_str);
-
- if(lavc_avopt){
- if(parse_avopts(avctx, lavc_avopt) < 0){
- mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Your options /%s/ look like gibberish to me pal\n", lavc_avopt);
+ sscanf(lavc_param->lowres_str, "%d,%d", &ctx->lowres, &lowres_w);
+ if(ctx->lowres < 1 || ctx->lowres > 16 || (lowres_w > 0 && avctx->width < lowres_w))
+ ctx->lowres = 0;
+ avctx->lowres = ctx->lowres;
+ }
+ avctx->skip_loop_filter = str2AVDiscard(lavc_param->skip_loop_filter_str);
+ avctx->skip_idct = str2AVDiscard(lavc_param->skip_idct_str);
+ avctx->skip_frame = str2AVDiscard(lavc_param->skip_frame_str);
+
+ if(lavc_param->avopt){
+ if(parse_avopts(avctx, lavc_param->avopt) < 0){
+ mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Your options /%s/ look like gibberish to me pal\n", lavc_param->avopt);
uninit(sh);
return 0;
}
@@ -429,17 +362,14 @@ static int init(sh_video_t *sh){
if(sh->bih)
avctx->bits_per_coded_sample= sh->bih->biBitCount;
- if(lavc_param_threads > 1)
- avcodec_thread_init(avctx, lavc_param_threads);
+ if(lavc_param->threads > 1)
+ avcodec_thread_init(avctx, lavc_param->threads);
/* open it */
if (avcodec_open(avctx, lavc_codec) < 0) {
- mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_CantOpenCodec);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not open codec.\n");
uninit(sh);
return 0;
}
- // this is necessary in case get_format was never called and init_vo is
- // too late e.g. for H.264 VDPAU
- set_format_params(avctx, avctx->pix_fmt);
mp_msg(MSGT_DECVIDEO, MSGL_V, "INFO: libavcodec init OK!\n");
return 1; //mpcodecs_config_vo(sh, sh->disp_w, sh->disp_h, IMGFMT_YV12);
}
@@ -449,12 +379,12 @@ static void uninit(sh_video_t *sh){
vd_ffmpeg_ctx *ctx = sh->context;
AVCodecContext *avctx = ctx->avctx;
- if(lavc_param_vstats){
+ if(sh->opts->lavc_param.vstats){
int i;
for(i=1; i<32; i++){
mp_msg(MSGT_DECVIDEO, MSGL_INFO, "QP: %d, count: %d\n", i, ctx->qp_stat[i]);
}
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_ArithmeticMeanOfQP,
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "[VD_FFMPEG] Arithmetic mean of QP: %2.4f, Harmonic mean of QP: %2.4f\n",
ctx->qp_sum / avctx->coded_frame->coded_picture_number,
1.0/(ctx->inv_qp_sum / avctx->coded_frame->coded_picture_number)
);
@@ -462,7 +392,7 @@ static void uninit(sh_video_t *sh){
if (avctx) {
if (avctx->codec && avcodec_close(avctx) < 0)
- mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_CantCloseCodec);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not close codec.\n");
av_freep(&avctx->extradata);
av_freep(&avctx->palctrl);
@@ -476,15 +406,16 @@ static void uninit(sh_video_t *sh){
}
static void draw_slice(struct AVCodecContext *s,
- const AVFrame *src, int offset[4],
- int y, int type, int height){
+ const AVFrame *src, int offset[4],
+ int y, int type, int height){
sh_video_t *sh = s->opaque;
uint8_t *source[MP_MAX_PLANES]= {src->data[0] + offset[0], src->data[1] + offset[1], src->data[2] + offset[2]};
int strides[MP_MAX_PLANES] = {src->linesize[0], src->linesize[1], src->linesize[2]};
#if 0
int start=0, i;
int width= s->width;
- int skip_stride= ((width<<lavc_param_lowres)+15)>>4;
+ vd_ffmpeg_ctx *ctx = sh->context;
+ int skip_stride= ((width << ctx->lowres)+15)>>4;
uint8_t *skip= &s->coded_frame->mbskip_table[(y>>4)*skip_stride];
int threshold= s->coded_frame->age;
if(s->pict_type!=B_TYPE){
@@ -533,8 +464,8 @@ static int init_vo(sh_video_t *sh, enum PixelFormat pix_fmt){
// if sh->ImageDesc is non-NULL, it means we decode QuickTime(tm) video.
// use dimensions from BIH to avoid black borders at the right and bottom.
if (sh->bih && sh->ImageDesc) {
- width = sh->bih->biWidth>>lavc_param_lowres;
- height = sh->bih->biHeight>>lavc_param_lowres;
+ width = sh->bih->biWidth >> ctx->lowres;
+ height = sh->bih->biHeight >> ctx->lowres;
}
// it is possible another vo buffers to be used after vo config()
@@ -545,9 +476,6 @@ static int init_vo(sh_video_t *sh, enum PixelFormat pix_fmt){
pix_fmt != ctx->pix_fmt ||
!ctx->vo_initialized)
{
- // this is a special-case HACK for MPEG-1/2 VDPAU that uses neither get_format nor
- // sets the value correctly in avcodec_open.
- set_format_params(avctx, avctx->pix_fmt);
mp_msg(MSGT_DECVIDEO, MSGL_V, "[ffmpeg] aspect_ratio: %f\n", aspect);
if (sh->aspect == 0 ||
av_cmp_q(avctx->sample_aspect_ratio,
@@ -615,7 +543,7 @@ static int get_buffer(AVCodecContext *avctx, AVFrame *pic){
} else
if (!pic->buffer_hints) {
if(ctx->b_count>1 || ctx->ip_count>2){
- mp_msg(MSGT_DECVIDEO, MSGL_WARN, MSGTR_MPCODECS_DRIFailure);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "[VD_FFMPEG] DRI failure.\n");
ctx->do_dr1=0; //FIXME
avctx->get_buffer= avcodec_default_get_buffer;
@@ -650,13 +578,13 @@ static int get_buffer(AVCodecContext *avctx, AVFrame *pic){
struct xvmc_pix_fmt *render = mpi->priv; //same as data[2]
avctx->draw_horiz_band= draw_slice;
if(!avctx->xvmc_acceleration) {
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_McGetBufferShouldWorkOnlyWithXVMC);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "[VD_FFMPEG] The mc_get_buffer should work only with XVMC acceleration!!");
assert(0);
exit(1);
// return -1;//!!fixme check error conditions in ffmpeg
}
if(!(mpi->flags & MP_IMGFLAG_DIRECT)) {
- mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_MPCODECS_OnlyBuffersAllocatedByVoXvmcAllowed);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "[VD_FFMPEG] Only buffers allocated by vo_xvmc allowed.\n");
assert(0);
exit(1);
// return -1;//!!fixme check error conditions in ffmpeg
@@ -723,6 +651,13 @@ else
ctx->b_age=1;
}
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;
}
@@ -779,8 +714,7 @@ typedef struct dp_hdr_s {
uint32_t chunktab; // offset to chunk offset array
} dp_hdr_t;
-static void swap_palette(void *pal)
-{
+static void swap_palette(void *pal) {
int i;
uint32_t *p = pal;
for (i = 0; i < AVPALETTE_COUNT; i++)
@@ -788,12 +722,15 @@ static void swap_palette(void *pal)
}
// decode a frame
-static mp_image_t *decode(sh_video_t *sh, void *data, int len, int flags){
+static struct mp_image *decode(struct sh_video *sh, void *data, int len,
+ int flags, double *reordered_pts)
+{
int got_picture=0;
int ret;
vd_ffmpeg_ctx *ctx = sh->context;
AVFrame *pic= ctx->pic;
AVCodecContext *avctx = ctx->avctx;
+ struct lavc_param *lavc_param = &sh->opts->lavc_param;
mp_image_t *mpi=NULL;
int dr1= ctx->do_dr1;
AVPacket pkt;
@@ -822,13 +759,16 @@ static mp_image_t *decode(sh_video_t *sh, void *data, int len, int flags){
pkt.size = len;
// HACK: make PNGs decode normally instead of as CorePNG delta frames
pkt.flags = PKT_FLAG_KEY;
+ // The avcodec opaque field stupidly supports only int64_t type
+ *(double *)&avctx->reordered_opaque = *reordered_pts;
ret = avcodec_decode_video2(avctx, pic, &got_picture, &pkt);
+ *reordered_pts = *(double *)&pic->reordered_opaque;
dr1= ctx->do_dr1;
if(ret<0) mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Error while decoding frame!\n");
//printf("repeat: %d\n", pic->repeat_pict);
//-- vstats generation
- while(lavc_param_vstats){ // always one time loop
+ while(lavc_param->vstats){ // always one time loop
static FILE *fvstats=NULL;
char filename[20];
static long long int all_len=0;
@@ -847,7 +787,7 @@ static mp_image_t *decode(sh_video_t *sh, void *data, int len, int flags){
fvstats = fopen(filename, "w");
if(!fvstats) {
perror("fopen");
- lavc_param_vstats=0; // disable block
+ lavc_param->vstats=0; // disable block
break;
/*exit(1);*/
}
@@ -856,8 +796,8 @@ static mp_image_t *decode(sh_video_t *sh, void *data, int len, int flags){
// average MB quantizer
{
int x, y;
- int w = ((avctx->width << lavc_param_lowres)+15) >> 4;
- int h = ((avctx->height << lavc_param_lowres)+15) >> 4;
+ int w = ((avctx->width << ctx->lowres)+15) >> 4;
+ int h = ((avctx->height << ctx->lowres)+15) >> 4;
int8_t *q = pic->qscale_table;
for(y = 0; y < h; y++) {
for(x = 0; x < w; x++)
@@ -912,7 +852,7 @@ static mp_image_t *decode(sh_video_t *sh, void *data, int len, int flags){
mpi=mpcodecs_get_image(sh, MP_IMGTYPE_EXPORT, MP_IMGFLAG_PRESERVE,
avctx->width, avctx->height);
if(!mpi){ // temporary!
- mp_msg(MSGT_DECVIDEO, MSGL_WARN, MSGTR_MPCODECS_CouldntAllocateImageForCodec);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "[VD_FFMPEG] Couldn't allocate image for codec.\n");
return NULL;
}
@@ -954,7 +894,6 @@ static mp_image_t *decode(sh_video_t *sh, void *data, int len, int flags){
return mpi;
}
-#if CONFIG_XVMC || CONFIG_VDPAU
static enum PixelFormat get_format(struct AVCodecContext *avctx,
const enum PixelFormat *fmt){
enum PixelFormat selected_format;
@@ -965,13 +904,19 @@ static enum PixelFormat get_format(struct AVCodecContext *avctx,
for(i=0;fmt[i]!=PIX_FMT_NONE;i++){
imgfmt = pixfmt2imgfmt(fmt[i]);
if(!IMGFMT_IS_XVMC(imgfmt) && !IMGFMT_IS_VDPAU(imgfmt)) continue;
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_TryingPixfmt, i);
+ mp_msg(MSGT_DECVIDEO, MSGL_V, "[VD_FFMPEG] Trying pixfmt=%d.\n", i);
if(init_vo(sh, fmt[i]) >= 0) {
break;
}
}
selected_format = fmt[i];
- set_format_params(avctx, selected_format);
return selected_format;
}
-#endif /* CONFIG_XVMC || CONFIG_VDPAU */
+
+const struct vd_functions mpcodecs_vd_ffmpeg = {
+ .info = &info,
+ .init = init,
+ .uninit = uninit,
+ .control = control,
+ .decode2 = decode
+};