bool VideoDecoderVDAPrivate::setup(AVCodecContext *avctx) { const int w = codedWidth(avctx); const int h = codedHeight(avctx); if (hw_ctx.width == w && hw_ctx.height == h && hw_ctx.decoder) { avctx->hwaccel_context = &hw_ctx; return true; } if (hw_ctx.decoder) { ff_vda_destroy_decoder(&hw_ctx); releaseUSWC(); } else { memset(&hw_ctx, 0, sizeof(hw_ctx)); hw_ctx.format = 'avc1'; //fourcc hw_ctx.cv_pix_fmt_type = out_fmt; // has the same value as cv pixel format } /* Setup the libavcodec hardware context */ hw_ctx.width = w; hw_ctx.height = h; width = avctx->width; // not necessary. set in decode() height = avctx->height; avctx->hwaccel_context = NULL; /* create the decoder */ int status = ff_vda_create_decoder(&hw_ctx, codec_ctx->extradata, codec_ctx->extradata_size); if (status) { qWarning("Failed to create decoder (%i): %s", status, vda_err_str(status)); return false; } avctx->hwaccel_context = &hw_ctx; initUSWC(hw_ctx.width); qDebug("VDA decoder created"); return true; }
static int Setup( vlc_va_t *p_external, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma, int i_width, int i_height ) { vlc_va_vda_t *p_va = vlc_va_vda_Get( p_external ); if( p_va->hw_ctx.width == i_width && p_va->hw_ctx.height == i_height && p_va->hw_ctx.decoder ) { *pp_hw_ctx = &p_va->hw_ctx; *pi_chroma = p_va->i_chroma; return VLC_SUCCESS; } if( p_va->hw_ctx.decoder ) { ff_vda_destroy_decoder( &p_va->hw_ctx ); goto ok; } memset( &p_va->hw_ctx, 0, sizeof(p_va->hw_ctx) ); p_va->hw_ctx.width = i_width; p_va->hw_ctx.height = i_height; p_va->hw_ctx.format = 'avc1'; int i_pix_fmt = var_CreateGetInteger( p_va->p_log, "avcodec-vda-pix-fmt" ); switch( i_pix_fmt ) { case 1 : p_va->hw_ctx.cv_pix_fmt_type = kCVPixelFormatType_422YpCbCr8; p_va->i_chroma = VLC_CODEC_UYVY; break; case 0 : default : p_va->hw_ctx.cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8Planar; p_va->i_chroma = VLC_CODEC_I420; CopyInitCache( &p_va->image_cache, i_width ); } ok: /* Setup the ffmpeg hardware context */ *pp_hw_ctx = &p_va->hw_ctx; *pi_chroma = p_va->i_chroma; /* create the decoder */ int status = ff_vda_create_decoder( &p_va->hw_ctx, p_va->p_extradata, p_va->i_extradata ); if( status ) { msg_Err( p_va->p_log, "Failed to create the decoder : %i", status ); return VLC_EGENERIC; } return VLC_SUCCESS; }
static av_cold int vdadec_init(AVCodecContext *avctx) { VDADecoderContext *ctx = avctx->priv_data; struct vda_context *vda_ctx = &ctx->vda_ctx; OSStatus status; int ret, i; ctx->h264_initialized = 0; /* init pix_fmts of codec */ if (!ff_h264_vda_decoder.pix_fmts) { if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_7) ff_h264_vda_decoder.pix_fmts = vda_pixfmts_prior_10_7; else ff_h264_vda_decoder.pix_fmts = vda_pixfmts; } /* init vda */ memset(vda_ctx, 0, sizeof(struct vda_context)); vda_ctx->width = avctx->width; vda_ctx->height = avctx->height; vda_ctx->format = 'avc1'; vda_ctx->use_sync_decoding = 1; vda_ctx->use_ref_buffer = 1; ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts); switch (ctx->pix_fmt) { case AV_PIX_FMT_UYVY422: vda_ctx->cv_pix_fmt_type = '2vuy'; break; case AV_PIX_FMT_YUYV422: vda_ctx->cv_pix_fmt_type = 'yuvs'; break; case AV_PIX_FMT_NV12: vda_ctx->cv_pix_fmt_type = '420v'; break; case AV_PIX_FMT_YUV420P: vda_ctx->cv_pix_fmt_type = 'y420'; break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n", avctx->pix_fmt); goto failed; } status = ff_vda_create_decoder(vda_ctx, avctx->extradata, avctx->extradata_size); if (status != kVDADecoderNoErr) { av_log(avctx, AV_LOG_ERROR, "Failed to init VDA decoder: %d.\n", status); goto failed; } /* init H.264 decoder */ set_context(avctx); ret = ff_h264_decoder.init(avctx); restore_context(avctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 decoder.\n"); goto failed; } ctx->h264_initialized = 1; for (i = 0; i < MAX_SPS_COUNT; i++) { const SPS *sps = (const SPS*)ctx->h264ctx.ps.sps_list[i]->data; if (sps && (sps->bit_depth_luma != 8 || sps->chroma_format_idc == 2 || sps->chroma_format_idc == 3)) { av_log(avctx, AV_LOG_ERROR, "Format is not supported.\n"); goto failed; } } return 0; failed: vdadec_close(avctx); return -1; }
static int init_vda_decoder(struct lavc_ctx *ctx) { struct priv *p = ctx->hwdec_priv; if (p->vda_ctx.decoder) ff_vda_destroy_decoder(&p->vda_ctx); const struct profile_entry *pe = find_codec(ctx->avctx->codec_id, ctx->avctx->profile); p->vda_ctx = (struct vda_context) { .width = ctx->avctx->width, .height = ctx->avctx->height, .format = pe->vda_codec, // equals to k2vuyPixelFormat (= YUY2/UYVY) .cv_pix_fmt_type = kCVPixelFormatType_422YpCbCr8, #if HAVE_VDA_LIBAVCODEC_REFCOUNTING .use_ref_buffer = 1, #endif // use_ref_buffer is 1 in ffmpeg (while libav doesn't support this // feature). This means that in the libav case, libavcodec returns us // a CVPixelBuffer with refcount=1 AND hands over ownership of that // reference. // This is slightly different from a typical refcounted situation // where the API would return something that we need to to retain // for it to stay around (ffmpeg behaves like expected when using // use_ref_buffer = 1). // If mpv doesn't properly free CVPixelBufferRefs that are no longer // used, the wrapped IOSurface ids increase monotonically hinting at // a leaking of both CVPixelBuffers and IOSurfaces. }; int status = ff_vda_create_decoder( &p->vda_ctx, ctx->avctx->extradata, ctx->avctx->extradata_size); if (status) { print_vda_error(ctx->log, MSGL_ERR, "failed to init VDA decoder", status); return -1; } return 0; } static int init(struct lavc_ctx *ctx) { struct priv *p = talloc_zero(NULL, struct priv); ctx->hwdec_priv = p; ctx->avctx->hwaccel_context = &p->vda_ctx; return 0; } static void uninit(struct lavc_ctx *ctx) { struct priv *p = ctx->hwdec_priv; if (p->vda_ctx.decoder) ff_vda_destroy_decoder(&p->vda_ctx); } static void cv_retain(void *pbuf) { CVPixelBufferRetain((CVPixelBufferRef)pbuf); }
static av_cold int vdadec_init(AVCodecContext *avctx) { VDADecoderContext *ctx = avctx->priv_data; struct vda_context *vda_ctx = &ctx->vda_ctx; OSStatus status; int ret; ctx->h264_initialized = 0; /* init pix_fmts of codec */ if (!ff_h264_vda_decoder.pix_fmts) { if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_7) ff_h264_vda_decoder.pix_fmts = vda_pixfmts_prior_10_7; else ff_h264_vda_decoder.pix_fmts = vda_pixfmts; } /* init vda */ memset(vda_ctx, 0, sizeof(struct vda_context)); vda_ctx->width = avctx->width; vda_ctx->height = avctx->height; vda_ctx->format = 'avc1'; vda_ctx->use_sync_decoding = 1; vda_ctx->use_ref_buffer = 1; ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts); switch (ctx->pix_fmt) { case AV_PIX_FMT_UYVY422: vda_ctx->cv_pix_fmt_type = '2vuy'; break; case AV_PIX_FMT_YUYV422: vda_ctx->cv_pix_fmt_type = 'yuvs'; break; case AV_PIX_FMT_NV12: vda_ctx->cv_pix_fmt_type = '420v'; break; case AV_PIX_FMT_YUV420P: vda_ctx->cv_pix_fmt_type = 'y420'; break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n", avctx->pix_fmt); goto failed; } status = ff_vda_create_decoder(vda_ctx, avctx->extradata, avctx->extradata_size); if (status != kVDADecoderNoErr) { av_log(avctx, AV_LOG_ERROR, "Failed to init VDA decoder: %d.\n", status); goto failed; } avctx->hwaccel_context = vda_ctx; /* changes callback functions */ avctx->get_format = get_format; avctx->get_buffer2 = get_buffer2; #if FF_API_GET_BUFFER // force the old get_buffer to be empty avctx->get_buffer = NULL; #endif /* init H.264 decoder */ ret = ff_h264_decoder.init(avctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 decoder.\n"); goto failed; } ctx->h264_initialized = 1; return 0; failed: vdadec_close(avctx); return -1; }
static int Setup( vlc_va_t *va, AVCodecContext *avctx, vlc_fourcc_t *pi_chroma ) { vlc_va_vda_t *p_vda = vlc_va_vda_Get( va ); if( p_vda->hw_ctx.width == avctx->coded_width && p_vda->hw_ctx.height == avctx->coded_height && p_vda->hw_ctx.decoder ) { avctx->hwaccel_context = &p_vda->hw_ctx; *pi_chroma = p_vda->i_chroma; return VLC_SUCCESS; } if( p_vda->hw_ctx.decoder ) { ff_vda_destroy_decoder( &p_vda->hw_ctx ); goto ok; } memset( &p_vda->hw_ctx, 0, sizeof(p_vda->hw_ctx) ); p_vda->hw_ctx.format = 'avc1'; p_vda->hw_ctx.use_ref_buffer = 1; int i_pix_fmt = var_CreateGetInteger( va, "avcodec-vda-pix-fmt" ); switch( i_pix_fmt ) { case 1 : p_vda->hw_ctx.cv_pix_fmt_type = kCVPixelFormatType_422YpCbCr8; p_vda->i_chroma = VLC_CODEC_UYVY; msg_Dbg(va, "using pixel format 422YpCbCr8"); break; case 0 : default : p_vda->hw_ctx.cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8Planar; p_vda->i_chroma = VLC_CODEC_I420; CopyInitCache( &p_vda->image_cache, avctx->coded_width ); msg_Dbg(va, "using pixel format 420YpCbCr8Planar"); } ok: /* Setup the libavcodec hardware context */ avctx->hwaccel_context = &p_vda->hw_ctx; *pi_chroma = p_vda->i_chroma; p_vda->hw_ctx.width = avctx->coded_width; p_vda->hw_ctx.height = avctx->coded_height; /* create the decoder */ int status = ff_vda_create_decoder( &p_vda->hw_ctx, p_vda->p_extradata, p_vda->i_extradata ); if( status ) { msg_Err( va, "Failed to create decoder: %i", status ); return VLC_EGENERIC; } else msg_Dbg( va, "VDA decoder created"); return VLC_SUCCESS; }