vd_ffmpeg.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,079 行 · 第 1/3 页

C
1,079
字号
#include <uclib.h>#include <uclib.h>#include <assert.h>#include <time.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "libavutil/common.h"#include "libavutil/intreadwrite.h"#include "mpbswap.h"#include "vd_internal.h"static vd_info_t info = {	"FFmpeg's libavcodec codec family",	"ffmpeg",	"A'rpi",	"A'rpi, Michael, Alex",	"native codecs (http://ffmpeg.sf.net/)"};LIBVD_EXTERN(ffmpeg)#ifdef USE_LIBAVCODEC_SO#include <ffmpeg/avcodec.h>#else#include "libavcodec/avcodec.h"#endif#ifdef HAVE_XVMC#include "xvmc_render.h"#endif#undef memcpy#define memcpy uc_memcpyint avcodec_inited=0;typedef struct {    AVCodecContext *avctx;    AVFrame *pic;    enum PixelFormat pix_fmt;    int do_slices;    int do_dr1;    int vo_inited;    int best_csp;    int b_age;    int ip_age[2];    int qp_stat[32];    double qp_sum;    double inv_qp_sum;    int ip_count;    int b_count;    AVRational last_sample_aspect_ratio;} vd_ffmpeg_ctx;//#ifdef USE_LIBPOSTPROC//unsigned int lavc_pp=0;//#endif#include "m_option.h"static int get_buffer(AVCodecContext *avctx, AVFrame *pic);static void release_buffer(AVCodecContext *avctx, AVFrame *pic);#ifdef HAVE_XVMCstatic enum PixelFormat get_format(struct AVCodecContext * avctx,                                   const enum PixelFormat * pix_fmt);static int mc_get_buffer(AVCodecContext *avctx, AVFrame *pic);static void mc_release_buffer(AVCodecContext *avctx, AVFrame *pic);static void mc_render_slice(struct AVCodecContext *s,                	AVFrame *src, int offset[4],                	int y, int type, int height);#endifstatic 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;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},#ifdef CODEC_FLAG2_FAST        {"fast", &lavc_param_fast, CONF_TYPE_FLAG, 0, 0, CODEC_FLAG2_FAST, NULL},#endif	{"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},	{NULL, NULL, 0, 0, 0, 0, NULL}};static enum AVDiscard str2AVDiscard(char *str) {  if (!str)    return AVDISCARD_DEFAULT;  if (strcasecmp(str, "none") == 0)    return AVDISCARD_NONE;  if (strcasecmp(str, "default") == 0)    return AVDISCARD_DEFAULT;  if (strcasecmp(str, "nonref") == 0)    return AVDISCARD_NONREF;  if (strcasecmp(str, "bidir") == 0)    return AVDISCARD_BIDIR;  if (strcasecmp(str, "nonkey") == 0)    return AVDISCARD_NONKEY;  if (strcasecmp(str, "all") == 0)    return AVDISCARD_ALL;  mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Unknown discard value %s\n", str);  return AVDISCARD_DEFAULT;}// to set/get/query special features/parametersstatic int control(sh_video_t *sh,int cmd,void* arg,...){    vd_ffmpeg_ctx *ctx = sh->context;    AVCodecContext *avctx = ctx->avctx;    switch(cmd){    case VDCTRL_QUERY_FORMAT:        {            int format =(*((int*)arg));	    if( format == ctx->best_csp ) return CONTROL_TRUE;//supported	// possible conversions:	    switch( format ){        case IMGFMT_YV12:        case IMGFMT_IYUV:        case IMGFMT_I420:	    // "converted" using pointer/stride modification	    if(avctx->pix_fmt==PIX_FMT_YUV420P) return CONTROL_TRUE;// u/v swap	    if(avctx->pix_fmt==PIX_FMT_YUV422P && !ctx->do_dr1) return CONTROL_TRUE;// half stride	    break;#ifdef HAVE_XVMC        case IMGFMT_XVMC_IDCT_MPEG2:        case IMGFMT_XVMC_MOCO_MPEG2:            if(avctx->pix_fmt==PIX_FMT_XVMC_MPEG2_IDCT) return CONTROL_TRUE;#endif	}        return CONTROL_FALSE;        }    break;    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;}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_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;#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);}// init driverstatic int init(sh_video_t *sh){    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));    if(!avcodec_inited){      avcodec_init();      avcodec_register_all();      avcodec_inited=1;      av_log_set_callback(mp_msp_av_log_callback);   }    ctx = sh->context = malloc(sizeof(vd_ffmpeg_ctx));    if (!ctx)	return(0);    memset(ctx, 0, sizeof(vd_ffmpeg_ctx));        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);        uninit(sh);	return 0;    }    if(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)	ctx->do_dr1=1;    ctx->b_age= ctx->ip_age[0]= ctx->ip_age[1]= 256*256*256*64;    ctx->ip_count= ctx->b_count= 0;    ctx->pic = avcodec_alloc_frame();    ctx->avctx = avcodec_alloc_context();    avctx = ctx->avctx;#ifdef HAVE_XVMC#ifdef CODEC_CAP_HWACCEL    if(lavc_codec->capabilities & CODEC_CAP_HWACCEL){#else    if(lavc_codec->id == CODEC_ID_MPEG2VIDEO_XVMC){#endif /* CODEC_CAP_HWACCEL */        mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_XVMCAcceleratedCodec);        assert(ctx->do_dr1);//these are must to!        assert(ctx->do_slices); //it is (vo_)ffmpeg bug if this fails        avctx->flags|= CODEC_FLAG_EMU_EDGE;//do i need that??!!        avctx->get_format= get_format;//for now only this decoder will use it        avctx->get_buffer= mc_get_buffer;        avctx->release_buffer= mc_release_buffer;        avctx->draw_horiz_band = mc_render_slice;        avctx->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;    }else#endif /* HAVE_XVMC */    if(ctx->do_dr1){        avctx->flags|= CODEC_FLAG_EMU_EDGE;         avctx->get_buffer= get_buffer;        avctx->release_buffer= release_buffer;        avctx->reget_buffer= get_buffer;    }#ifdef CODEC_FLAG_NOT_TRUNCATED    avctx->flags|= CODEC_FLAG_NOT_TRUNCATED;#endif    avctx->flags|= lavc_param_bitexact;        avctx->width = sh->disp_w;    avctx->height= sh->disp_h;    avctx->workaround_bugs= lavc_param_workaround_bugs;    avctx->error_resilience= lavc_param_error_resilience;    if(lavc_param_gray) avctx->flags|= CODEC_FLAG_GRAY;#ifdef CODEC_FLAG2_FAST    avctx->flags2|= lavc_param_fast;#endif    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)        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)    {        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);    mp_dbg(MSGT_DECVIDEO,MSGL_DBG2,"libavcodec.size: %d x %d\n",avctx->width,avctx->height);    switch (sh->format) {    case mmioFOURCC('S','V','Q','3'):    /* SVQ3 extradata can show up as sh->ImageDesc if demux_mov is used, or       in the phony AVI header if demux_lavf is used. The first case is       handled here; the second case falls through to the next section. */	if (sh->ImageDesc) {	    avctx->extradata_size = (*(int*)sh->ImageDesc) - sizeof(int);	    avctx->extradata = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);	    memcpy(avctx->extradata, ((int*)sh->ImageDesc)+1, avctx->extradata_size);	    break;	}	/* fallthrough */    case mmioFOURCC('A','V','R','n'):    case mmioFOURCC('M','J','P','G'):    /* AVRn stores huffman table in AVI header */    /* Pegasus MJPEG stores it also in AVI header, but it uses the common       MJPG fourcc :( */	if (!sh->bih || sh->bih->biSize <= sizeof(BITMAPINFOHEADER))	    break;	avctx->flags |= CODEC_FLAG_EXTERN_HUFF;	avctx->extradata_size = sh->bih->biSize-sizeof(BITMAPINFOHEADER);	avctx->extradata = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);	memcpy(avctx->extradata, sh->bih+1, avctx->extradata_size);#if 0	{	    int x;	    uint8_t *p = avctx->extradata;	    	    for (x=0; x<avctx->extradata_size; x++)		mp_msg(MSGT_DECVIDEO, MSGL_INFO,"[%x] ", p[x]);	    mp_msg(MSGT_DECVIDEO, MSGL_INFO,"\n");	}#endif	break;    case mmioFOURCC('R', 'V', '1', '0'):    case mmioFOURCC('R', 'V', '1', '3'):    case mmioFOURCC('R', 'V', '2', '0'):

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?