Fplay: vaapi works, but the video output is too slow.

git-svn-id: svn://kolibrios.org@6121 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2016-02-01 19:27:17 +00:00
parent 09b80753fe
commit 63743484d7
4 changed files with 122 additions and 119 deletions

View File

@ -27,11 +27,11 @@ volatile enum player_state sound_state = STOP;
uint32_t win_width, win_height; uint32_t win_width, win_height;
AVFrame *pFrame; AVFrame *pFrame;
int have_sound = 0; int have_sound = 0;
uint8_t *decoder_buffer; uint8_t *decoder_buffer;
extern int resampler_size; extern int resampler_size;
extern int sample_rate; extern int sample_rate;
@ -80,10 +80,6 @@ int main( int argc, char *argv[])
avdevice_register_all(); avdevice_register_all();
av_register_all(); av_register_all();
#ifdef HAVE_VAAPI
fplay_vaapi_init();
#endif
if( avformat_open_input(&vst.fCtx, movie_file, NULL, NULL) < 0) if( avformat_open_input(&vst.fCtx, movie_file, NULL, NULL) < 0)
{ {
printf("Cannot open file %s\n\r", movie_file); printf("Cannot open file %s\n\r", movie_file);
@ -158,20 +154,8 @@ int main( int argc, char *argv[])
return -1; // Codec not found return -1; // Codec not found
} }
#ifdef HAVE_VAAPI if(fplay_init_context(&vst))
int hwdec = va_check_codec_support(vst.vCtx->codec_id); return -1;
if(hwdec)
{
printf("hardware decode supported\n");
if (fplay_init_context(&vst) < 0)
{
printf("context initialization failed\n");
return -1;
};
};
#endif
if(avcodec_open2(vst.vCtx, vst.vCodec, NULL) < 0) if(avcodec_open2(vst.vCtx, vst.vCodec, NULL) < 0)
{ {
@ -180,6 +164,7 @@ int main( int argc, char *argv[])
return -1; // Could not open codec return -1; // Could not open codec
}; };
printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt);
mutex_init(&vst.q_video.lock); mutex_init(&vst.q_video.lock);
mutex_init(&vst.q_audio.lock); mutex_init(&vst.q_audio.lock);

View File

@ -16,6 +16,15 @@ typedef struct vstate vst_t;
#define HAS_RIGHT (1<<2) #define HAS_RIGHT (1<<2)
#define HAS_BOTTOM (1<<3) #define HAS_BOTTOM (1<<3)
typedef struct
{
enum AVPixelFormat format;
AVPicture picture;
int planar;
double pts;
volatile int ready;
}vframe_t;
struct render struct render
{ {
vst_t *vst; vst_t *vst;
@ -98,26 +107,27 @@ int get_packet(queue_t *q, AVPacket *pkt);
struct vstate struct vstate
{ {
AVFormatContext *fCtx; /* format context */ AVFormatContext *fCtx; /* format context */
AVCodecContext *vCtx; /* video decoder context */ AVCodecContext *vCtx; /* video decoder context */
AVCodecContext *aCtx; /* audio decoder context */ AVCodecContext *aCtx; /* audio decoder context */
AVCodec *vCodec; /* video codec */ AVCodec *vCodec; /* video codec */
AVCodec *aCodec; /* audio codec */ AVCodec *aCodec; /* audio codec */
int vStream; /* video stream index */ int vStream; /* video stream index */
int aStream; /* audio stream index */ int aStream; /* audio stream index */
queue_t q_video; /* video packets queue */ queue_t q_video; /* video packets queue */
queue_t q_audio; /* audio packets queue */ queue_t q_audio; /* audio packets queue */
mutex_t gpu_lock; /* gpu access lock. libdrm not yet thread safe :( */ mutex_t gpu_lock; /* gpu access lock. libdrm not yet thread safe :( */
int vfx; /* index of decoded frame */ vframe_t vframe[4]; /* decoder workset */
int dfx; /* index of renderd frame */ int vfx; /* index of decoded frame */
int dfx; /* index of renderd frame */
void *hwCtx; /* hardware context */
int hwdec; /* hardware decoder */
}; };
#define DECODER_THREAD 1 #define DECODER_THREAD 1
#define AUDIO_THREAD 2 #define AUDIO_THREAD 2
#define VIDEO_THREAD 4 #define VIDEO_THREAD 4
@ -155,7 +165,6 @@ static inline void GetNotify(void *event)
::"a"(68),"b"(14),"c"(event)); ::"a"(68),"b"(14),"c"(event));
} }
int fplay_vaapi_init(void);
void va_convert_picture(vst_t *vst, int width, int height, AVPicture *pic); void va_convert_picture(vst_t *vst, int width, int height, AVPicture *pic);
int init_fontlib(); int init_fontlib();

View File

@ -176,7 +176,7 @@ VADisplay va_open_display(void)
return NULL; return NULL;
}; };
int vaapi_init(VADisplay display) void *vaapi_init(VADisplay display)
{ {
struct vaapi_context *vaapi; struct vaapi_context *vaapi;
int major_version, minor_version; int major_version, minor_version;
@ -225,14 +225,13 @@ int vaapi_init(VADisplay display)
v_context = vaapi; v_context = vaapi;
return 0; return vaapi;
error: error:
free(display_attrs); free(display_attrs);
return -1; return NULL;
} }
static int has_profile(struct vaapi_context *vaapi, VAProfile profile) static int has_profile(struct vaapi_context *vaapi, VAProfile profile)
{ {
VAProfile *profiles; VAProfile *profiles;
@ -485,25 +484,61 @@ int fplay_init_context(vst_t *vst)
{ {
AVCodecContext *vCtx = vst->vCtx; AVCodecContext *vCtx = vst->vCtx;
vCtx->opaque = vst; if(va_check_codec_support(vCtx->codec_id))
vCtx->thread_count = 1; {
vCtx->get_format = get_format; VADisplay dpy;
vCtx->get_buffer2 = get_buffer2;
dpy = va_open_display();
vst->hwCtx = vaapi_init(dpy);
if(vst->hwCtx != NULL)
{
for(int i = 0; i < 4; i++)
{
int ret;
ret = avpicture_alloc(&vst->vframe[i].picture, AV_PIX_FMT_BGRA,
vst->vCtx->width, vst->vCtx->height);
if ( ret != 0 )
{
printf("Cannot alloc video buffer\n\r");
return ret;
};
vst->vframe[i].format = AV_PIX_FMT_BGRA;
vst->vframe[i].pts = 0;
vst->vframe[i].ready = 0;
};
vst->hwdec = 1;
vCtx->opaque = vst;
vCtx->thread_count = 1;
vCtx->get_format = get_format;
vCtx->get_buffer2 = get_buffer2;
return 0;
};
};
vst->hwdec = 0;
for(int i = 0; i < 4; i++)
{
int ret;
ret = avpicture_alloc(&vst->vframe[i].picture, vst->vCtx->pix_fmt,
vst->vCtx->width, vst->vCtx->height);
if ( ret != 0 )
{
printf("Cannot alloc video buffer\n\r");
return ret;
};
vst->vframe[i].format = vst->vCtx->pix_fmt;
vst->vframe[i].pts = 0;
vst->vframe[i].ready = 0;
};
return 0; return 0;
} }
int fplay_vaapi_init(void)
{
VADisplay dpy;
dpy = va_open_display();
if (vaapi_init(dpy) < 0)
return -1;
return 0;
}
struct SwsContext *vacvt_ctx; struct SwsContext *vacvt_ctx;
@ -584,9 +619,6 @@ void va_convert_picture(vst_t *vst, int width, int height, AVPicture *pic)
return ; return ;
}; };
// __asm__ volatile ("int3");
sws_scale(vacvt_ctx, (const uint8_t* const *)src_data, src_linesize, 0, height, pic->data, pic->linesize); sws_scale(vacvt_ctx, (const uint8_t* const *)src_data, src_linesize, 0, height, pic->data, pic->linesize);
vaUnmapBuffer (vaapi->display, vaimage.buf); vaUnmapBuffer (vaapi->display, vaimage.buf);

View File

@ -11,8 +11,6 @@
#include "winlib/winlib.h" #include "winlib/winlib.h"
#include "fplay.h" #include "fplay.h"
int fplay_blit_bitmap(bitmap_t *bitmap, int dst_x, int dst_y,int w, int h);
extern int res_pause_btn[]; extern int res_pause_btn[];
extern int res_pause_btn_pressed[]; extern int res_pause_btn_pressed[];
@ -23,15 +21,7 @@ extern int64_t stream_duration;
extern volatile int sound_level_0; extern volatile int sound_level_0;
extern volatile int sound_level_1; extern volatile int sound_level_1;
typedef struct volatile int frames_count = 0;
{
AVPicture picture;
double pts;
volatile int ready;
}vframe_t;
vframe_t frames[4];
volatile int frames_count = 0;
struct SwsContext *cvt_ctx = NULL; struct SwsContext *cvt_ctx = NULL;
@ -52,8 +42,8 @@ void flush_video(vst_t *vst)
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++)
{ {
frames[i].pts = 0; vst->vframe[i].pts = 0;
frames[i].ready = 0; vst->vframe[i].ready = 0;
}; };
vst->vfx = 0; vst->vfx = 0;
vst->dfx = 0; vst->dfx = 0;
@ -74,22 +64,6 @@ int init_video(vst_t *vst)
return 0; return 0;
}; };
for( i=0; i < 4; i++)
{
int ret;
ret = avpicture_alloc(&frames[i].picture, vst->vCtx->pix_fmt,
vst->vCtx->width, vst->vCtx->height);
if ( ret != 0 )
{
printf("Cannot alloc video buffer\n\r");
return 0;
};
frames[i].pts = 0;
frames[i].ready = 0;
};
create_thread(video_thread, vst, 1024*1024); create_thread(video_thread, vst, 1024*1024);
delay(50); delay(50);
@ -103,7 +77,7 @@ int decode_video(vst_t* vst)
int frameFinished; int frameFinished;
double current_clock; double current_clock;
if(frames[vst->dfx].ready != 0 ) if(vst->vframe[vst->dfx].ready != 0 )
return -1; return -1;
if( get_packet(&vst->q_video, &pkt) == 0 ) if( get_packet(&vst->q_video, &pkt) == 0 )
@ -148,16 +122,17 @@ int decode_video(vst_t* vst)
pts *= av_q2d(video_time_base); pts *= av_q2d(video_time_base);
dst_pic = &frames[vst->dfx].picture; dst_pic = &vst->vframe[vst->dfx].picture;
av_image_copy(dst_pic->data, dst_pic->linesize, if(vst->hwdec == 0)
(const uint8_t**)Frame->data, av_image_copy(dst_pic->data, dst_pic->linesize,
Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height); (const uint8_t**)Frame->data,
Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height);
frames[vst->dfx].pts = pts*1000.0; else
va_convert_picture(vst, vst->vCtx->width, vst->vCtx->height, dst_pic);
frames[vst->dfx].ready = 1;
vst->vframe[vst->dfx].pts = pts*1000.0;
vst->vframe[vst->dfx].ready = 1;
vst->dfx = (vst->dfx + 1) & 3; vst->dfx = (vst->dfx + 1) & 3;
frames_count++; frames_count++;
}; };
@ -417,12 +392,12 @@ void render_time(render_t *render)
#ifdef VERSION_A #ifdef VERSION_A
if(frames[vst->vfx].ready == 1 ) if(vst->vframe[vst->vfx].ready == 1 )
{ {
int sys_time; int sys_time;
ctime = get_master_clock(); ctime = get_master_clock();
fdelay = (frames[vst->vfx].pts - ctime); fdelay = (vst->vframe[vst->vfx].pts - ctime);
// printf("pts %f time %f delay %f\n", // printf("pts %f time %f delay %f\n",
// frames[vfx].pts, ctime, fdelay); // frames[vfx].pts, ctime, fdelay);
@ -434,7 +409,7 @@ void render_time(render_t *render)
}; };
#if 0 #if 0
ctime = get_master_clock(); ctime = get_master_clock();
fdelay = (frames[vst->vfx].pts - ctime); fdelay = (vst->vframe[vst->vfx].pts - ctime);
// while(fdelay > 0) // while(fdelay > 0)
// { // {
@ -450,14 +425,14 @@ void render_time(render_t *render)
// sys_time*10, frames[vfx].pts, ctime, fdelay); // sys_time*10, frames[vfx].pts, ctime, fdelay);
printf("pts %f time %f delay %f\n", printf("pts %f time %f delay %f\n",
frames[vfx].pts, ctime, fdelay); vst->vframe[vst->vfx].pts, ctime, fdelay);
printf("video cache %d audio cache %d\n", q_video.size/1024, q_audio.size/1024); printf("video cache %d audio cache %d\n", q_video.size/1024, q_audio.size/1024);
#endif #endif
main_render->draw(main_render, &frames[vst->vfx].picture); main_render->draw(main_render, &vst->vframe[vst->vfx].picture);
if(main_render->win->win_state != FULLSCREEN) if(main_render->win->win_state != FULLSCREEN)
{ {
prg->current = frames[vst->vfx].pts*1000; prg->current = vst->vframe[vst->vfx].pts*1000;
// printf("current %f\n", prg->current); // printf("current %f\n", prg->current);
lvl->current = vst->vfx & 1 ? sound_level_1 : sound_level_0; lvl->current = vst->vfx & 1 ? sound_level_1 : sound_level_0;
@ -468,17 +443,17 @@ void render_time(render_t *render)
} }
frames_count--; frames_count--;
frames[vst->vfx].ready = 0; vst->vframe[vst->vfx].ready = 0;
vst->vfx = (vst->vfx + 1) & 3; vst->vfx = (vst->vfx + 1) & 3;
} }
else delay(1); else delay(1);
#else #else
if(frames[vfx].ready == 1 ) if(vst->vframe[vfx].ready == 1 )
{ {
ctime = get_master_clock(); ctime = get_master_clock();
fdelay = (frames[vst->vfx].pts - ctime); fdelay = (vst->vrame[vst->vfx].pts - ctime);
// printf("pts %f time %f delay %f\n", // printf("pts %f time %f delay %f\n",
// frames[vfx].pts, ctime, fdelay); // frames[vfx].pts, ctime, fdelay);
@ -488,21 +463,21 @@ void render_time(render_t *render)
int next_vfx; int next_vfx;
fdelay = 0; fdelay = 0;
next_vfx = (vst->vfx+1) & 3; next_vfx = (vst->vfx+1) & 3;
if( frames[next_vfx].ready == 1 ) if( vst->vrame[next_vfx].ready == 1 )
{ {
if(frames[next_vfx].pts <= ctime) if(vst->vrame[next_vfx].pts <= ctime)
{ {
frames[vst->vfx].ready = 0; // skip this frame vst->vrame[vst->vfx].ready = 0; // skip this frame
vst->vfx = (vst->vfx + 1) & 3; vst->vfx = (vst->vfx + 1) & 3;
} }
else else
{ {
if( (frames[next_vfx].pts - ctime) < if( (vst->vrame[next_vfx].pts - ctime) <
( ctime - frames[vst->vfx].pts) ) ( ctime - frames[vst->vfx].pts) )
{ {
frames[vst->vfx].ready = 0; // skip this frame vst->vrame[vst->vfx].ready = 0; // skip this frame
vst->vfx = (vst->vfx + 1) & 3; vst->vfx = (vst->vfx + 1) & 3;
fdelay = (frames[next_vfx].pts - ctime); fdelay = (vst->vrame[next_vfx].pts - ctime);
} }
} }
}; };
@ -512,20 +487,20 @@ void render_time(render_t *render)
{ {
int val = fdelay; int val = fdelay;
printf("pts %f time %f delay %d\n", printf("pts %f time %f delay %d\n",
frames[vst->vfx].pts, ctime, val); vst->vrame[vst->vfx].pts, ctime, val);
delay(val/10); delay(val/10);
}; };
ctime = get_master_clock(); ctime = get_master_clock();
fdelay = (frames[vst->vfx].pts - ctime); fdelay = (vst->vrame[vst->vfx].pts - ctime);
printf("pts %f time %f delay %f\n", printf("pts %f time %f delay %f\n",
frames[vst->vfx].pts, ctime, fdelay); vst->vrame[vst->vfx].pts, ctime, fdelay);
main_render->draw(main_render, &frames[vfx].picture); main_render->draw(main_render, &vst->vrame[vfx].picture);
main_render->win->panel.prg->current = frames[vfx].pts; main_render->win->panel.prg->current = vst->vrame[vfx].pts;
// send_message(&render->win->panel.prg->ctrl, MSG_PAINT, 0, 0); // send_message(&render->win->panel.prg->ctrl, MSG_PAINT, 0, 0);
frames[vst->vfx].ready = 0; vst->vrame[vst->vfx].ready = 0;
vst->vfx = (vst->vfx + 1) & 3; vst->vfx = (vst->vfx + 1) & 3;
} }
else yield(); else yield();
@ -817,6 +792,7 @@ void draw_hw_picture(render_t *render, AVPicture *picture)
uint32_t bitmap_pitch; uint32_t bitmap_pitch;
uint8_t *data[4]; uint8_t *data[4];
int linesize[4]; int linesize[4];
enum AVPixelFormat format;
if(render->win->win_state == MINIMIZED || if(render->win->win_state == MINIMIZED ||
render->win->win_state == ROLLED) render->win->win_state == ROLLED)
@ -833,8 +809,9 @@ void draw_hw_picture(render_t *render, AVPicture *picture)
dst_height = render->rcvideo.b; dst_height = render->rcvideo.b;
}; };
format = render->vst->hwdec == 0 ? render->ctx_format : AV_PIX_FMT_BGRA
cvt_ctx = sws_getCachedContext(cvt_ctx, cvt_ctx = sws_getCachedContext(cvt_ctx,
render->ctx_width, render->ctx_height, render->ctx_format, render->ctx_width, render->ctx_height, format,
dst_width, dst_height, AV_PIX_FMT_BGRA, dst_width, dst_height, AV_PIX_FMT_BGRA,
SWS_FAST_BILINEAR, NULL, NULL, NULL); SWS_FAST_BILINEAR, NULL, NULL, NULL);
if(cvt_ctx == NULL) if(cvt_ctx == NULL)
@ -960,8 +937,8 @@ void render_draw_client(render_t *render)
if(player_state == PAUSE) if(player_state == PAUSE)
{ {
if(frames[vst->vfx].ready == 1 ) if(vst->vframe[vst->vfx].ready == 1 )
main_render->draw(main_render, &frames[vst->vfx].picture); main_render->draw(main_render, &vst->vframe[vst->vfx].picture);
else else
draw_bar(0, y, render->win_width, draw_bar(0, y, render->win_width,
render->rcvideo.b, 0); render->rcvideo.b, 0);