Fplay: code cleanup

git-svn-id: svn://kolibrios.org@6136 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2016-02-04 19:25:52 +00:00
parent 798707fd38
commit f71187e224
4 changed files with 91 additions and 118 deletions

View File

@ -16,26 +16,17 @@
#include "sound.h" #include "sound.h"
#include "fplay.h" #include "fplay.h"
#ifdef HAVE_VAAPI
int va_check_codec_support(enum AVCodecID id);
#endif
volatile enum player_state player_state = STOP; volatile enum player_state player_state = STOP;
volatile enum player_state decoder_state = PREPARE; volatile enum player_state decoder_state = PREPARE;
volatile enum player_state sound_state = STOP; volatile enum player_state sound_state = STOP;
uint32_t win_width, win_height; uint32_t win_width, win_height;
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;
char *movie_file;
void flush_video(vst_t* vst);
int64_t rewind_pos; int64_t rewind_pos;
@ -46,12 +37,6 @@ int threads_running = DECODER_THREAD;
extern double audio_base; extern double audio_base;
double get_audio_base(vst_t* vst)
{
return (double)av_q2d(vst->fCtx->streams[vst->aStream]->time_base)*1000;
};
int main( int argc, char *argv[]) int main( int argc, char *argv[])
{ {
static vst_t vst; static vst_t vst;
@ -60,14 +45,14 @@ int main( int argc, char *argv[])
if(argc < 2) if(argc < 2)
{ {
movie_file = get_moviefile(); vst.input_file = get_moviefile();
if(movie_file == NULL) if(vst.input_file == NULL)
{ {
printf("Please provide a movie file\n"); printf("Please provide a movie file\n");
return -1; return -1;
} }
} }
else movie_file = argv[1]; else vst.input_file = argv[1];
/* register all codecs, demux and protocols */ /* register all codecs, demux and protocols */
@ -77,9 +62,9 @@ int main( int argc, char *argv[])
avdevice_register_all(); avdevice_register_all();
av_register_all(); av_register_all();
if( avformat_open_input(&vst.fCtx, movie_file, NULL, NULL) < 0) if( avformat_open_input(&vst.fCtx, vst.input_file, NULL, NULL) < 0)
{ {
printf("Cannot open file %s\n\r", movie_file); printf("Cannot open file %s\n\r", vst.input_file);
return -1; // Couldn't open file return -1; // Couldn't open file
}; };
@ -92,15 +77,15 @@ int main( int argc, char *argv[])
return -1; return -1;
}; };
file_name = strrchr(movie_file,'/')+1; file_name = strrchr(vst.input_file,'/')+1;
dot = strrchr(file_name,'.'); dot = strrchr(file_name,'.');
if(dot) if(dot)
{ {
movie_file = malloc(dot-file_name+1); vst.input_name = malloc(dot-file_name+1);
memcpy(movie_file, file_name, dot-file_name); memcpy(vst.input_name, file_name, dot-file_name);
movie_file[dot-file_name] = 0; vst.input_name[dot-file_name] = 0;
} }
else movie_file = file_name; else vst.input_name = file_name;
stream_duration = vst.fCtx->duration; stream_duration = vst.fCtx->duration;
@ -114,7 +99,7 @@ int main( int argc, char *argv[])
&& vst.vStream < 0) && vst.vStream < 0)
{ {
vst.vStream = i; vst.vStream = i;
video_time_base = vst.fCtx->streams[i]->time_base; vst.video_time_base = vst.fCtx->streams[i]->time_base;
if(stream_duration == 0) if(stream_duration == 0)
stream_duration = vst.fCtx->streams[i]->duration; stream_duration = vst.fCtx->streams[i]->duration;
} }
@ -123,6 +108,7 @@ int main( int argc, char *argv[])
vst.aStream < 0) vst.aStream < 0)
{ {
vst.aStream = i; vst.aStream = i;
vst.audio_time_base = vst.fCtx->streams[i]->time_base;
if(stream_duration == 0) if(stream_duration == 0)
stream_duration = vst.fCtx->streams[i]->duration; stream_duration = vst.fCtx->streams[i]->duration;
} }
@ -141,8 +127,6 @@ int main( int argc, char *argv[])
vst.aCtx = vst.fCtx->streams[vst.aStream]->codec; vst.aCtx = vst.fCtx->streams[vst.aStream]->codec;
vst.vCodec = avcodec_find_decoder(vst.vCtx->codec_id); vst.vCodec = avcodec_find_decoder(vst.vCtx->codec_id);
printf("codec id %x name %s\n",vst.vCtx->codec_id, vst.vCodec->name);
printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt);
INIT_LIST_HEAD(&vst.input_list); INIT_LIST_HEAD(&vst.input_list);
INIT_LIST_HEAD(&vst.output_list); INIT_LIST_HEAD(&vst.output_list);
@ -157,9 +141,16 @@ int main( int argc, char *argv[])
{ {
printf("Unsupported codec with id %d for input stream %d\n", printf("Unsupported codec with id %d for input stream %d\n",
vst.vCtx->codec_id, vst.vStream); vst.vCtx->codec_id, vst.vStream);
return -1; // Codec not found return -1;
} }
vst.Frame = av_frame_alloc();
if(vst.Frame == NULL)
{
printf("Cannot alloc video frame\n");
return -1;
};
if(fplay_init_context(&vst)) if(fplay_init_context(&vst))
return -1; return -1;
@ -170,8 +161,6 @@ 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);
if (vst.aCtx->channels > 0) if (vst.aCtx->channels > 0)
vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels); vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels);
else else
@ -223,10 +212,10 @@ int main( int argc, char *argv[])
} }
else printf("Unsupported audio codec!\n"); else printf("Unsupported audio codec!\n");
if(!init_video(&vst)) mutex_lock(&vst.decoder_lock);
return 0; create_thread(video_thread, &vst, 1024*1024);
if(mutex_lock_timeout(&vst.decoder_lock, 3000) == 0)
mutex_lock_timeout(&vst.decoder_lock, 3000); return -1;
decoder(&vst); decoder(&vst);
@ -369,7 +358,6 @@ void decoder(vst_t* vst)
delay(1); delay(1);
continue; continue;
} }
yield(); yield();
continue; continue;

View File

@ -27,7 +27,6 @@ typedef struct
int index; int index;
double pts; double pts;
double pkt_pts; double pkt_pts;
double pkt_dts;
volatile int ready; volatile int ready;
}vframe_t; }vframe_t;
@ -111,21 +110,24 @@ typedef struct {
int put_packet(queue_t *q, AVPacket *pkt); int put_packet(queue_t *q, AVPacket *pkt);
int get_packet(queue_t *q, AVPacket *pkt); int get_packet(queue_t *q, AVPacket *pkt);
#define HWDEC_NUM_SURFACES 16
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 */ char *input_file;
int aStream; /* audio stream index */ char *input_name;
int vStream; /* video stream index */
int aStream; /* audio stream index */
AVRational video_time_base;
AVRational audio_time_base;
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 :( */
mutex_t decoder_lock; mutex_t decoder_lock;
mutex_t input_lock; mutex_t input_lock;
@ -133,13 +135,18 @@ struct vstate
struct list_head input_list; struct list_head input_list;
struct list_head output_list; struct list_head output_list;
AVFrame *Frame;
vframe_t *decoder_frame; vframe_t *decoder_frame;
void *hwCtx; /* hardware context */ volatile int frames_count;
int hwdec:1; /* hardware decoder */ void *hwCtx; /* hardware context */
int blit_bitmap:1; /* hardware RGBA blitter */ int hwdec:1; /* hardware decoder */
int blit_texture:1; /* hardware RGBA blit and scale */ int blit_bitmap:1; /* hardware RGBA blitter */
int blit_planar:1; /* hardbare YUV blit and scale */ int blit_texture:1; /* hardware RGBA blit and scale */
int blit_planar:1; /* hardbare YUV blit and scale */
int frame_reorder:1; int frame_reorder:1;
int nframes;
vframe_t vframes[16];
}; };
@ -149,7 +156,6 @@ struct vstate
extern int threads_running; extern int threads_running;
extern astream_t astream; extern astream_t astream;
extern AVRational video_time_base;
render_t *create_render(vst_t *vst, window_t *win, uint32_t flags); render_t *create_render(vst_t *vst, window_t *win, uint32_t flags);
void destroy_render(render_t *render); void destroy_render(render_t *render);
@ -164,8 +170,8 @@ int init_audio(int format);
int audio_thread(void *param); int audio_thread(void *param);
void set_audio_volume(int left, int right); void set_audio_volume(int left, int right);
int init_video(vst_t* vst);
int video_thread(void *param); int video_thread(void *param);
void flush_video(vst_t* vst);
void decoder(vst_t *vst); void decoder(vst_t *vst);
int decode_video(vst_t* vst); int decode_video(vst_t* vst);
@ -180,6 +186,11 @@ static inline void GetNotify(void *event)
::"a"(68),"b"(14),"c"(event)); ::"a"(68),"b"(14),"c"(event));
} }
static inline double get_audio_base(vst_t* vst)
{
return (double)av_q2d(vst->fCtx->streams[vst->aStream]->time_base)*1000;
};
void va_create_planar(vst_t *vst, vframe_t *vframe); void va_create_planar(vst_t *vst, vframe_t *vframe);
int init_fontlib(); int init_fontlib();

View File

@ -39,7 +39,7 @@ struct hw_profile
static int drm_fd = 0; static int drm_fd = 0;
static struct vaapi_context *v_context; static struct vaapi_context *v_context;
static VASurfaceID v_surface_id[HWDEC_NUM_SURFACES]; static VASurfaceID v_surface_id[16];
#define HAS_HEVC VA_CHECK_VERSION(0, 38, 0) #define HAS_HEVC VA_CHECK_VERSION(0, 38, 0)
#define HAS_VP9 (VA_CHECK_VERSION(0, 38, 1) && defined(FF_PROFILE_VP9_0)) #define HAS_VP9 (VA_CHECK_VERSION(0, 38, 1) && defined(FF_PROFILE_VP9_0))
@ -281,10 +281,10 @@ static int has_entrypoint(struct vaapi_context *vaapi, VAProfile profile, VAEntr
return 0; return 0;
} }
static int vaapi_init_decoder(VAProfile profile, static int vaapi_init_decoder(vst_t *vst,VAProfile profile,
VAEntrypoint entrypoint, VAEntrypoint entrypoint,
unsigned int picture_width, unsigned int picture_width,
unsigned int picture_height) unsigned int picture_height)
{ {
struct vaapi_context* const vaapi = v_context; struct vaapi_context* const vaapi = v_context;
VAConfigAttrib attrib; VAConfigAttrib attrib;
@ -343,7 +343,7 @@ ENTER();
printf("vaCreateSurfaces %dx%d\n",picture_width,picture_height); printf("vaCreateSurfaces %dx%d\n",picture_width,picture_height);
status = vaCreateSurfaces(vaapi->display, VA_RT_FORMAT_YUV420, picture_width, picture_height, status = vaCreateSurfaces(vaapi->display, VA_RT_FORMAT_YUV420, picture_width, picture_height,
v_surface_id,HWDEC_NUM_SURFACES,NULL,0); v_surface_id,vst->nframes,NULL,0);
if (!vaapi_check_status(status, "vaCreateSurfaces()")) if (!vaapi_check_status(status, "vaCreateSurfaces()"))
{ {
FAIL(); FAIL();
@ -378,7 +378,7 @@ ENTER();
status = vaCreateContext(vaapi->display, config_id, status = vaCreateContext(vaapi->display, config_id,
picture_width, picture_height, picture_width, picture_height,
VA_PROGRESSIVE, VA_PROGRESSIVE,
v_surface_id, HWDEC_NUM_SURFACES, v_surface_id, vst->nframes,
&context_id); &context_id);
if (!vaapi_check_status(status, "vaCreateContext()")) if (!vaapi_check_status(status, "vaCreateContext()"))
{ {
@ -396,9 +396,9 @@ ENTER();
static enum PixelFormat get_format(struct AVCodecContext *avctx, static enum PixelFormat get_format(struct AVCodecContext *avctx,
const enum AVPixelFormat *fmt) const enum AVPixelFormat *fmt)
{ {
vst_t *vst = (vst_t*)avctx->opaque;
VAProfile profile = VAProfileNone; VAProfile profile = VAProfileNone;
ENTER();
for (int i = 0; fmt[i] != PIX_FMT_NONE; i++) for (int i = 0; fmt[i] != PIX_FMT_NONE; i++)
{ {
@ -419,17 +419,15 @@ static enum PixelFormat get_format(struct AVCodecContext *avctx,
hw_profiles[n].ff_profile == avctx->profile) hw_profiles[n].ff_profile == avctx->profile)
{ {
profile = hw_profiles[n].va_profile; profile = hw_profiles[n].va_profile;
if (vaapi_init_decoder(profile, VAEntrypointVLD, avctx->width, avctx->height) == 0) if (vaapi_init_decoder(vst, profile, VAEntrypointVLD, avctx->width, avctx->height) == 0)
{ {
avctx->hwaccel_context = v_context; avctx->hwaccel_context = v_context;
LEAVE();
return fmt[i]; ; return fmt[i]; ;
} }
} }
} }
} }
FAIL();
return PIX_FMT_NONE; return PIX_FMT_NONE;
} }
@ -472,6 +470,8 @@ int fplay_init_context(vst_t *vst)
{ {
AVCodecContext *vCtx = vst->vCtx; AVCodecContext *vCtx = vst->vCtx;
vst->nframes = 4;
if(va_check_codec_support(vCtx->codec_id)) if(va_check_codec_support(vCtx->codec_id))
{ {
VADisplay dpy; VADisplay dpy;
@ -481,9 +481,12 @@ int fplay_init_context(vst_t *vst)
if(vst->hwCtx != NULL) if(vst->hwCtx != NULL)
{ {
for(int i = 0; i < HWDEC_NUM_SURFACES; i++) if(vCtx->codec_id == AV_CODEC_ID_H264)
vst->nframes = 16;
for(int i = 0; i < vst->nframes; i++)
{ {
vframe_t *vframe = calloc(1, sizeof(*vframe)); vframe_t *vframe = &vst->vframes[i];
vframe->format = AV_PIX_FMT_NONE; vframe->format = AV_PIX_FMT_NONE;
vframe->is_hw_pic = 1; vframe->is_hw_pic = 1;
@ -494,6 +497,7 @@ int fplay_init_context(vst_t *vst)
}; };
vst->hwdec = 1; vst->hwdec = 1;
vst->frame_reorder = 1;
vCtx->opaque = vst; vCtx->opaque = vst;
vCtx->thread_count = 1; vCtx->thread_count = 1;
vCtx->get_format = get_format; vCtx->get_format = get_format;
@ -504,12 +508,12 @@ int fplay_init_context(vst_t *vst)
vst->hwdec = 0; vst->hwdec = 0;
for(int i = 0; i < HWDEC_NUM_SURFACES; i++) for(int i = 0; i < vst->nframes; i++)
{ {
vframe_t *vframe; vframe_t *vframe;
int ret; int ret;
vframe = calloc(1, sizeof(*vframe)); vframe = &vst->vframes[i];
ret = avpicture_alloc(&vframe->picture, vst->vCtx->pix_fmt, ret = avpicture_alloc(&vframe->picture, vst->vCtx->pix_fmt,
vst->vCtx->width, vst->vCtx->height); vst->vCtx->width, vst->vCtx->height);

View File

@ -21,16 +21,10 @@ 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;
volatile int frames_count = 0;
struct SwsContext *cvt_ctx = NULL; struct SwsContext *cvt_ctx = NULL;
render_t *main_render; render_t *main_render;
AVRational video_time_base;
AVFrame *Frame;
void get_client_rect(rect_t *rc); void get_client_rect(rect_t *rc);
void run_render(window_t *win, void *render); void run_render(window_t *win, void *render);
void window_update_layout(window_t *win); void window_update_layout(window_t *win);
@ -51,30 +45,12 @@ void flush_video(vst_t *vst)
vframe->pts = 0; vframe->pts = 0;
vframe->ready = 0; vframe->ready = 0;
} }
vst->frames_count = 0;
mutex_unlock(&vst->input_lock); mutex_unlock(&vst->input_lock);
mutex_unlock(&vst->output_lock); mutex_unlock(&vst->output_lock);
frames_count = 0;
}; };
int init_video(vst_t *vst)
{
Frame = av_frame_alloc();
if ( Frame == NULL )
{
printf("Cannot alloc video frame\n\r");
return 0;
};
mutex_lock(&vst->decoder_lock);
create_thread(video_thread, vst, 1024*1024);
return 1;
};
static double dts = 0.0;
static vframe_t *get_input_frame(vst_t *vst) static vframe_t *get_input_frame(vst_t *vst)
{ {
@ -115,31 +91,31 @@ static void put_output_frame(vst_t *vst, vframe_t *vframe)
}; };
}; };
}; };
vst->frames_count++;
mutex_unlock(&vst->output_lock); mutex_unlock(&vst->output_lock);
}; };
int decode_video(vst_t* vst) int decode_video(vst_t* vst)
{ {
AVPacket pkt;
double pts; double pts;
AVPacket pkt;
int frameFinished; int frameFinished;
if(vst->decoder_frame == NULL) if(vst->decoder_frame == NULL)
vst->decoder_frame = get_input_frame(vst); vst->decoder_frame = get_input_frame(vst);
if(vst->decoder_frame == NULL) if(vst->decoder_frame == NULL)
return 0; return -1;
if( get_packet(&vst->q_video, &pkt) == 0 ) if( get_packet(&vst->q_video, &pkt) == 0 )
return 0; return 0;
frameFinished = 0; frameFinished = 0;
if(dts == 0)
dts = pkt.pts;
mutex_lock(&vst->gpu_lock); mutex_lock(&vst->gpu_lock);
if(avcodec_decode_video2(vst->vCtx, Frame, &frameFinished, &pkt) <= 0) if(avcodec_decode_video2(vst->vCtx, vst->Frame, &frameFinished, &pkt) <= 0)
printf("video decoder error\n"); printf("video decoder error\n");
if(frameFinished) if(frameFinished)
@ -150,22 +126,21 @@ int decode_video(vst_t* vst)
if(vst->hwdec) if(vst->hwdec)
pts = pkt.pts; pts = pkt.pts;
else else
pts = av_frame_get_best_effort_timestamp(Frame); pts = av_frame_get_best_effort_timestamp(vst->Frame);
pts*= av_q2d(video_time_base); pts*= av_q2d(vst->video_time_base);
dst_pic = &vframe->picture; dst_pic = &vframe->picture;
if(vframe->is_hw_pic == 0) if(vframe->is_hw_pic == 0)
av_image_copy(dst_pic->data, dst_pic->linesize, av_image_copy(dst_pic->data, dst_pic->linesize,
(const uint8_t**)Frame->data, (const uint8_t**)vst->Frame->data,
Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height); vst->Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height);
else else
va_create_planar(vst, vframe); va_create_planar(vst, vframe);
vframe->pts = pts*1000.0; vframe->pts = pts*1000.0;
vframe->pkt_pts = pkt.pts*av_q2d(video_time_base)*1000.0; vframe->pkt_pts = pkt.pts*av_q2d(vst->video_time_base)*1000.0;
vframe->pkt_dts = dts*av_q2d(video_time_base)*1000.0;
vframe->ready = 1; vframe->ready = 1;
put_output_frame(vst, vframe); put_output_frame(vst, vframe);
@ -175,10 +150,8 @@ int decode_video(vst_t* vst)
// vst->vframe[vst->dfx].pkt_pts, vst->vframe[vst->dfx].pkt_dts); // vst->vframe[vst->dfx].pkt_pts, vst->vframe[vst->dfx].pkt_dts);
vst->decoder_frame = NULL; vst->decoder_frame = NULL;
frames_count++;
dts = 0;
}; };
av_frame_unref(Frame); av_frame_unref(vst->Frame);
mutex_unlock(&vst->gpu_lock); mutex_unlock(&vst->gpu_lock);
av_free_packet(&pkt); av_free_packet(&pkt);
@ -417,7 +390,7 @@ void render_time(render_t *render)
delay(1); delay(1);
return; return;
} }
else if (decoder_state == STOP && frames_count == 0 && else if (decoder_state == STOP && vst->frames_count == 0 &&
player_state != STOP) player_state != STOP)
{ {
player_stop(); player_stop();
@ -441,10 +414,11 @@ void render_time(render_t *render)
vframe = list_first_entry(&vst->output_list, vframe_t, list); vframe = list_first_entry(&vst->output_list, vframe_t, list);
list_del(&vframe->list); list_del(&vframe->list);
vst->frames_count--;
mutex_unlock(&vst->output_lock); mutex_unlock(&vst->output_lock);
ctime = get_master_clock(); ctime = get_master_clock();
fdelay = (vframe->pkt_pts - ctime); fdelay = (vframe->pts - ctime);
if(fdelay > 15.0) if(fdelay > 15.0)
{ {
@ -458,7 +432,7 @@ void render_time(render_t *render)
if(main_render->win->win_state != FULLSCREEN) if(main_render->win->win_state != FULLSCREEN)
{ {
prg->current = vframe->pkt_pts * 1000; prg->current = vframe->pts * 1000;
lvl->current = vframe->index & 1 ? sound_level_1 : sound_level_0; lvl->current = vframe->index & 1 ? sound_level_1 : sound_level_0;
send_message(&prg->ctrl, PRG_PROGRESS, 0, 0); send_message(&prg->ctrl, PRG_PROGRESS, 0, 0);
@ -467,7 +441,6 @@ void render_time(render_t *render)
send_message(&lvl->ctrl, MSG_PAINT, 0, 0); send_message(&lvl->ctrl, MSG_PAINT, 0, 0);
} }
frames_count--;
vframe->ready = 0; vframe->ready = 0;
mutex_lock(&vst->input_lock); mutex_lock(&vst->input_lock);
@ -476,9 +449,6 @@ void render_time(render_t *render)
} }
} }
extern char *movie_file;
int video_thread(void *param) int video_thread(void *param)
{ {
vst_t *vst = param; vst_t *vst = param;
@ -486,7 +456,7 @@ int video_thread(void *param)
init_winlib(); init_winlib();
MainWindow = create_window(movie_file,0, MainWindow = create_window(vst->input_name,0,
10,10,vst->vCtx->width,vst->vCtx->height+CAPTION_HEIGHT+PANEL_HEIGHT,MainWindowProc); 10,10,vst->vCtx->width,vst->vCtx->height+CAPTION_HEIGHT+PANEL_HEIGHT,MainWindowProc);
MainWindow->panel.prg->max = stream_duration; MainWindow->panel.prg->max = stream_duration;