static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff ) { VLC_UNUSED( p_ff ); vlc_va_vda_t *p_va = vlc_va_vda_Get( p_external ); if( !p_va->top_frame ) { msg_Dbg( p_va->p_log, "Decoder is buffering..."); return VLC_EGENERIC; } CVPixelBufferRef cv_buffer = p_va->top_frame->cv_buffer; if( p_va->hw_ctx.cv_pix_fmt_type == kCVPixelFormatType_420YpCbCr8Planar ) { if( !p_va->image_cache.buffer ) return VLC_EGENERIC; vda_Copy420YpCbCr8Planar( p_picture, cv_buffer, p_va->hw_ctx.width, p_va->hw_ctx.height, &p_va->image_cache ); } else vda_Copy422YpCbCr8( p_picture, cv_buffer ); p_picture->date = p_va->top_frame->pts; return VLC_SUCCESS; }
static int Extract( vlc_va_t *external, picture_t *p_picture, void *opaque, uint8_t *data ) { vlc_va_vda_t *p_va = vlc_va_vda_Get( external ); CVPixelBufferRef cv_buffer = ( CVPixelBufferRef )data; if( !cv_buffer ) { msg_Dbg( p_va->p_log, "Frame buffer is empty."); return VLC_EGENERIC; } if (!CVPixelBufferGetDataSize(cv_buffer) > 0) { msg_Dbg( p_va->p_log, "Empty frame buffer"); return VLC_EGENERIC; } if( p_va->hw_ctx.cv_pix_fmt_type == kCVPixelFormatType_420YpCbCr8Planar ) { if( !p_va->image_cache.buffer ) { CVPixelBufferRelease( cv_buffer ); return VLC_EGENERIC; } vda_Copy420YpCbCr8Planar( p_picture, cv_buffer, p_va->hw_ctx.width, p_va->hw_ctx.height, &p_va->image_cache ); } else vda_Copy422YpCbCr8( p_picture, cv_buffer ); (void) opaque; return VLC_SUCCESS; }
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 void Close( vlc_va_t *external ) { vlc_va_vda_t *p_va = vlc_va_vda_Get( external ); msg_Dbg(p_va->p_log, "destroying VDA decoder"); ff_vda_destroy_decoder( &p_va->hw_ctx ) ; if( p_va->hw_ctx.cv_pix_fmt_type == kCVPixelFormatType_420YpCbCr8Planar ) CopyCleanCache( &p_va->image_cache ); free( p_va ); }
static void Close( vlc_va_t *p_external ) { vlc_va_vda_t *p_va = vlc_va_vda_Get( p_external ); ff_vda_destroy_decoder( &p_va->hw_ctx ) ; if( p_va->top_frame ) ff_vda_release_vda_frame( p_va->top_frame ); if( p_va->hw_ctx.cv_pix_fmt_type == kCVPixelFormatType_420YpCbCr8Planar ) CopyCleanCache( &p_va->image_cache ); free( p_va ); }
static void Close( vlc_va_t *va, AVCodecContext *ctx ) { vlc_va_vda_t *p_vda = vlc_va_vda_Get( va ); msg_Dbg(va, "destroying VDA decoder"); ff_vda_destroy_decoder( &p_vda->hw_ctx ) ; if( p_vda->hw_ctx.cv_pix_fmt_type == kCVPixelFormatType_420YpCbCr8Planar ) CopyCleanCache( &p_vda->image_cache ); free( p_vda ); (void) ctx; }
static int Get( vlc_va_t *p_external, AVFrame *p_ff ) { vlc_va_vda_t *p_va = vlc_va_vda_Get( p_external ); if( p_va->top_frame ) ff_vda_release_vda_frame( p_va->top_frame ); p_va->top_frame = ff_vda_queue_pop( &p_va->hw_ctx ); /* */ for( int i = 0; i < 4; i++ ) { p_ff->data[i] = NULL; p_ff->linesize[i] = 0; if( i == 0 || i == 3 ) p_ff->data[i] = 1; // dummy } return VLC_SUCCESS; }
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; }