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 + -
显示快捷键?