/* Note: To get YUV range, must not pass avoid_yuv_scale_conversion( &ctx->pix_fmt ) before this function. */
int initialize_scaler_handler
(
    lw_video_scaler_handler_t *vshp,
    AVCodecContext            *ctx,
    int                        enabled,
    int                        flags,
    enum AVPixelFormat         output_pixel_format
)
{
    if( flags != SWS_FAST_BILINEAR )
        flags |= SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP | SWS_ACCURATE_RND | SWS_BITEXACT;
    int yuv_range = avoid_yuv_scale_conversion( &ctx->pix_fmt );
    if( ctx->color_range == AVCOL_RANGE_MPEG || ctx->color_range == AVCOL_RANGE_JPEG )
        yuv_range = (ctx->color_range == AVCOL_RANGE_JPEG);
    vshp->sws_ctx = update_scaler_configuration( NULL, flags,
                                                 ctx->width, ctx->height,
                                                 ctx->pix_fmt, output_pixel_format,
                                                 ctx->colorspace, yuv_range );
    if( !vshp->sws_ctx )
        return -1;
    vshp->enabled             = enabled;
    vshp->flags               = flags;
    vshp->input_width         = ctx->width;
    vshp->input_height        = ctx->height;
    vshp->input_pixel_format  = ctx->pix_fmt;
    vshp->output_pixel_format = output_pixel_format;
    vshp->input_colorspace    = ctx->colorspace;
    vshp->input_yuv_range     = yuv_range;
    return 0;
}
Beispiel #2
0
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 );
}
Beispiel #3
0
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) );
}
Beispiel #4
0
VSFrameRef *make_frame
(
    lw_video_output_handler_t *vohp,
    AVCodecContext            *ctx,
    AVFrame                   *av_frame
)
{
    vs_video_output_handler_t *vs_vohp = (vs_video_output_handler_t *)vohp->private_handler;
    VSFrameContext *frame_ctx = vs_vohp->frame_ctx;
    VSCore         *core      = vs_vohp->core;
    const VSAPI    *vsapi     = vs_vohp->vsapi;
    if( vs_vohp->direct_rendering && !vohp->scaler.enabled && av_frame->opaque )
    {
        /* Render from the decoder directly. */
        vs_video_buffer_handler_t *vs_vbhp = (vs_video_buffer_handler_t *)av_frame->opaque;
        return vs_vbhp ? (VSFrameRef *)vs_vbhp->vsapi->cloneFrameRef( vs_vbhp->vs_frame_buffer ) : NULL;
    }
    if( !vs_vohp->make_frame )
        return NULL;
    /* Convert pixel format if needed. We don't change the presentation resolution. */
    enum AVPixelFormat *input_pixel_format = (enum AVPixelFormat *)&av_frame->format;
    int yuv_range = avoid_yuv_scale_conversion( input_pixel_format );
    lw_video_scaler_handler_t *vshp = &vohp->scaler;
    if( !vshp->sws_ctx
     || vshp->input_width        != ctx->width
     || vshp->input_height       != ctx->height
     || vshp->input_pixel_format != *input_pixel_format
     || vshp->input_colorspace   != ctx->colorspace
     || vshp->input_yuv_range    != yuv_range )
    {
        /* Update scaler. */
        vshp->sws_ctx = update_scaler_configuration( vshp->sws_ctx, vshp->flags,
                                                     ctx->width, ctx->height,
                                                     *input_pixel_format, vshp->output_pixel_format,
                                                     ctx->colorspace, yuv_range );
        if( !vshp->sws_ctx )
        {
            if( frame_ctx )
                vsapi->setFilterError( "lsmas: failed to update scaler settings.", frame_ctx );
            return NULL;
        }
        vshp->input_width        = ctx->width;
        vshp->input_height       = ctx->height;
        vshp->input_pixel_format = *input_pixel_format;
        vshp->input_colorspace   = ctx->colorspace;
        vshp->input_yuv_range    = yuv_range;
    }
    /* Make video frame. */
    AVPicture av_picture;
    int ret = convert_av_pixel_format( vshp, ctx->width, ctx->height, av_frame, &av_picture );
    if( ret < 0 )
    {
        if( frame_ctx )
            vsapi->setFilterError( "lsmas: failed to av_image_alloc.", frame_ctx );
        return NULL;
    }
    VSFrameRef *vs_frame = new_output_video_frame( vohp, ctx->width, ctx->height, *input_pixel_format, frame_ctx, core, vsapi );
    if( vs_frame )
        vs_vohp->make_frame( &av_picture, ctx->width, ctx->height, vs_vohp->component_reorder, vs_frame, frame_ctx, vsapi );
    else if( frame_ctx )
        vsapi->setFilterError( "lsmas: failed to alloc a output video frame.", frame_ctx );
    if( ret > 0 )
        av_free( av_picture.data[0] );
    return vs_frame;
}
Beispiel #5
0
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 );
}
Beispiel #6
0
static int as_video_get_buffer
(
    AVCodecContext *ctx,
    AVFrame        *av_frame,
    int             flags
)
{
    lw_video_output_handler_t *lw_vohp = (lw_video_output_handler_t *)ctx->opaque;
    as_video_output_handler_t *as_vohp = (as_video_output_handler_t *)lw_vohp->private_handler;
    lw_video_scaler_handler_t *vshp    = &lw_vohp->scaler;
    enum AVPixelFormat pix_fmt = ctx->pix_fmt;
    avoid_yuv_scale_conversion( &pix_fmt );
    av_frame->format = pix_fmt; /* Don't use AV_PIX_FMT_YUVJ*. */
    if( vshp->output_pixel_format != pix_fmt
     || !as_check_dr_available( ctx, pix_fmt, as_vohp->stacked_format ) )
        return avcodec_default_get_buffer2( ctx, av_frame, 0 );
    /* New AviSynth video frame buffer. */
    as_video_buffer_handler_t *as_vbhp = new as_video_buffer_handler_t;
    if( !as_vbhp )
    {
        av_frame_unref( av_frame );
        return AVERROR( ENOMEM );
    }
    av_frame->opaque = as_vbhp;
    as_vbhp->as_frame_buffer = as_vohp->env->NewVideoFrame( *as_vohp->vi, 32 );
    int aligned_width  = ctx->width << (as_vohp->bitdepth_minus_8 ? 1 : 0);
    int aligned_height = ctx->height;
    avcodec_align_dimensions2( ctx, &aligned_width, &aligned_height, av_frame->linesize );
    if( lw_vohp->output_width != aligned_width || lw_vohp->output_height != aligned_height )
        as_vohp->make_black_background( as_vbhp->as_frame_buffer, as_vohp->bitdepth_minus_8 );
    /* Create frame buffers for the decoder.
     * The callback as_video_release_buffer_handler() shall be called when no reference to the video buffer handler is present.
     * The callback as_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 *as_buffer_handler = av_buffer_create( NULL, 0, as_video_release_buffer_handler, as_vbhp, 0 );
    if( !as_buffer_handler )
    {
        delete as_vbhp;
        av_frame_unref( av_frame );
        return AVERROR( ENOMEM );
    }
#define CREATE_PLANE_BUFFER( PLANE, PLANE_ID )                                                      \
    do                                                                                              \
    {                                                                                               \
        AVBufferRef *as_buffer_ref = av_buffer_ref( as_buffer_handler );                            \
        if( !as_buffer_ref )                                                                        \
        {                                                                                           \
            av_buffer_unref( &as_buffer_handler );                                                  \
            goto fail;                                                                              \
        }                                                                                           \
        av_frame->linesize[PLANE] = as_vbhp->as_frame_buffer->GetPitch( PLANE_ID );                 \
        int as_plane_size = as_vbhp->as_frame_buffer->GetHeight( PLANE_ID )                         \
                          * av_frame->linesize[PLANE];                                              \
        av_frame->buf[PLANE] = av_buffer_create( as_vbhp->as_frame_buffer->GetWritePtr( PLANE_ID ), \
                                                 as_plane_size,                                     \
                                                 as_video_unref_buffer_handler,                     \
                                                 as_buffer_ref,                                     \
                                                 0 );                                               \
        if( !av_frame->buf[PLANE] )                                                                 \
            goto fail;                                                                              \
        av_frame->data[PLANE] = av_frame->buf[PLANE]->data;                                         \
    } while( 0 )
    if( as_vohp->vi->pixel_type & VideoInfo::CS_INTERLEAVED )
        CREATE_PLANE_BUFFER( 0, );
    else
        for( int i = 0; i < 3; i++ )
Beispiel #7
0
static int determine_colorspace_conversion
(
    as_video_output_handler_t *as_vohp,
    enum AVPixelFormat         input_pixel_format,
    enum AVPixelFormat        *output_pixel_format,
    int                       *output_pixel_type
)
{
    avoid_yuv_scale_conversion( &input_pixel_format );
    const struct
    {
        enum AVPixelFormat input_pixel_format;
        enum AVPixelFormat output_pixel_format;
        int                output_pixel_type;
        int                output_bitdepth_minus_8;
        int                output_sub_width;
        int                output_sub_height;
    } conversion_table[] =
        {
            { AV_PIX_FMT_YUV420P,     AV_PIX_FMT_YUV420P,     VideoInfo::CS_I420,    0, 1, 1 },
            { AV_PIX_FMT_NV12,        AV_PIX_FMT_YUV420P,     VideoInfo::CS_I420,    0, 1, 1 },
            { AV_PIX_FMT_NV21,        AV_PIX_FMT_YUV420P,     VideoInfo::CS_I420,    0, 1, 1 },
            { AV_PIX_FMT_YUV420P9LE,  AV_PIX_FMT_YUV420P9LE,  VideoInfo::CS_I420,    1, 1, 1 },
            { AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUV420P10LE, VideoInfo::CS_I420,    2, 1, 1 },
            { AV_PIX_FMT_YUV420P16LE, AV_PIX_FMT_YUV420P16LE, VideoInfo::CS_I420,    8, 1, 1 },
            { AV_PIX_FMT_YUYV422,     AV_PIX_FMT_YUYV422,     VideoInfo::CS_YUY2,    0, 1, 0 },
            { AV_PIX_FMT_YUV422P,     AV_PIX_FMT_YUYV422,     VideoInfo::CS_YUY2,    0, 1, 0 },
            { AV_PIX_FMT_UYVY422,     AV_PIX_FMT_YUYV422,     VideoInfo::CS_YUY2,    0, 1, 0 },
            { AV_PIX_FMT_YUV422P,     AV_PIX_FMT_YUV422P,     VideoInfo::CS_YV16,    0, 1, 0 },
            { AV_PIX_FMT_YUV422P9LE,  AV_PIX_FMT_YUV422P9LE,  VideoInfo::CS_YV16,    1, 1, 0 },
            { AV_PIX_FMT_YUV422P10LE, AV_PIX_FMT_YUV422P10LE, VideoInfo::CS_YV16,    2, 1, 0 },
            { AV_PIX_FMT_YUV422P16LE, AV_PIX_FMT_YUV422P16LE, VideoInfo::CS_YV16,    8, 1, 0 },
            { AV_PIX_FMT_YUV444P,     AV_PIX_FMT_YUV444P,     VideoInfo::CS_YV24,    0, 0, 0 },
            { AV_PIX_FMT_YUV444P9LE,  AV_PIX_FMT_YUV444P9LE,  VideoInfo::CS_YV24,    1, 0, 0 },
            { AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUV444P10LE, VideoInfo::CS_YV24,    2, 0, 0 },
            { AV_PIX_FMT_YUV444P16LE, AV_PIX_FMT_YUV444P16LE, VideoInfo::CS_YV24,    8, 0, 0 },
            { AV_PIX_FMT_YUV410P,     AV_PIX_FMT_YUV410P,     VideoInfo::CS_YUV9,    0, 2, 2 },
            { AV_PIX_FMT_YUV411P,     AV_PIX_FMT_YUV411P,     VideoInfo::CS_YV411,   0, 2, 0 },
            { AV_PIX_FMT_GRAY8,       AV_PIX_FMT_GRAY8,       VideoInfo::CS_Y8,      0, 0, 0 },
            { AV_PIX_FMT_RGB24,       AV_PIX_FMT_BGR24,       VideoInfo::CS_BGR24,   0, 0, 0 },
            { AV_PIX_FMT_BGR24,       AV_PIX_FMT_BGR24,       VideoInfo::CS_BGR24,   0, 0, 0 },
            { AV_PIX_FMT_ARGB,        AV_PIX_FMT_BGRA,        VideoInfo::CS_BGR32,   0, 0, 0 },
            { AV_PIX_FMT_RGBA,        AV_PIX_FMT_BGRA,        VideoInfo::CS_BGR32,   0, 0, 0 },
            { AV_PIX_FMT_ABGR,        AV_PIX_FMT_BGRA,        VideoInfo::CS_BGR32,   0, 0, 0 },
            { AV_PIX_FMT_BGRA,        AV_PIX_FMT_BGRA,        VideoInfo::CS_BGR32,   0, 0, 0 },
#if FFMPEG_HIGH_DEPTH_SUPPORT
            { AV_PIX_FMT_YUV420P12LE, AV_PIX_FMT_YUV420P12LE, VideoInfo::CS_I420,    4, 1, 1 },
            { AV_PIX_FMT_YUV420P14LE, AV_PIX_FMT_YUV420P14LE, VideoInfo::CS_I420,    6, 1, 1 },
            { AV_PIX_FMT_YUV422P12LE, AV_PIX_FMT_YUV422P12LE, VideoInfo::CS_YV16,    4, 1, 0 },
            { AV_PIX_FMT_YUV422P14LE, AV_PIX_FMT_YUV422P14LE, VideoInfo::CS_YV16,    6, 1, 0 },
            { AV_PIX_FMT_YUV444P12LE, AV_PIX_FMT_YUV444P12LE, VideoInfo::CS_YV24,    4, 0, 0 },
            { AV_PIX_FMT_YUV444P14LE, AV_PIX_FMT_YUV444P14LE, VideoInfo::CS_YV24,    6, 0, 0 },
#endif
            { AV_PIX_FMT_NONE,        AV_PIX_FMT_NONE,        VideoInfo::CS_UNKNOWN, 0, 0, 0 }
        };
    as_vohp->bitdepth_minus_8 = 0;
    int i = 0;
    if( *output_pixel_format == AV_PIX_FMT_NONE )
    {
        for( i = 0; conversion_table[i].input_pixel_format != AV_PIX_FMT_NONE; i++ )
            if( conversion_table[i].input_pixel_format == input_pixel_format )
            {
                *output_pixel_format = conversion_table[i].output_pixel_format;
                break;
            }
    }
    else
    {
        for( i = 0; conversion_table[i].input_pixel_format != AV_PIX_FMT_NONE; i++ )
            if( conversion_table[i].output_pixel_format == *output_pixel_format )
                break;
    }
    *output_pixel_type        = conversion_table[i].output_pixel_type;
    as_vohp->bitdepth_minus_8 = conversion_table[i].output_bitdepth_minus_8;
    as_vohp->sub_width        = conversion_table[i].output_sub_width;
    as_vohp->sub_height       = conversion_table[i].output_sub_height;
    switch( *output_pixel_format )
    {
        case AV_PIX_FMT_YUV420P     :   /* planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) */
        case AV_PIX_FMT_YUV422P     :   /* planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) */
        case AV_PIX_FMT_YUV444P     :   /* planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) */
        case AV_PIX_FMT_YUV410P     :   /* planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples) */
        case AV_PIX_FMT_YUV411P     :   /* planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) */
            as_vohp->make_black_background = make_black_background_planar_yuv;
            as_vohp->make_frame            = make_frame_planar_yuv;
            return 0;
        case AV_PIX_FMT_YUYV422     :   /* packed YUV 4:2:2, 16bpp */
            as_vohp->make_black_background = make_black_background_packed_yuv422;
            as_vohp->make_frame            = make_frame_packed_yuv;
            return 0;
        case AV_PIX_FMT_YUV420P9LE  :   /* planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian */
        case AV_PIX_FMT_YUV420P10LE :   /* planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian */
        case AV_PIX_FMT_YUV420P16LE :   /* planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian */
        case AV_PIX_FMT_YUV422P9LE  :   /* planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian */
        case AV_PIX_FMT_YUV422P10LE :   /* planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian */
        case AV_PIX_FMT_YUV422P16LE :   /* planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian */
        case AV_PIX_FMT_YUV444P9LE  :   /* planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian */
        case AV_PIX_FMT_YUV444P10LE :   /* planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian */
        case AV_PIX_FMT_YUV444P16LE :   /* planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian */
#if FFMPEG_HIGH_DEPTH_SUPPORT
        case AV_PIX_FMT_YUV420P12LE :
        case AV_PIX_FMT_YUV420P14LE :
        case AV_PIX_FMT_YUV422P12LE :
        case AV_PIX_FMT_YUV422P14LE :
        case AV_PIX_FMT_YUV444P12LE :
        case AV_PIX_FMT_YUV444P14LE :
#endif
            if( as_vohp->stacked_format )
            {
                as_vohp->make_black_background = make_black_background_planar_yuv;
                as_vohp->make_frame            = make_frame_planar_yuv_stacked;
            }
            else
            {
                as_vohp->make_black_background = make_black_background_planar_yuv_interleaved;
                as_vohp->make_frame            = make_frame_planar_yuv;
            }
            return 0;
        case AV_PIX_FMT_GRAY8 :     /* Y, 8bpp */
            as_vohp->make_black_background = make_black_background_packed_all_zero;
            as_vohp->make_frame            = make_frame_packed_yuv;
            return 0;
        case AV_PIX_FMT_BGR24 :     /* packed RGB 8:8:8, 24bpp, BGRBGR... */
        case AV_PIX_FMT_BGRA  :     /* packed BGRA 8:8:8:8, 32bpp, BGRABGRA... */
            as_vohp->make_black_background = make_black_background_packed_all_zero;
            as_vohp->make_frame            = make_frame_packed_rgb;
            return 0;
        default :
            as_vohp->make_black_background = NULL;
            as_vohp->make_frame            = NULL;
            return -1;
    }
}