/** * Callback used by libavcodec to get a frame buffer. * * It is used for direct rendering as well as to get the right PTS for each * decoded picture (even in indirect rendering mode). */ static int lavc_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags) { decoder_t *dec = ctx->opaque; decoder_sys_t *sys = dec->p_sys; picture_t *pic; for (unsigned i = 0; i < AV_NUM_DATA_POINTERS; i++) { frame->data[i] = NULL; frame->linesize[i] = 0; frame->buf[i] = NULL; } if (sys->p_va != NULL) return lavc_va_GetFrame(ctx, frame, flags); frame->opaque = NULL; if (!sys->b_direct_rendering) return avcodec_default_get_buffer2(ctx, frame, flags); /* Some codecs set pix_fmt only after the 1st frame has been decoded, * so we need to check for direct rendering again. */ wait_mt(sys); pic = lavc_dr_GetFrame(ctx, frame, flags); if (pic == NULL) { if (sys->i_direct_rendering_used != 0) { msg_Warn(dec, "disabling direct rendering"); sys->i_direct_rendering_used = 0; } post_mt(sys); return avcodec_default_get_buffer2(ctx, frame, flags); } if (sys->i_direct_rendering_used != 1) { msg_Dbg(dec, "enabling direct rendering"); sys->i_direct_rendering_used = 1; } post_mt(sys); frame->opaque = pic; static_assert(PICTURE_PLANE_MAX <= AV_NUM_DATA_POINTERS, "Oops!"); for (unsigned i = 0; i < PICTURE_PLANE_MAX; i++) { frame->data[i] = pic->p[i].p_pixels; frame->linesize[i] = pic->p[i].i_pitch; } return 0; }
/** * Callback used by libavcodec to get a frame buffer. * * It is used for direct rendering as well as to get the right PTS for each * decoded picture (even in indirect rendering mode). */ static int lavc_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags) { decoder_t *dec = ctx->opaque; decoder_sys_t *sys = dec->p_sys; picture_t *pic; for (unsigned i = 0; i < AV_NUM_DATA_POINTERS; i++) { frame->data[i] = NULL; frame->linesize[i] = 0; frame->buf[i] = NULL; } frame->opaque = NULL; wait_mt(sys); if (sys->p_va != NULL) { /* TODO: Move this to get_format(). We are screwed if it fails here. */ if (vlc_va_Setup(sys->p_va, ctx, &dec->fmt_out.video.i_chroma)) { post_mt(sys); msg_Err(dec, "hardware acceleration setup failed"); return -1; } } else if (!sys->b_direct_rendering) { post_mt(sys); return avcodec_default_get_buffer2(ctx, frame, flags); } /* The semaphore protects updates to fmt_out */ pic = ffmpeg_NewPictBuf(dec, ctx); post_mt(sys); if (pic == NULL) return -1; if (sys->p_va != NULL) return lavc_va_GetFrame(ctx, frame, pic); /* Some codecs set pix_fmt only after the 1st frame has been decoded, * so we need to check for direct rendering again. */ int ret = lavc_dr_GetFrame(ctx, frame, pic); if (ret) ret = avcodec_default_get_buffer2(ctx, frame, flags); return ret; }