/contrib/media/fplay/fplay.c |
---|
16,10 → 16,6 |
#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; |
30,13 → 26,8 |
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; |
int64_t stream_duration; |
46,12 → 37,6 |
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 |
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 |
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 |
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 |
&& 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 |
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 |
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 |
{ |
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 |
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,11 → 212,11 |
} |
else printf("Unsupported audio codec!\n"); |
if(!init_video(&vst)) |
return 0; |
mutex_lock(&vst.decoder_lock); |
create_thread(video_thread, &vst, 1024*1024); |
if(mutex_lock_timeout(&vst.decoder_lock, 3000) == 0) |
return -1; |
mutex_lock_timeout(&vst.decoder_lock, 3000); |
decoder(&vst); |
369,7 → 358,6 |
delay(1); |
continue; |
} |
yield(); |
continue; |
/contrib/media/fplay/fplay.h |
---|
27,7 → 27,6 |
int index; |
double pts; |
double pkt_pts; |
double pkt_dts; |
volatile int ready; |
}vframe_t; |
111,7 → 110,6 |
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 */ |
119,8 → 117,12 |
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 */ |
133,7 → 135,10 |
struct list_head input_list; |
struct list_head output_list; |
AVFrame *Frame; |
vframe_t *decoder_frame; |
volatile int frames_count; |
void *hwCtx; /* hardware context */ |
int hwdec:1; /* hardware decoder */ |
int blit_bitmap:1; /* hardware RGBA blitter */ |
140,6 → 145,8 |
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 |
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 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 |
::"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(); |
/contrib/media/fplay/vaapi.c |
---|
39,7 → 39,7 |
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,7 → 281,7 |
return 0; |
} |
static int vaapi_init_decoder(VAProfile profile, |
static int vaapi_init_decoder(vst_t *vst,VAProfile profile, |
VAEntrypoint entrypoint, |
unsigned int picture_width, |
unsigned int picture_height) |
343,7 → 343,7 |
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 |
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 |
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,10 → 419,9 |
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]; ; |
} |
} |
429,7 → 428,6 |
} |
} |
FAIL(); |
return PIX_FMT_NONE; |
} |
472,6 → 470,8 |
{ |
AVCodecContext *vCtx = vst->vCtx; |
vst->nframes = 4; |
if(va_check_codec_support(vCtx->codec_id)) |
{ |
VADisplay dpy; |
481,9 → 481,12 |
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 |
}; |
vst->hwdec = 1; |
vst->frame_reorder = 1; |
vCtx->opaque = vst; |
vCtx->thread_count = 1; |
vCtx->get_format = get_format; |
504,12 → 508,12 |
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); |
/contrib/media/fplay/video.c |
---|
21,16 → 21,10 |
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,31 → 45,13 |
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) |
{ |
vframe_t *vframe = NULL; |
115,13 → 91,15 |
}; |
}; |
}; |
vst->frames_count++; |
mutex_unlock(&vst->output_lock); |
}; |
int decode_video(vst_t* vst) |
{ |
double pts; |
AVPacket pkt; |
double pts; |
int frameFinished; |
if(vst->decoder_frame == NULL) |
128,18 → 106,16 |
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 |
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 |
// 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 |
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 |
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 |
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 |
send_message(&lvl->ctrl, MSG_PAINT, 0, 0); |
} |
frames_count--; |
vframe->ready = 0; |
mutex_lock(&vst->input_lock); |
476,9 → 449,6 |
} |
} |
extern char *movie_file; |
int video_thread(void *param) |
{ |
vst_t *vst = param; |
486,7 → 456,7 |
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; |