static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags) { decoder_t *dec = ctx->opaque; decoder_sys_t *sys = dec->p_sys; vlc_va_t *va = sys->p_va; if (vlc_va_Setup(va, &ctx->hwaccel_context, &dec->fmt_out.video.i_chroma, ctx->coded_width, ctx->coded_height)) { msg_Err(dec, "hardware acceleration setup failed"); return -1; } if (vlc_va_Get(va, &frame->opaque, &frame->data[0])) { msg_Err(dec, "hardware acceleration picture allocation failed"); return -1; } /* data[0] must be non-NULL for libavcodec internal checks. * data[3] actually contains the format-specific surface handle. */ frame->data[3] = frame->data[0]; frame->buf[0] = av_buffer_create(frame->data[0], 0, va->release, frame->opaque, 0); if (unlikely(frame->buf[0] == NULL)) { vlc_va_Release(va, frame->opaque, frame->data[0]); return -1; } assert(frame->data[0] != NULL); (void) flags; return 0; }
static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, picture_t *pic) { decoder_t *dec = ctx->opaque; vlc_va_t *va = dec->p_sys->p_va; if (vlc_va_Get(va, pic, &frame->data[0])) { msg_Err(dec, "hardware acceleration picture allocation failed"); picture_Release(pic); return -1; } /* data[0] must be non-NULL for libavcodec internal checks. * data[3] actually contains the format-specific surface handle. */ frame->data[3] = frame->data[0]; void (*release)(void *, uint8_t *) = va->release; if (va->release == NULL) release = lavc_ReleaseFrame; frame->buf[0] = av_buffer_create(frame->data[0], 0, release, pic, 0); if (unlikely(frame->buf[0] == NULL)) { release(pic, frame->data[0]); return -1; } frame->opaque = pic; assert(frame->data[0] != NULL); return 0; }
static int ffmpeg_va_GetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic ) { decoder_t *p_dec = (decoder_t *)p_context->opaque; decoder_sys_t *p_sys = p_dec->p_sys; vlc_va_t *p_va = p_sys->p_va; /* hwaccel_context is not present in old ffmpeg version */ if( vlc_va_Setup( p_va, &p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma, p_context->coded_width, p_context->coded_height ) ) { msg_Err( p_dec, "vlc_va_Setup failed" ); return -1; } if( vlc_va_Get( p_va, &p_ff_pic->opaque, &p_ff_pic->data[0] ) ) { msg_Err( p_dec, "vlc_va_Get failed" ); return -1; } p_ff_pic->data[3] = p_ff_pic->data[0]; p_ff_pic->type = FF_BUFFER_TYPE_USER; return 0; }
static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic ) { decoder_t *p_dec = (decoder_t *)p_context->opaque; decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; /* Set picture PTS */ ffmpeg_SetFrameBufferPts( p_dec, p_ff_pic ); /* */ p_ff_pic->opaque = NULL; if( p_sys->p_va ) { #ifdef HAVE_AVCODEC_VA /* hwaccel_context is not present in old fffmpeg version */ if( vlc_va_Setup( p_sys->p_va, &p_sys->p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma, p_sys->p_context->width, p_sys->p_context->height ) ) { msg_Err( p_dec, "vlc_va_Setup failed" ); return -1; } #else assert(0); #endif /* */ p_ff_pic->type = FF_BUFFER_TYPE_USER; /* FIXME what is that, should give good value */ p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg if( vlc_va_Get( p_sys->p_va, p_ff_pic ) ) { msg_Err( p_dec, "VaGrabSurface failed" ); return -1; } return 0; } else if( !p_sys->b_direct_rendering ) { /* Not much to do in indirect rendering mode. */ return avcodec_default_get_buffer( p_context, p_ff_pic ); } /* Some codecs set pix_fmt only after the 1st frame has been decoded, * so we need to check for direct rendering again. */ int i_width = p_sys->p_context->width; int i_height = p_sys->p_context->height; avcodec_align_dimensions( p_sys->p_context, &i_width, &i_height ); if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS || p_context->pix_fmt == PIX_FMT_PAL8 ) goto no_dr; p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma; /* Get a new picture */ p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context ); if( !p_pic ) goto no_dr; bool b_compatible = true; if( p_pic->p[0].i_pitch / p_pic->p[0].i_pixel_pitch < i_width || p_pic->p[0].i_lines < i_height ) b_compatible = false; for( int i = 0; i < p_pic->i_planes && b_compatible; i++ ) { unsigned i_align; switch( p_sys->i_codec_id ) { case CODEC_ID_SVQ1: case CODEC_ID_VP5: case CODEC_ID_VP6: case CODEC_ID_VP6F: case CODEC_ID_VP6A: i_align = 16; break; default: i_align = i == 0 ? 16 : 8; break; } if( p_pic->p[i].i_pitch % i_align ) b_compatible = false; if( (intptr_t)p_pic->p[i].p_pixels % i_align ) b_compatible = false; } if( p_context->pix_fmt == PIX_FMT_YUV422P && b_compatible ) { if( 2 * p_pic->p[1].i_pitch != p_pic->p[0].i_pitch || 2 * p_pic->p[2].i_pitch != p_pic->p[0].i_pitch ) b_compatible = false; } if( !b_compatible ) { decoder_DeletePicture( p_dec, p_pic ); goto no_dr; } if( p_sys->i_direct_rendering_used != 1 ) { msg_Dbg( p_dec, "using direct rendering" ); p_sys->i_direct_rendering_used = 1; } p_sys->p_context->draw_horiz_band = NULL; p_ff_pic->opaque = (void*)p_pic; p_ff_pic->type = FF_BUFFER_TYPE_USER; p_ff_pic->data[0] = p_pic->p[0].p_pixels; p_ff_pic->data[1] = p_pic->p[1].p_pixels; p_ff_pic->data[2] = p_pic->p[2].p_pixels; p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */ p_ff_pic->linesize[0] = p_pic->p[0].i_pitch; p_ff_pic->linesize[1] = p_pic->p[1].i_pitch; p_ff_pic->linesize[2] = p_pic->p[2].i_pitch; p_ff_pic->linesize[3] = 0; decoder_LinkPicture( p_dec, p_pic ); /* FIXME what is that, should give good value */ p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg return 0; no_dr: if( p_sys->i_direct_rendering_used != 0 ) { msg_Warn( p_dec, "disabling direct rendering" ); p_sys->i_direct_rendering_used = 0; } return avcodec_default_get_buffer( p_context, p_ff_pic ); }