int vs_setup_video_rendering ( lw_video_output_handler_t *lw_vohp, AVCodecContext *ctx, VSVideoInfo *vi, VSMap *out, int width, int height ) { vs_video_output_handler_t *vs_vohp = (vs_video_output_handler_t *)lw_vohp->private_handler; const VSAPI *vsapi = vs_vohp->vsapi; enum AVPixelFormat output_pixel_format; int enable_scaler; if( determine_colorspace_conversion( vs_vohp, ctx->pix_fmt, &output_pixel_format, &enable_scaler ) ) { set_error_on_init( out, vsapi, "lsmas: %s is not supported", av_get_pix_fmt_name( ctx->pix_fmt ) ); return -1; } vs_vohp->direct_rendering &= vs_check_dr_available( ctx, ctx->pix_fmt ); int (*dr_get_buffer)( struct AVCodecContext *, AVFrame *, int ) = vs_vohp->direct_rendering ? vs_video_get_buffer : NULL; setup_video_rendering( lw_vohp, enable_scaler, SWS_FAST_BILINEAR, width, height, output_pixel_format, ctx, dr_get_buffer ); if( vs_vohp->variable_info ) { vi->format = NULL; vi->width = 0; vi->height = 0; /* Unused */ //lw_vohp->output_width = 0; //lw_vohp->output_height = 0; } else { vi->format = vsapi->getFormatPreset( vs_vohp->vs_output_pixel_format, vs_vohp->core ); vi->width = lw_vohp->output_width; vi->height = lw_vohp->output_height; vs_vohp->background_frame = vsapi->newVideoFrame( vi->format, vi->width, vi->height, NULL, vs_vohp->core ); if( !vs_vohp->background_frame ) { set_error_on_init( out, vsapi, "lsmas: failed to allocate memory for the background black frame data." ); return -1; } vs_vohp->make_black_background( vs_vohp->background_frame, vsapi ); } return 0; }
func_get_buffer_t *setup_video_rendering ( lw_video_output_handler_t *lw_vohp, AVCodecContext *ctx, VSVideoInfo *vi, int width, int height ) { vs_video_output_handler_t *vs_vohp = (vs_video_output_handler_t *)lw_vohp->private_handler; vs_vohp->direct_rendering &= vs_check_dr_available( ctx, ctx->pix_fmt ); if( vs_vohp->variable_info ) { vi->format = NULL; vi->width = 0; vi->height = 0; } else { const VSAPI *vsapi = vs_vohp->vsapi; vi->format = vsapi->getFormatPreset( vs_vohp->vs_output_pixel_format, vs_vohp->core ); vi->width = width; vi->height = height; if( vs_vohp->direct_rendering ) { /* Align output width and height for direct rendering. */ int linesize_align[AV_NUM_DATA_POINTERS]; enum AVPixelFormat input_pixel_format = ctx->pix_fmt; ctx->pix_fmt = lw_vohp->scaler.output_pixel_format; avcodec_align_dimensions2( ctx, &vi->width, &vi->height, linesize_align ); ctx->pix_fmt = input_pixel_format; } vs_vohp->background_frame = vsapi->newVideoFrame( vi->format, vi->width, vi->height, NULL, vs_vohp->core ); if( !vs_vohp->background_frame ) return NULL; vs_vohp->make_black_background( vs_vohp->background_frame, vsapi ); } lw_vohp->output_width = vi->width; lw_vohp->output_height = vi->height; /* Set up custom get_buffer() for direct rendering if available. */ if( vs_vohp->direct_rendering ) { ctx->get_buffer2 = vs_video_get_buffer; ctx->opaque = lw_vohp; ctx->flags |= CODEC_FLAG_EMU_EDGE; } return ctx->get_buffer2; }
static int vs_video_get_buffer ( AVCodecContext *ctx, AVFrame *av_frame, int flags ) { av_frame->opaque = NULL; lw_video_output_handler_t *lw_vohp = (lw_video_output_handler_t *)ctx->opaque; vs_video_output_handler_t *vs_vohp = (vs_video_output_handler_t *)lw_vohp->private_handler; enum AVPixelFormat pix_fmt = av_frame->format; avoid_yuv_scale_conversion( &pix_fmt ); av_frame->format = pix_fmt; /* Don't use AV_PIX_FMT_YUVJ*. */ if( (!vs_vohp->variable_info && lw_vohp->scaler.output_pixel_format != pix_fmt) || !vs_check_dr_available( ctx, pix_fmt ) ) return avcodec_default_get_buffer2( ctx, av_frame, flags ); /* New VapourSynth video frame buffer. */ vs_video_buffer_handler_t *vs_vbhp = malloc( sizeof(vs_video_buffer_handler_t) ); if( !vs_vbhp ) { av_frame_unref( av_frame ); return AVERROR( ENOMEM ); } av_frame->opaque = vs_vbhp; avcodec_align_dimensions2( ctx, &av_frame->width, &av_frame->height, av_frame->linesize ); VSFrameRef *vs_frame_buffer = new_output_video_frame( vs_vohp, av_frame, NULL, NULL, 0, vs_vohp->frame_ctx, vs_vohp->core, vs_vohp->vsapi ); if( !vs_frame_buffer ) { free( vs_vbhp ); av_frame_unref( av_frame ); return AVERROR( ENOMEM ); } vs_vbhp->vs_frame_buffer = vs_frame_buffer; vs_vbhp->vsapi = vs_vohp->vsapi; /* Create frame buffers for the decoder. * The callback vs_video_release_buffer_handler() shall be called when no reference to the video buffer handler is present. * The callback vs_video_unref_buffer_handler() decrements the reference-counter by 1. */ memset( av_frame->buf, 0, sizeof(av_frame->buf) ); memset( av_frame->data, 0, sizeof(av_frame->data) ); memset( av_frame->linesize, 0, sizeof(av_frame->linesize) ); AVBufferRef *vs_buffer_handler = av_buffer_create( NULL, 0, vs_video_release_buffer_handler, vs_vbhp, 0 ); if( !vs_buffer_handler ) { vs_video_release_buffer_handler( vs_vbhp, NULL ); av_frame_unref( av_frame ); return AVERROR( ENOMEM ); } vs_vohp->component_reorder = get_component_reorder( pix_fmt ); for( int i = 0; i < 3; i++ ) if( vs_create_plane_buffer( vs_vbhp, vs_buffer_handler, av_frame, i, vs_vohp->component_reorder[i] ) < 0 ) goto fail; /* Here, a variable 'vs_buffer_handler' itself is not referenced by any pointer. */ av_buffer_unref( &vs_buffer_handler ); av_frame->nb_extended_buf = 0; av_frame->extended_data = av_frame->data; return 0; fail: av_frame_unref( av_frame ); av_buffer_unref( &vs_buffer_handler ); return AVERROR( ENOMEM ); }