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 "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 decoder_state = PREPARE;
volatile enum player_state sound_state = STOP;
uint32_t win_width, win_height;
int have_sound = 0;
int have_sound = 0;
uint8_t *decoder_buffer;
extern int resampler_size;
extern int sample_rate;
char *movie_file;
void flush_video(vst_t* vst);
int64_t rewind_pos;
@ -46,12 +37,6 @@ int threads_running = DECODER_THREAD;
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[])
{
static vst_t vst;
@ -60,14 +45,14 @@ int main( int argc, char *argv[])
if(argc < 2)
{
movie_file = get_moviefile();
if(movie_file == NULL)
vst.input_file = get_moviefile();
if(vst.input_file == NULL)
{
printf("Please provide a movie file\n");
return -1;
}
}
else movie_file = argv[1];
else vst.input_file = argv[1];
/* register all codecs, demux and protocols */
@ -77,9 +62,9 @@ int main( int argc, char *argv[])
avdevice_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
};
@ -92,15 +77,15 @@ int main( int argc, char *argv[])
return -1;
};
file_name = strrchr(movie_file,'/')+1;
file_name = strrchr(vst.input_file,'/')+1;
dot = strrchr(file_name,'.');
if(dot)
{
movie_file = malloc(dot-file_name+1);
memcpy(movie_file, file_name, dot-file_name);
movie_file[dot-file_name] = 0;
vst.input_name = malloc(dot-file_name+1);
memcpy(vst.input_name, file_name, dot-file_name);
vst.input_name[dot-file_name] = 0;
}
else movie_file = file_name;
else vst.input_name = file_name;
stream_duration = vst.fCtx->duration;
@ -114,7 +99,7 @@ int main( int argc, char *argv[])
&& vst.vStream < 0)
{
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)
stream_duration = vst.fCtx->streams[i]->duration;
}
@ -123,6 +108,7 @@ int main( int argc, char *argv[])
vst.aStream < 0)
{
vst.aStream = i;
vst.audio_time_base = vst.fCtx->streams[i]->time_base;
if(stream_duration == 0)
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.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.output_list);
@ -157,9 +141,16 @@ int main( int argc, char *argv[])
{
printf("Unsupported codec with id %d for input stream %d\n",
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))
return -1;
@ -170,8 +161,6 @@ int main( int argc, char *argv[])
return -1; // Could not open codec
};
printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt);
if (vst.aCtx->channels > 0)
vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels);
else
@ -223,10 +212,10 @@ int main( int argc, char *argv[])
}
else printf("Unsupported audio codec!\n");
if(!init_video(&vst))
return 0;
mutex_lock_timeout(&vst.decoder_lock, 3000);
mutex_lock(&vst.decoder_lock);
create_thread(video_thread, &vst, 1024*1024);
if(mutex_lock_timeout(&vst.decoder_lock, 3000) == 0)
return -1;
decoder(&vst);
@ -369,7 +358,6 @@ void decoder(vst_t* vst)
delay(1);
continue;
}
yield();
continue;

View File

@ -27,7 +27,6 @@ typedef struct
int index;
double pts;
double pkt_pts;
double pkt_dts;
volatile int ready;
}vframe_t;
@ -111,21 +110,24 @@ typedef struct {
int put_packet(queue_t *q, AVPacket *pkt);
int get_packet(queue_t *q, AVPacket *pkt);
#define HWDEC_NUM_SURFACES 16
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 */
char *input_file;
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_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 :( */
mutex_t gpu_lock; /* gpu access lock. libdrm not yet thread safe :( */
mutex_t decoder_lock;
mutex_t input_lock;
@ -133,13 +135,18 @@ struct vstate
struct list_head input_list;
struct list_head output_list;
AVFrame *Frame;
vframe_t *decoder_frame;
void *hwCtx; /* hardware context */
int hwdec:1; /* hardware decoder */
int blit_bitmap:1; /* hardware RGBA blitter */
int blit_texture:1; /* hardware RGBA blit and scale */
int blit_planar:1; /* hardbare YUV blit and scale */
volatile int frames_count;
void *hwCtx; /* hardware context */
int hwdec:1; /* hardware decoder */
int blit_bitmap:1; /* hardware RGBA blitter */
int blit_texture:1; /* hardware RGBA blit and scale */
int blit_planar:1; /* hardbare YUV blit and scale */
int frame_reorder:1;
int nframes;
vframe_t vframes[16];
};
@ -149,7 +156,6 @@ struct vstate
extern int threads_running;
extern astream_t astream;
extern AVRational video_time_base;
render_t *create_render(vst_t *vst, window_t *win, uint32_t flags);
void destroy_render(render_t *render);
@ -164,8 +170,8 @@ int init_audio(int format);
int audio_thread(void *param);
void set_audio_volume(int left, int right);
int init_video(vst_t* vst);
int video_thread(void *param);
void flush_video(vst_t* vst);
void decoder(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));
}
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);
int init_fontlib();

View File

@ -39,7 +39,7 @@ struct hw_profile
static int drm_fd = 0;
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_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;
}
static int vaapi_init_decoder(VAProfile profile,
VAEntrypoint entrypoint,
unsigned int picture_width,
unsigned int picture_height)
static int vaapi_init_decoder(vst_t *vst,VAProfile profile,
VAEntrypoint entrypoint,
unsigned int picture_width,
unsigned int picture_height)
{
struct vaapi_context* const vaapi = v_context;
VAConfigAttrib attrib;
@ -343,7 +343,7 @@ ENTER();
printf("vaCreateSurfaces %dx%d\n",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()"))
{
FAIL();
@ -378,7 +378,7 @@ ENTER();
status = vaCreateContext(vaapi->display, config_id,
picture_width, picture_height,
VA_PROGRESSIVE,
v_surface_id, HWDEC_NUM_SURFACES,
v_surface_id, vst->nframes,
&context_id);
if (!vaapi_check_status(status, "vaCreateContext()"))
{
@ -396,9 +396,9 @@ ENTER();
static enum PixelFormat get_format(struct AVCodecContext *avctx,
const enum AVPixelFormat *fmt)
{
vst_t *vst = (vst_t*)avctx->opaque;
VAProfile profile = VAProfileNone;
ENTER();
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)
{
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;
LEAVE();
return fmt[i]; ;
}
}
}
}
FAIL();
return PIX_FMT_NONE;
}
@ -472,6 +470,8 @@ int fplay_init_context(vst_t *vst)
{
AVCodecContext *vCtx = vst->vCtx;
vst->nframes = 4;
if(va_check_codec_support(vCtx->codec_id))
{
VADisplay dpy;
@ -481,9 +481,12 @@ int fplay_init_context(vst_t *vst)
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->is_hw_pic = 1;
@ -494,6 +497,7 @@ int fplay_init_context(vst_t *vst)
};
vst->hwdec = 1;
vst->frame_reorder = 1;
vCtx->opaque = vst;
vCtx->thread_count = 1;
vCtx->get_format = get_format;
@ -504,12 +508,12 @@ int fplay_init_context(vst_t *vst)
vst->hwdec = 0;
for(int i = 0; i < HWDEC_NUM_SURFACES; i++)
for(int i = 0; i < vst->nframes; i++)
{
vframe_t *vframe;
int ret;
vframe = calloc(1, sizeof(*vframe));
vframe = &vst->vframes[i];
ret = avpicture_alloc(&vframe->picture, vst->vCtx->pix_fmt,
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_1;
volatile int frames_count = 0;
struct SwsContext *cvt_ctx = NULL;
render_t *main_render;
AVRational video_time_base;
AVFrame *Frame;
void get_client_rect(rect_t *rc);
void run_render(window_t *win, void *render);
void window_update_layout(window_t *win);
@ -51,30 +45,12 @@ void flush_video(vst_t *vst)
vframe->pts = 0;
vframe->ready = 0;
}
vst->frames_count = 0;
mutex_unlock(&vst->input_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)
{
@ -115,31 +91,31 @@ static void put_output_frame(vst_t *vst, vframe_t *vframe)
};
};
};
vst->frames_count++;
mutex_unlock(&vst->output_lock);
};
int decode_video(vst_t* vst)
{
AVPacket pkt;
double pts;
AVPacket pkt;
int frameFinished;
if(vst->decoder_frame == NULL)
vst->decoder_frame = get_input_frame(vst);
if(vst->decoder_frame == NULL)
return 0;
return -1;
if( get_packet(&vst->q_video, &pkt) == 0 )
return 0;
frameFinished = 0;
if(dts == 0)
dts = pkt.pts;
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");
if(frameFinished)
@ -150,22 +126,21 @@ int decode_video(vst_t* vst)
if(vst->hwdec)
pts = pkt.pts;
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;
if(vframe->is_hw_pic == 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);
(const uint8_t**)vst->Frame->data,
vst->Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height);
else
va_create_planar(vst, vframe);
vframe->pts = pts*1000.0;
vframe->pkt_pts = pkt.pts*av_q2d(video_time_base)*1000.0;
vframe->pkt_dts = dts*av_q2d(video_time_base)*1000.0;
vframe->pkt_pts = pkt.pts*av_q2d(vst->video_time_base)*1000.0;
vframe->ready = 1;
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->decoder_frame = NULL;
frames_count++;
dts = 0;
};
av_frame_unref(Frame);
av_frame_unref(vst->Frame);
mutex_unlock(&vst->gpu_lock);
av_free_packet(&pkt);
@ -417,7 +390,7 @@ void render_time(render_t *render)
delay(1);
return;
}
else if (decoder_state == STOP && frames_count == 0 &&
else if (decoder_state == STOP && vst->frames_count == 0 &&
player_state != STOP)
{
player_stop();
@ -441,10 +414,11 @@ void render_time(render_t *render)
vframe = list_first_entry(&vst->output_list, vframe_t, list);
list_del(&vframe->list);
vst->frames_count--;
mutex_unlock(&vst->output_lock);
ctime = get_master_clock();
fdelay = (vframe->pkt_pts - ctime);
fdelay = (vframe->pts - ctime);
if(fdelay > 15.0)
{
@ -458,7 +432,7 @@ void render_time(render_t *render)
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;
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);
}
frames_count--;
vframe->ready = 0;
mutex_lock(&vst->input_lock);
@ -476,9 +449,6 @@ void render_time(render_t *render)
}
}
extern char *movie_file;
int video_thread(void *param)
{
vst_t *vst = param;
@ -486,7 +456,7 @@ int video_thread(void *param)
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);
MainWindow->panel.prg->max = stream_duration;