示例#1
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;
}
示例#2
0
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;
}
示例#3
0
文件: video.c 项目: bobwxb/vlc
/**
 * 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;
}
示例#4
0
static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
                                          const enum PixelFormat *pi_fmt )
{
    decoder_t *p_dec = p_context->opaque;
    decoder_sys_t *p_sys = p_dec->p_sys;
    vlc_va_t *p_va = p_sys->p_va;

    if( p_va != NULL )
        vlc_va_Delete( p_va );

    /* Enumerate available formats */
    bool can_hwaccel = false;
    for( size_t i = 0; pi_fmt[i] != PIX_FMT_NONE; i++ )
    {
        const AVPixFmtDescriptor *dsc = av_pix_fmt_desc_get(pi_fmt[i]);
        if (dsc == NULL)
            continue;
        bool hwaccel = (dsc->flags & AV_PIX_FMT_FLAG_HWACCEL) != 0;

        msg_Dbg( p_dec, "available %sware decoder output format %d (%s)",
                 hwaccel ? "hard" : "soft", pi_fmt[i], dsc->name );
        if (hwaccel)
            can_hwaccel = true;
    }

    if (!can_hwaccel)
        goto end;

    /* Profile and level information is needed now.
     * TODO: avoid code duplication with avcodec.c */
    if( p_context->profile != FF_PROFILE_UNKNOWN)
        p_dec->fmt_in.i_profile = p_context->profile;
    if( p_context->level != FF_LEVEL_UNKNOWN)
        p_dec->fmt_in.i_level = p_context->level;

    p_va = vlc_va_New( VLC_OBJECT(p_dec), p_context, &p_dec->fmt_in );
    if( p_va == NULL )
        goto end;

    for( size_t i = 0; pi_fmt[i] != PIX_FMT_NONE; i++ )
    {
        if( p_va->pix_fmt != pi_fmt[i] )
            continue;

        /* We try to call vlc_va_Setup when possible to detect errors when
         * possible (later is too late) */
        if( p_context->width > 0 && p_context->height > 0
         && vlc_va_Setup( p_va, &p_context->hwaccel_context,
                          &p_dec->fmt_out.video.i_chroma,
                          p_context->width, p_context->height ) )
        {
            msg_Err( p_dec, "acceleration setup failure" );
            break;
        }

        if( p_va->description )
            msg_Info( p_dec, "Using %s for hardware decoding.",
                      p_va->description );

        /* FIXME this will disable direct rendering
         * even if a new pixel format is renegotiated
         */
        p_sys->b_direct_rendering = false;
        p_sys->p_va = p_va;
        p_context->draw_horiz_band = NULL;
        return pi_fmt[i];
    }

    vlc_va_Delete( p_va );

end:
    /* Fallback to default behaviour */
    p_sys->p_va = NULL;
    return avcodec_default_get_format( p_context, pi_fmt );
}
示例#5
0
文件: video.c 项目: bobwxb/vlc
static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
                                          const enum PixelFormat *pi_fmt )
{
    decoder_t *p_dec = p_context->opaque;
    decoder_sys_t *p_sys = p_dec->p_sys;

    if (p_sys->p_va != NULL)
    {
        vlc_va_Delete(p_sys->p_va, p_context);
        p_sys->p_va = NULL;
    }

    /* Enumerate available formats */
    enum PixelFormat swfmt = avcodec_default_get_format(p_context, pi_fmt);
    bool can_hwaccel = false;

    for( size_t i = 0; pi_fmt[i] != PIX_FMT_NONE; i++ )
    {
        const AVPixFmtDescriptor *dsc = av_pix_fmt_desc_get(pi_fmt[i]);
        if (dsc == NULL)
            continue;
        bool hwaccel = (dsc->flags & AV_PIX_FMT_FLAG_HWACCEL) != 0;

        msg_Dbg( p_dec, "available %sware decoder output format %d (%s)",
                 hwaccel ? "hard" : "soft", pi_fmt[i], dsc->name );
        if (hwaccel)
            can_hwaccel = true;
    }

    if (!can_hwaccel)
        return swfmt;

    for( size_t i = 0; pi_fmt[i] != PIX_FMT_NONE; i++ )
    {
        enum PixelFormat hwfmt = pi_fmt[i];

        p_dec->fmt_out.video.i_chroma = vlc_va_GetChroma(hwfmt, swfmt);
        if (p_dec->fmt_out.video.i_chroma == 0)
            continue; /* Unknown brand of hardware acceleration */
        if (lavc_UpdateVideoFormat(p_dec, p_context, true))
            continue; /* Unsupported brand of hardware acceleration */

        vlc_va_t *va = vlc_va_New(VLC_OBJECT(p_dec), p_context, hwfmt,
                                  &p_dec->fmt_in);
        if (va == NULL)
            continue; /* Unsupported codec profile or such */

        /* We try to call vlc_va_Setup when possible to detect errors when
         * possible (later is too late) */
        if( p_context->width > 0 && p_context->height > 0
         && vlc_va_Setup(va, p_context, &p_dec->fmt_out.video.i_chroma))
        {
            msg_Err( p_dec, "acceleration setup failure" );
            vlc_va_Delete(va, p_context);
            continue;
        }

        if (va->description != NULL)
            msg_Info(p_dec, "Using %s for hardware decoding", va->description);

        /* FIXME this will disable direct rendering
         * even if a new pixel format is renegotiated
         */
        p_sys->b_direct_rendering = false;
        p_sys->p_va = va;
        p_context->draw_horiz_band = NULL;
        return pi_fmt[i];
    }

    /* Fallback to default behaviour */
    return swfmt;
}
示例#6
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 );
}
示例#7
0
static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_codec,
                                          const enum PixelFormat *pi_fmt )
{
    decoder_t *p_dec = p_codec->opaque;
    decoder_sys_t *p_sys = p_dec->p_sys;

    if( p_sys->p_va )
    {
        vlc_va_Delete( p_sys->p_va );
        p_sys->p_va = NULL;
    }

    /* Try too look for a supported hw acceleration */
    for( int i = 0; pi_fmt[i] != PIX_FMT_NONE; i++ )
    {
        static const char *ppsz_name[PIX_FMT_NB] = {
            [PIX_FMT_VDPAU_H264] = "PIX_FMT_VDPAU_H264",
            [PIX_FMT_VAAPI_IDCT] = "PIX_FMT_VAAPI_IDCT",
            [PIX_FMT_VAAPI_VLD] = "PIX_FMT_VAAPI_VLD",
            [PIX_FMT_VAAPI_MOCO] = "PIX_FMT_VAAPI_MOCO",
#ifdef HAVE_AVCODEC_DXVA2
            [PIX_FMT_DXVA2_VLD] = "PIX_FMT_DXVA2_VLD",
#endif
            [PIX_FMT_YUYV422] = "PIX_FMT_YUYV422",
            [PIX_FMT_YUV420P] = "PIX_FMT_YUV420P",
        };
        msg_Dbg( p_dec, "Available decoder output format %d (%s)", pi_fmt[i], ppsz_name[pi_fmt[i]] ?: "Unknown" );

        /* Only VLD supported */
        if( pi_fmt[i] == PIX_FMT_VAAPI_VLD )
        {
#ifdef HAVE_AVCODEC_VAAPI
            msg_Dbg( p_dec, "Trying VA API" );
            p_sys->p_va = vlc_va_NewVaapi( p_sys->i_codec_id );
            if( !p_sys->p_va )
                msg_Warn( p_dec, "Failed to open VA API" );
#else
            continue;
#endif
        }
#ifdef HAVE_AVCODEC_DXVA2
        if( pi_fmt[i] == PIX_FMT_DXVA2_VLD )
        {
            msg_Dbg( p_dec, "Trying DXVA2" );
            p_sys->p_va = vlc_va_NewDxva2( VLC_OBJECT(p_dec), p_sys->i_codec_id );
            if( !p_sys->p_va )
                msg_Warn( p_dec, "Failed to open DXVA2" );
        }
#endif

        if( p_sys->p_va &&
            p_sys->p_context->width > 0 && p_sys->p_context->height > 0 )
        {
            /* We try to call vlc_va_Setup when possible to detect errors when
             * possible (later is too late) */
            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" );
                vlc_va_Delete( p_sys->p_va );
                p_sys->p_va = NULL;
            }
        }

        if( p_sys->p_va )
        {
            if( p_sys->p_va->description )
                msg_Info( p_dec, "Using %s for hardware decoding.", p_sys->p_va->description );

            /* FIXME this will disabled direct rendering
             * even if a new pixel format is renegociated
             */
            p_sys->b_direct_rendering = false;
            p_sys->p_context->draw_horiz_band = NULL;
            return pi_fmt[i];
        }
    }

    /* Fallback to default behaviour */
    return avcodec_default_get_format( p_codec, pi_fmt );
}