From 63743484d7de48476abafb240f061293863f5193 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Mon, 1 Feb 2016 19:27:17 +0000 Subject: [PATCH] Fplay: vaapi works, but the video output is too slow. git-svn-id: svn://kolibrios.org@6121 a494cfbc-eb01-0410-851d-a64ba20cac60 --- contrib/media/fplay/fplay.c | 27 +++------- contrib/media/fplay/fplay.h | 37 ++++++++----- contrib/media/fplay/vaapi.c | 76 +++++++++++++++++++-------- contrib/media/fplay/video.c | 101 ++++++++++++++---------------------- 4 files changed, 122 insertions(+), 119 deletions(-) diff --git a/contrib/media/fplay/fplay.c b/contrib/media/fplay/fplay.c index 9ba9ee4de9..44ff91fa4c 100644 --- a/contrib/media/fplay/fplay.c +++ b/contrib/media/fplay/fplay.c @@ -27,11 +27,11 @@ volatile enum player_state sound_state = STOP; 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 sample_rate; @@ -80,10 +80,6 @@ int main( int argc, char *argv[]) avdevice_register_all(); av_register_all(); -#ifdef HAVE_VAAPI - fplay_vaapi_init(); -#endif - if( avformat_open_input(&vst.fCtx, movie_file, NULL, NULL) < 0) { printf("Cannot open file %s\n\r", movie_file); @@ -158,20 +154,8 @@ int main( int argc, char *argv[]) return -1; // Codec not found } -#ifdef HAVE_VAAPI - int hwdec = va_check_codec_support(vst.vCtx->codec_id); - - if(hwdec) - { - printf("hardware decode supported\n"); - - if (fplay_init_context(&vst) < 0) - { - printf("context initialization failed\n"); - return -1; - }; - }; -#endif + if(fplay_init_context(&vst)) + return -1; 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 }; + printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt); mutex_init(&vst.q_video.lock); mutex_init(&vst.q_audio.lock); diff --git a/contrib/media/fplay/fplay.h b/contrib/media/fplay/fplay.h index 46fd015431..75c59ec78b 100644 --- a/contrib/media/fplay/fplay.h +++ b/contrib/media/fplay/fplay.h @@ -16,6 +16,15 @@ typedef struct vstate vst_t; #define HAS_RIGHT (1<<2) #define HAS_BOTTOM (1<<3) +typedef struct +{ + enum AVPixelFormat format; + AVPicture picture; + int planar; + double pts; + volatile int ready; +}vframe_t; + struct render { vst_t *vst; @@ -98,26 +107,27 @@ int get_packet(queue_t *q, AVPacket *pkt); struct vstate { - AVFormatContext *fCtx; /* format context */ - AVCodecContext *vCtx; /* video decoder context */ - AVCodecContext *aCtx; /* audio decoder context */ - AVCodec *vCodec; /* video codec */ - AVCodec *aCodec; /* audio codec */ - int vStream; /* video stream index */ - int aStream; /* audio stream index */ + AVFormatContext *fCtx; /* format context */ + AVCodecContext *vCtx; /* video decoder context */ + AVCodecContext *aCtx; /* audio decoder context */ + AVCodec *vCodec; /* video codec */ + AVCodec *aCodec; /* audio codec */ + int vStream; /* video stream index */ + int aStream; /* audio stream index */ - queue_t q_video; /* video packets queue */ - queue_t q_audio; /* audio packets queue */ + queue_t q_video; /* video packets queue */ + queue_t q_audio; /* audio packets queue */ mutex_t gpu_lock; /* gpu access lock. libdrm not yet thread safe :( */ - int vfx; /* index of decoded frame */ - int dfx; /* index of renderd frame */ - + vframe_t vframe[4]; /* decoder workset */ + 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 AUDIO_THREAD 2 #define VIDEO_THREAD 4 @@ -155,7 +165,6 @@ static inline void GetNotify(void *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); int init_fontlib(); diff --git a/contrib/media/fplay/vaapi.c b/contrib/media/fplay/vaapi.c index 6347409785..e305a0507f 100644 --- a/contrib/media/fplay/vaapi.c +++ b/contrib/media/fplay/vaapi.c @@ -176,7 +176,7 @@ VADisplay va_open_display(void) return NULL; }; -int vaapi_init(VADisplay display) +void *vaapi_init(VADisplay display) { struct vaapi_context *vaapi; int major_version, minor_version; @@ -225,14 +225,13 @@ int vaapi_init(VADisplay display) v_context = vaapi; - return 0; + return vaapi; error: free(display_attrs); - return -1; + return NULL; } - static int has_profile(struct vaapi_context *vaapi, VAProfile profile) { VAProfile *profiles; @@ -485,25 +484,61 @@ int fplay_init_context(vst_t *vst) { AVCodecContext *vCtx = vst->vCtx; - vCtx->opaque = vst; - vCtx->thread_count = 1; - vCtx->get_format = get_format; - vCtx->get_buffer2 = get_buffer2; + if(va_check_codec_support(vCtx->codec_id)) + { + VADisplay dpy; + + 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; } -int fplay_vaapi_init(void) -{ - VADisplay dpy; - - dpy = va_open_display(); - - if (vaapi_init(dpy) < 0) - return -1; - - return 0; -} struct SwsContext *vacvt_ctx; @@ -584,9 +619,6 @@ void va_convert_picture(vst_t *vst, int width, int height, AVPicture *pic) return ; }; - -// __asm__ volatile ("int3"); - sws_scale(vacvt_ctx, (const uint8_t* const *)src_data, src_linesize, 0, height, pic->data, pic->linesize); vaUnmapBuffer (vaapi->display, vaimage.buf); diff --git a/contrib/media/fplay/video.c b/contrib/media/fplay/video.c index 848efd9143..31c5fb385d 100644 --- a/contrib/media/fplay/video.c +++ b/contrib/media/fplay/video.c @@ -11,8 +11,6 @@ #include "winlib/winlib.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_pressed[]; @@ -23,15 +21,7 @@ extern int64_t stream_duration; extern volatile int sound_level_0; extern volatile int sound_level_1; -typedef struct -{ - AVPicture picture; - double pts; - volatile int ready; -}vframe_t; - -vframe_t frames[4]; -volatile int frames_count = 0; +volatile int frames_count = 0; struct SwsContext *cvt_ctx = NULL; @@ -52,8 +42,8 @@ void flush_video(vst_t *vst) for(i = 0; i < 4; i++) { - frames[i].pts = 0; - frames[i].ready = 0; + vst->vframe[i].pts = 0; + vst->vframe[i].ready = 0; }; vst->vfx = 0; vst->dfx = 0; @@ -74,22 +64,6 @@ int init_video(vst_t *vst) 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); delay(50); @@ -103,7 +77,7 @@ int decode_video(vst_t* vst) int frameFinished; double current_clock; - if(frames[vst->dfx].ready != 0 ) + if(vst->vframe[vst->dfx].ready != 0 ) return -1; if( get_packet(&vst->q_video, &pkt) == 0 ) @@ -148,16 +122,17 @@ int decode_video(vst_t* vst) 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, - (const uint8_t**)Frame->data, - Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height); - - frames[vst->dfx].pts = pts*1000.0; - - frames[vst->dfx].ready = 1; + if(vst->hwdec == 0) + av_image_copy(dst_pic->data, dst_pic->linesize, + (const uint8_t**)Frame->data, + Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height); + else + va_convert_picture(vst, vst->vCtx->width, vst->vCtx->height, dst_pic); + vst->vframe[vst->dfx].pts = pts*1000.0; + vst->vframe[vst->dfx].ready = 1; vst->dfx = (vst->dfx + 1) & 3; frames_count++; }; @@ -417,12 +392,12 @@ void render_time(render_t *render) #ifdef VERSION_A - if(frames[vst->vfx].ready == 1 ) + if(vst->vframe[vst->vfx].ready == 1 ) { int sys_time; 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", // frames[vfx].pts, ctime, fdelay); @@ -434,7 +409,7 @@ void render_time(render_t *render) }; #if 0 ctime = get_master_clock(); - fdelay = (frames[vst->vfx].pts - ctime); + fdelay = (vst->vframe[vst->vfx].pts - ctime); // while(fdelay > 0) // { @@ -450,14 +425,14 @@ void render_time(render_t *render) // sys_time*10, frames[vfx].pts, ctime, fdelay); 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); #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) { - prg->current = frames[vst->vfx].pts*1000; + prg->current = vst->vframe[vst->vfx].pts*1000; // printf("current %f\n", prg->current); lvl->current = vst->vfx & 1 ? sound_level_1 : sound_level_0; @@ -468,17 +443,17 @@ void render_time(render_t *render) } frames_count--; - frames[vst->vfx].ready = 0; + vst->vframe[vst->vfx].ready = 0; vst->vfx = (vst->vfx + 1) & 3; } else delay(1); #else - if(frames[vfx].ready == 1 ) + if(vst->vframe[vfx].ready == 1 ) { 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", // frames[vfx].pts, ctime, fdelay); @@ -488,21 +463,21 @@ void render_time(render_t *render) int next_vfx; fdelay = 0; 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; } else { - if( (frames[next_vfx].pts - ctime) < + if( (vst->vrame[next_vfx].pts - ctime) < ( 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; - 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; printf("pts %f time %f delay %d\n", - frames[vst->vfx].pts, ctime, val); + vst->vrame[vst->vfx].pts, ctime, val); delay(val/10); }; 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", - frames[vst->vfx].pts, ctime, fdelay); + vst->vrame[vst->vfx].pts, ctime, fdelay); - main_render->draw(main_render, &frames[vfx].picture); - main_render->win->panel.prg->current = frames[vfx].pts; + main_render->draw(main_render, &vst->vrame[vfx].picture); + main_render->win->panel.prg->current = vst->vrame[vfx].pts; // 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; } else yield(); @@ -817,6 +792,7 @@ void draw_hw_picture(render_t *render, AVPicture *picture) uint32_t bitmap_pitch; uint8_t *data[4]; int linesize[4]; + enum AVPixelFormat format; if(render->win->win_state == MINIMIZED || render->win->win_state == ROLLED) @@ -833,8 +809,9 @@ void draw_hw_picture(render_t *render, AVPicture *picture) dst_height = render->rcvideo.b; }; + format = render->vst->hwdec == 0 ? render->ctx_format : AV_PIX_FMT_BGRA 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, SWS_FAST_BILINEAR, NULL, NULL, NULL); if(cvt_ctx == NULL) @@ -960,8 +937,8 @@ void render_draw_client(render_t *render) if(player_state == PAUSE) { - if(frames[vst->vfx].ready == 1 ) - main_render->draw(main_render, &frames[vst->vfx].picture); + if(vst->vframe[vst->vfx].ready == 1 ) + main_render->draw(main_render, &vst->vframe[vst->vfx].picture); else draw_bar(0, y, render->win_width, render->rcvideo.b, 0);