static int determine_colorspace_conversion ( vs_video_output_handler_t *vs_vohp, enum AVPixelFormat input_pixel_format, enum AVPixelFormat *output_pixel_format, int *enable_scaler ) { *enable_scaler = 1; avoid_yuv_scale_conversion( &input_pixel_format ); static const struct { enum AVPixelFormat av_input_pixel_format; VSPresetFormat vs_output_pixel_format; int enable_scaler; } conversion_table[] = { { AV_PIX_FMT_YUV420P, pfYUV420P8, 0 }, { AV_PIX_FMT_NV12, pfYUV420P8, 1 }, { AV_PIX_FMT_NV21, pfYUV420P8, 1 }, { AV_PIX_FMT_YUV422P, pfYUV422P8, 0 }, { AV_PIX_FMT_UYVY422, pfYUV422P8, 1 }, { AV_PIX_FMT_YUYV422, pfYUV422P8, 1 }, { AV_PIX_FMT_YUV444P, pfYUV444P8, 0 }, { AV_PIX_FMT_YUV410P, pfYUV410P8, 0 }, { AV_PIX_FMT_YUV411P, pfYUV411P8, 0 }, { AV_PIX_FMT_UYYVYY411, pfYUV411P8, 1 }, { AV_PIX_FMT_YUV440P, pfYUV440P8, 0 }, { AV_PIX_FMT_YUV420P9LE, pfYUV420P9, 0 }, { AV_PIX_FMT_YUV420P9BE, pfYUV420P9, 1 }, { AV_PIX_FMT_YUV422P9LE, pfYUV422P9, 0 }, { AV_PIX_FMT_YUV422P9BE, pfYUV422P9, 1 }, { AV_PIX_FMT_YUV444P9LE, pfYUV444P9, 0 }, { AV_PIX_FMT_YUV444P9BE, pfYUV444P9, 1 }, { AV_PIX_FMT_YUV420P10LE, pfYUV420P10, 0 }, { AV_PIX_FMT_YUV420P10BE, pfYUV420P10, 1 }, { AV_PIX_FMT_YUV422P10LE, pfYUV422P10, 0 }, { AV_PIX_FMT_YUV422P10BE, pfYUV422P10, 1 }, { AV_PIX_FMT_YUV444P10LE, pfYUV444P10, 0 }, { AV_PIX_FMT_YUV444P10BE, pfYUV444P10, 1 }, { AV_PIX_FMT_YUV420P16LE, pfYUV420P16, 0 }, { AV_PIX_FMT_YUV420P16BE, pfYUV420P16, 1 }, { AV_PIX_FMT_YUV422P16LE, pfYUV422P16, 0 }, { AV_PIX_FMT_YUV422P16BE, pfYUV422P16, 1 }, { AV_PIX_FMT_YUV444P16LE, pfYUV444P16, 0 }, { AV_PIX_FMT_YUV444P16BE, pfYUV444P16, 1 }, { AV_PIX_FMT_GBRP, pfRGB24, 0 }, { AV_PIX_FMT_GBRP9LE, pfRGB48, 0 }, { AV_PIX_FMT_GBRP9BE, pfRGB48, 1 }, { AV_PIX_FMT_GBRP10LE, pfRGB48, 0 }, { AV_PIX_FMT_GBRP10BE, pfRGB48, 1 }, { AV_PIX_FMT_GBRP16LE, pfRGB48, 0 }, { AV_PIX_FMT_GBRP16BE, pfRGB48, 1 }, { AV_PIX_FMT_BGR24, pfRGB24, 0 }, { AV_PIX_FMT_RGB24, pfRGB24, 0 }, { AV_PIX_FMT_ARGB, pfRGB24, 0 }, { AV_PIX_FMT_RGBA, pfRGB24, 0 }, { AV_PIX_FMT_ABGR, pfRGB24, 0 }, { AV_PIX_FMT_BGRA, pfRGB24, 0 }, { AV_PIX_FMT_BGR48LE, pfRGB48, 0 }, { AV_PIX_FMT_BGR48BE, pfRGB48, 1 }, { AV_PIX_FMT_NONE, pfNone, 1 } }; if( vs_vohp->variable_info || vs_vohp->vs_output_pixel_format == pfNone ) { /* Determine by input pixel format. */ for( int i = 0; conversion_table[i].vs_output_pixel_format != pfNone; i++ ) if( input_pixel_format == conversion_table[i].av_input_pixel_format ) { vs_vohp->vs_output_pixel_format = conversion_table[i].vs_output_pixel_format; *enable_scaler = conversion_table[i].enable_scaler; break; } } else { /* Determine by both input pixel format and output pixel format. */ for( int i = 0; conversion_table[i].vs_output_pixel_format != pfNone; i++ ) { if( input_pixel_format == conversion_table[i].av_input_pixel_format && vs_vohp->vs_output_pixel_format == conversion_table[i].vs_output_pixel_format ) { *enable_scaler = conversion_table[i].enable_scaler; break; } } } *output_pixel_format = *enable_scaler ? vs_to_av_output_pixel_format( vs_vohp->vs_output_pixel_format ) : input_pixel_format; vs_vohp->component_reorder = get_component_reorder( *output_pixel_format ); int av_output_flags = av_pix_fmt_desc_get( *output_pixel_format )->flags; return set_frame_maker( vs_vohp, (av_output_flags & AV_PIX_FMT_FLAG_PLANAR) && (av_output_flags & AV_PIX_FMT_FLAG_RGB) ); }
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 ); }
int determine_colorspace_conversion ( lw_video_output_handler_t *vohp, enum AVPixelFormat input_pixel_format ) { avoid_yuv_scale_conversion( &input_pixel_format ); static const struct { enum AVPixelFormat av_input_pixel_format; VSPresetFormat vs_output_pixel_format; int enable_scaler; } conversion_table[] = { { AV_PIX_FMT_YUV420P, pfYUV420P8, 0 }, { AV_PIX_FMT_NV12, pfYUV420P8, 1 }, { AV_PIX_FMT_NV21, pfYUV420P8, 1 }, { AV_PIX_FMT_YUV422P, pfYUV422P8, 0 }, { AV_PIX_FMT_UYVY422, pfYUV422P8, 1 }, { AV_PIX_FMT_YUYV422, pfYUV422P8, 1 }, { AV_PIX_FMT_YUV444P, pfYUV444P8, 0 }, { AV_PIX_FMT_YUV410P, pfYUV410P8, 0 }, { AV_PIX_FMT_YUV411P, pfYUV411P8, 0 }, { AV_PIX_FMT_UYYVYY411, pfYUV411P8, 1 }, { AV_PIX_FMT_YUV440P, pfYUV440P8, 0 }, { AV_PIX_FMT_YUV420P9LE, pfYUV420P9, 0 }, { AV_PIX_FMT_YUV420P9BE, pfYUV420P9, 1 }, { AV_PIX_FMT_YUV422P9LE, pfYUV422P9, 0 }, { AV_PIX_FMT_YUV422P9BE, pfYUV422P9, 1 }, { AV_PIX_FMT_YUV444P9LE, pfYUV444P9, 0 }, { AV_PIX_FMT_YUV444P9BE, pfYUV444P9, 1 }, { AV_PIX_FMT_YUV420P10LE, pfYUV420P10, 0 }, { AV_PIX_FMT_YUV420P10BE, pfYUV420P10, 1 }, { AV_PIX_FMT_YUV422P10LE, pfYUV422P10, 0 }, { AV_PIX_FMT_YUV422P10BE, pfYUV422P10, 1 }, { AV_PIX_FMT_YUV444P10LE, pfYUV444P10, 0 }, { AV_PIX_FMT_YUV444P10BE, pfYUV444P10, 1 }, { AV_PIX_FMT_YUV420P16LE, pfYUV420P16, 0 }, { AV_PIX_FMT_YUV420P16BE, pfYUV420P16, 1 }, { AV_PIX_FMT_YUV422P16LE, pfYUV422P16, 0 }, { AV_PIX_FMT_YUV422P16BE, pfYUV422P16, 1 }, { AV_PIX_FMT_YUV444P16LE, pfYUV444P16, 0 }, { AV_PIX_FMT_YUV444P16BE, pfYUV444P16, 1 }, { AV_PIX_FMT_BGR24, pfRGB24, 0 }, { AV_PIX_FMT_RGB24, pfRGB24, 0 }, { AV_PIX_FMT_ARGB, pfRGB24, 0 }, { AV_PIX_FMT_RGBA, pfRGB24, 0 }, { AV_PIX_FMT_ABGR, pfRGB24, 0 }, { AV_PIX_FMT_BGRA, pfRGB24, 0 }, { AV_PIX_FMT_BGR48LE, pfRGB48, 0 }, { AV_PIX_FMT_BGR48BE, pfRGB48, 1 }, { AV_PIX_FMT_NONE, pfNone, 1 } }; vs_video_output_handler_t *vs_vohp = (vs_video_output_handler_t *)vohp->private_handler; if( vs_vohp->variable_info || vs_vohp->vs_output_pixel_format == pfNone ) { /* Determine by input pixel format. */ for( int i = 0; conversion_table[i].vs_output_pixel_format != pfNone; i++ ) if( input_pixel_format == conversion_table[i].av_input_pixel_format ) { vs_vohp->vs_output_pixel_format = conversion_table[i].vs_output_pixel_format; vohp->scaler.enabled = conversion_table[i].enable_scaler; break; } } else { /* Determine by both input pixel format and output pixel format. */ int i = 0; while( conversion_table[i].vs_output_pixel_format != pfNone ) { if( input_pixel_format == conversion_table[i].av_input_pixel_format && vs_vohp->vs_output_pixel_format == conversion_table[i].vs_output_pixel_format ) { vohp->scaler.enabled = conversion_table[i].enable_scaler; break; } ++i; } if( conversion_table[i].vs_output_pixel_format == pfNone ) vohp->scaler.enabled = 1; } vohp->scaler.output_pixel_format = vohp->scaler.enabled ? vs_to_av_output_pixel_format( vs_vohp->vs_output_pixel_format ) : input_pixel_format; vs_vohp->component_reorder = get_component_reorder( vohp->scaler.output_pixel_format ); return set_frame_maker( vs_vohp ); }