From d6faa0933b992c0777910a90a28054f22eae05f1 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Fri, 2 Mar 2012 10:31:15 +0000 Subject: [PATCH] FPlay UI: PAUSE and even more PAUSE git-svn-id: svn://kolibrios.org@2427 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/media/Fplay/audio.c | 145 ++++++++++++++---------- programs/media/Fplay/fplay.c | 19 +++- programs/media/Fplay/fplay.h | 9 +- programs/media/Fplay/pixlib2.c | 4 +- programs/media/Fplay/system.h | 25 +++-- programs/media/Fplay/utils.c | 2 +- programs/media/Fplay/video.c | 198 +++++++++++++++++++++------------ 7 files changed, 254 insertions(+), 148 deletions(-) diff --git a/programs/media/Fplay/audio.c b/programs/media/Fplay/audio.c index 746dc7269f..f0b70a1ca9 100644 --- a/programs/media/Fplay/audio.c +++ b/programs/media/Fplay/audio.c @@ -6,25 +6,26 @@ #include #include -#include +#include "../winlib/winlib.h" #include "sound.h" #include "fplay.h" astream_t astream; -static SNDBUF hBuff; - extern uint8_t *decoder_buffer; -extern volatile uint32_t status; +extern volatile enum player_state player_state; extern volatile uint32_t driver_lock; +static SNDBUF hBuff; static int snd_format; int sample_rate; +static uint32_t samples_written = 0; + int init_audio(int format) { int err; @@ -65,8 +66,10 @@ exit_whith_error: static uint64_t samples_lost; static double audio_delta; +static double last_time_stamp; -double get_master_clock() + +double get_master_clock(void) { double tstamp; @@ -116,13 +119,61 @@ int decode_audio(AVCodecContext *ctx, queue_t *qa) }; +static void sync_audio(SNDBUF hbuff, int buffsize) +{ + SND_EVENT evnt; + uint32_t offset; + double time_stamp; + +#ifdef BLACK_MAGIC_SOUND + + while( player_state != CLOSED) + { + GetNotify(&evnt); + + if(evnt.code != 0xFF000001) + { + printf("invalid event code %d\n\r", evnt.code); + continue; + } + + if(evnt.stream != hbuff) + { + printf("invalid stream %x hBuff= %x\n\r", + evnt.stream, hbuff); + continue; + } + + GetTimeStamp(hbuff, &time_stamp); + audio_delta = time_stamp - last_time_stamp; + + offset = evnt.offset; + + mutex_lock(&astream.lock); + { + SetBuffer(hbuff, astream.buffer, offset, buffsize); + samples_written+= buffsize/4; + astream.count -= buffsize; + if(astream.count) + memcpy(astream.buffer, astream.buffer+buffsize, astream.count); + mutex_unlock(&astream.lock); + }; + break; + }; +#endif + +}; + + int audio_thread(void *param) { SND_EVENT evnt; + int buffsize; int samples; int err; char *errstr; + int active; if((err = CreateBuffer(snd_format|PCM_RING,0, &hBuff)) != 0) @@ -144,71 +195,49 @@ int audio_thread(void *param) samples = buffsize/4; while( (astream.count < buffsize*2) && - (status != 0) ) + (player_state != CLOSED) ) yield(); mutex_lock(&astream.lock); { SetBuffer(hBuff, astream.buffer, 0, buffsize); + samples_written+= buffsize/4; astream.count -= buffsize; if(astream.count) memcpy(astream.buffer, astream.buffer+buffsize, astream.count); mutex_unlock(&astream.lock); }; - if((err = PlayBuffer(hBuff, 0)) !=0 ) - { - errstr = "Cannot play buffer\n\r"; - goto exit_whith_error; - }; - - -#ifdef BLACK_MAGIC_SOUND - - while( status != 0) - { - uint32_t offset; - - GetNotify(&evnt); - - if(evnt.code != 0xFF000001) - { - printf("invalid event code %d\n\r", evnt.code); - continue; - } - - if(evnt.stream != hBuff) - { - printf("invalid stream %x hBuff= %x\n\r", - evnt.stream, hBuff); - continue; - } - - GetTimeStamp(hBuff, &audio_delta); - samples_lost = audio_delta*sample_rate/1000; - - offset = evnt.offset; - - mutex_lock(&astream.lock); - { - SetBuffer(hBuff, astream.buffer, offset, buffsize); - astream.count -= buffsize; - if(astream.count) - memcpy(astream.buffer, astream.buffer+buffsize, astream.count); - mutex_unlock(&astream.lock); - }; - break; - }; -#endif - - printf("initial audio delta %f\n", audio_delta); - - while( status != 0) + while( player_state != CLOSED) { uint32_t offset; double event_stamp, wait_stamp; int too_late = 0; + if(player_state == PAUSE) + { + if( active ) + { + StopBuffer(hBuff); + active = 0; + } + delay(1); + continue; + } + else if(player_state == PLAY_RESTART) + { + GetTimeStamp(hBuff, &last_time_stamp); + if((err = PlayBuffer(hBuff, 0)) !=0 ) + { + errstr = "Cannot play buffer\n\r"; + goto exit_whith_error; + }; + active = 1; + sync_audio(hBuff, buffsize); + player_state = PLAY; + printf("audio delta %f\n", audio_delta); + }; + GetNotify(&evnt); if(evnt.code != 0xFF000001) @@ -229,7 +258,7 @@ int audio_thread(void *param) offset = evnt.offset; while( (astream.count < buffsize) && - (status != 0) ) + (player_state != CLOSED) ) { yield(); GetTimeStamp(hBuff, &wait_stamp); @@ -244,11 +273,15 @@ int audio_thread(void *param) } }; - if((too_late == 1) || (status == 0)) + if((too_late == 1) || (player_state == CLOSED)) + { + too_late = 0; continue; + }; mutex_lock(&astream.lock); SetBuffer(hBuff, astream.buffer, offset, buffsize); + samples_written+= buffsize/4; astream.count -= buffsize; if(astream.count) memcpy(astream.buffer, astream.buffer+buffsize, astream.count); diff --git a/programs/media/Fplay/fplay.c b/programs/media/Fplay/fplay.c index 527eed3c98..17703d7532 100644 --- a/programs/media/Fplay/fplay.c +++ b/programs/media/Fplay/fplay.c @@ -10,12 +10,12 @@ #include #include #include -#include +#include "../winlib/winlib.h" #include "sound.h" #include "fplay.h" -volatile uint32_t status = 1; +volatile enum player_state player_state; uint32_t win_width, win_height; @@ -102,6 +102,8 @@ int main( int argc, char *argv[]) return -1; // Didn't find a video stream } + player_state = PLAY_RESTART; + // __asm__ __volatile__("int3"); // Get a pointer to the codec context for the video stream @@ -204,12 +206,18 @@ void decoder() AVPacket packet; int ret; - while( status != 0 && !eof) + while( player_state != CLOSED && !eof) { int err; // __asm__ __volatile__("int3"); + if( player_state == PAUSE ) + { + delay(1); + continue; + }; + if(q_video.size+q_audio.size < 12*1024*1024) { err = av_read_frame(pFormatCtx, &packet); @@ -244,15 +252,14 @@ void decoder() ret = 1; - while( (status != 0) && ret) + while( (player_state != CLOSED) && ret) { ret = decode_video(pCodecCtx, &q_video); ret |= decode_audio(aCodecCtx, &q_audio); delay(1); }; delay(50); - status = 0; - printf("status = 0\n"); + player_state = CLOSED; delay(300); }; diff --git a/programs/media/Fplay/fplay.h b/programs/media/Fplay/fplay.h index c6f3dfab58..74c5b8a66c 100644 --- a/programs/media/Fplay/fplay.h +++ b/programs/media/Fplay/fplay.h @@ -38,6 +38,8 @@ struct render uint32_t layout; bitmap_t bitmap[4]; + bitmap_t *last_bitmap; + uint32_t ctx_format; int target; @@ -49,6 +51,11 @@ struct render void (*draw)(render_t *render, AVPicture *picture); }; +enum player_state +{ CLOSED=0, STOP, PLAY_RESTART, PLAY, PAUSE, REWIND }; + +#define ID_PLAY 100 + typedef struct { volatile uint32_t lock; @@ -109,7 +116,7 @@ int video_thread(void *param); int decode_video(AVCodecContext *ctx, queue_t *qv); int decode_audio(AVCodecContext *ctx, queue_t *qa); -double get_master_clock(); +double get_master_clock(void); int create_thread(int (*proc)(void *param), void *param, int stack_size); diff --git a/programs/media/Fplay/pixlib2.c b/programs/media/Fplay/pixlib2.c index 688b7fa19b..88ca6d2340 100644 --- a/programs/media/Fplay/pixlib2.c +++ b/programs/media/Fplay/pixlib2.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include "../winlib/winlib.h" #include "fplay.h" #define DISPLAY_VERSION 0x0200 /* 2.00 */ @@ -339,7 +339,7 @@ static inline void* user_realloc(void *mem, size_t size) void *val; __asm__ __volatile__( "int $0x40" - :"=eax"(val) + :"=a"(val) :"a"(68),"b"(12),"c"(size),"d"(mem) :"memory"); diff --git a/programs/media/Fplay/system.h b/programs/media/Fplay/system.h index 50522a4813..f2437c0388 100644 --- a/programs/media/Fplay/system.h +++ b/programs/media/Fplay/system.h @@ -67,7 +67,7 @@ pos_t get_mouse_pos(void) __asm__ __volatile__( "int $0x40 \n\t" "rol $16, %%eax" - :"=eax"(val) + :"=a"(val) :"a"(37),"b"(1)); return val; } @@ -80,7 +80,7 @@ pos_t get_cursor_pos(void) __asm__ __volatile__( "int $0x40 \n\t" "rol $16, %%eax" - :"=eax"(val) + :"=a"(val) :"a"(37),"b"(0)); return val; } @@ -137,7 +137,7 @@ uint32_t get_tick_count(void) uint32_t val; __asm__ __volatile__( "int $0x40" - :"=eax"(val) + :"=a"(val) :"a"(26),"b"(9)); return val; }; @@ -148,7 +148,7 @@ oskey_t get_key(void) oskey_t val; __asm__ __volatile__( "int $0x40" - :"=eax"(val) + :"=a"(val) :"a"(2)); return val; } @@ -201,7 +201,7 @@ void *user_alloc(size_t size) void *val; __asm__ __volatile__( "int $0x40" - :"=eax"(val) + :"=a"(val) :"a"(68),"b"(12),"c"(size)); return val; } @@ -212,7 +212,7 @@ int user_free(void *mem) int val; __asm__ __volatile__( "int $0x40" - :"=eax"(val) + :"=a"(val) :"a"(68),"b"(12),"c"(mem)); return val; } @@ -223,7 +223,7 @@ int *user_unmap(void *base, size_t offset, size_t size) void *val; __asm__ __volatile__( "int $0x40" - :"=eax"(val) + :"=a"(val) :"a"(68),"b"(26),"c"(base),"d"(offset),"S"(size)); return val; } @@ -248,7 +248,7 @@ uint32_t load_cursor(void *path, uint32_t flags) uint32_t val; __asm__ __volatile__( "int $0x40" - :"=eax"(val) + :"=a"(val) :"a"(37), "b"(4), "c"(path), "d"(flags)); return val; } @@ -259,7 +259,7 @@ uint32_t set_cursor(uint32_t cursor) uint32_t old; __asm__ __volatile__( "int $0x40" - :"=eax"(old) + :"=a"(old) :"a"(37), "b"(5), "c"(cursor)); return old; } @@ -278,7 +278,7 @@ void* user_realloc(void *mem, size_t size) void *val; __asm__ __volatile__( "int $0x40" - :"=eax"(val) + :"=a"(val) :"a"(68),"b"(12),"c"(size),"d"(mem) :"memory"); @@ -309,3 +309,8 @@ void Blit(void *bitmap, int dst_x, int dst_y, int src_x, int src_y, int w, int h, int src_w, int src_h, int stride); + + + + + diff --git a/programs/media/Fplay/utils.c b/programs/media/Fplay/utils.c index 1e7f8311ee..9e5b55f3a5 100644 --- a/programs/media/Fplay/utils.c +++ b/programs/media/Fplay/utils.c @@ -5,7 +5,7 @@ #include #include #include -#include +#include "../winlib/winlib.h" #include "fplay.h" extern uint32_t hw2d ; diff --git a/programs/media/Fplay/video.c b/programs/media/Fplay/video.c index 92ca24d6d8..ace1998b13 100644 --- a/programs/media/Fplay/video.c +++ b/programs/media/Fplay/video.c @@ -5,12 +5,19 @@ #include #include #include "system.h" -#include +#include "../winlib/winlib.h" #include "sound.h" #include "fplay.h" #define CAPTION_HEIGHT 24 +extern int res_pause_btn[]; +extern int res_pause_btn_pressed[]; + +extern int res_play_btn[]; +extern int res_play_btn_pressed[]; + + typedef struct { AVPicture picture; @@ -98,6 +105,7 @@ int decode_video(AVCodecContext *ctx, queue_t *qv) AVPacket pkt; double pts; int frameFinished; + double current_clock; if(frames[dfx].ready != 0 ) return 1; @@ -105,25 +113,38 @@ int decode_video(AVCodecContext *ctx, queue_t *qv) if( get_packet(qv, &pkt) == 0 ) return 0; - frameFinished = 0; + current_clock = -80.0 + get_master_clock(); - ctx->reordered_opaque = pkt.pts; - - if(avcodec_decode_video2(ctx, Frame, &frameFinished, &pkt) <= 0) - printf("video decoder error\n"); - - if(frameFinished) - { - AVPicture *dst_pic; - - - if( pkt.dts == AV_NOPTS_VALUE && - Frame->reordered_opaque != AV_NOPTS_VALUE) - pts = Frame->reordered_opaque; + if( pkt.dts == AV_NOPTS_VALUE && + Frame->reordered_opaque != AV_NOPTS_VALUE) + pts = Frame->reordered_opaque; else if(pkt.dts != AV_NOPTS_VALUE) - pts= pkt.dts; - else - pts= 0; + pts= pkt.dts; + else + pts= 0; + + pts *= av_q2d(video_time_base)*1000.0; + + if( pts > current_clock) + { + frameFinished = 0; + + ctx->reordered_opaque = pkt.pts; + + if(avcodec_decode_video2(ctx, Frame, &frameFinished, &pkt) <= 0) + printf("video decoder error\n"); + + if(frameFinished) + { + AVPicture *dst_pic; + + if( pkt.dts == AV_NOPTS_VALUE && + Frame->reordered_opaque != AV_NOPTS_VALUE) + pts = Frame->reordered_opaque; + else if(pkt.dts != AV_NOPTS_VALUE) + pts= pkt.dts; + else + pts= 0; // pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(), // Frame, "best_effort_timestamp"); @@ -131,27 +152,28 @@ int decode_video(AVCodecContext *ctx, queue_t *qv) // if (pts == AV_NOPTS_VALUE) // pts = 0; - pts *= av_q2d(video_time_base); + pts *= av_q2d(video_time_base); - dst_pic = &frames[dfx].picture; + dst_pic = &frames[dfx].picture; - av_image_copy(dst_pic->data, dst_pic->linesize, + av_image_copy(dst_pic->data, dst_pic->linesize, (const uint8_t**)Frame->data, Frame->linesize, ctx->pix_fmt, ctx->width, ctx->height); - frames[dfx].pts = pts*1000.0; - frames[dfx].ready = 1; + frames[dfx].pts = pts*1000.0; + frames[dfx].ready = 1; - dfx++; - dfx&= 3; + dfx++; + dfx&= 3; + }; }; av_free_packet(&pkt); return 1; } -extern volatile uint32_t status; -rect_t win_rect; +extern volatile enum player_state player_state; +//rect_t win_rect; int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) @@ -171,12 +193,48 @@ int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) render_draw_client(main_render); break; + case MSG_LBTNDOWN: + if(player_state == PAUSE) + { + win->panel.play_btn->img_default = res_play_btn; + win->panel.play_btn->img_hilite = res_play_btn; + win->panel.play_btn->img_pressed = res_play_btn_pressed; + send_message(win->panel.play_btn, MSG_PAINT, 0, 0); + player_state = PLAY_RESTART; + + } + else if(player_state == PLAY) + { + win->panel.play_btn->img_default = res_pause_btn; + win->panel.play_btn->img_hilite = res_pause_btn; + win->panel.play_btn->img_pressed = res_pause_btn_pressed; + send_message(win->panel.play_btn, MSG_PAINT, 0, 0); + player_state = PAUSE; + } + break; + case MSG_COMMAND: switch((short)arg1) { - case ID_CLOSE: - exit(0); - }; + case ID_PLAY: + if(player_state == PAUSE) + { + win->panel.play_btn->img_default = res_play_btn; + win->panel.play_btn->img_hilite = res_play_btn; + win->panel.play_btn->img_pressed = res_play_btn_pressed; + player_state = PLAY_RESTART; + } + else if(player_state == PLAY) + { + win->panel.play_btn->img_default = res_pause_btn; + win->panel.play_btn->img_hilite = res_pause_btn; + win->panel.play_btn->img_pressed = res_pause_btn_pressed; + player_state = PAUSE; + } + break; + default: + break; + } break; default: @@ -187,13 +245,20 @@ int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) void render_time(render_t *render) { - double ctime; - double fdelay; + double ctime; /* milliseconds */ + double fdelay; /* milliseconds */ - if(status == 0) +//again: + + if(player_state == CLOSED) { render->win->win_command = WIN_CLOSED; return; + } + else if(player_state != PLAY) + { + yield(); + return; }; if(frames[vfx].ready == 1 ) @@ -201,40 +266,13 @@ void render_time(render_t *render) ctime = get_master_clock(); fdelay = (frames[vfx].pts - ctime); -// printf("pts %f time %f delay %f\n", -// frames[vfx].pts, ctime, fdelay); +// printf("pts %f time %f delay %f\n", + // frames[vfx].pts, ctime, fdelay); - if(fdelay < 0.0 ) + if(fdelay > 20.0) { - int next_vfx; - fdelay = 0; - next_vfx = (vfx+1) & 3; - if( frames[next_vfx].ready == 1 ) - { - if(frames[next_vfx].pts <= ctime) - { - frames[vfx].ready = 0; // skip this frame - vfx++; - vfx&= 3; - } - else - { - if( (frames[next_vfx].pts - ctime) < - ( ctime - frames[vfx].pts) ) - { - frames[vfx].ready = 0; // skip this frame - vfx++; - vfx&= 3; - fdelay = (frames[next_vfx].pts - ctime); - } - } - }; - }; - - if(fdelay > 10.0) - { - // delay( (uint32_t)(fdelay/10.0)); - yield(); + delay(2); +// yield(); return; }; @@ -242,9 +280,14 @@ void render_time(render_t *render) frames[vfx].ready = 0; vfx++; vfx&= 3; - }; + } + else yield(); + } + + + extern char *movie_file; int video_thread(void *param) @@ -254,7 +297,7 @@ int video_thread(void *param) init_winlib(); MainWindow = create_window(movie_file,0, - 10,10,width+14,height+29,MainWindowProc); + 10,10,width,height+29+75,MainWindowProc); // printf("MainWindow %x\n", MainWindow); @@ -264,7 +307,7 @@ int video_thread(void *param) run_render(MainWindow, main_render); // printf("exit thread\n"); - status = 0; + player_state = CLOSED; return 0; }; @@ -366,7 +409,7 @@ int render_set_size(render_t *render, int width, int height) if( create_bitmap(&render->bitmap[i]) != 0 ) { - status = 0; + player_state = CLOSED; /* * Epic fail. Need exit_thread() here * @@ -405,7 +448,7 @@ void render_adjust_size(render_t *render, window_t *win) right = win->w; - bottom = win->h-CAPTION_HEIGHT; + bottom = win->h-CAPTION_HEIGHT-75; render->win_state = win->win_state; if(render->win_state == MINIMIZED) @@ -439,7 +482,7 @@ void render_adjust_size(render_t *render, window_t *win) }; render->win_width = win->w; - render->win_height = win->h-CAPTION_HEIGHT; + render->win_height = win->h-CAPTION_HEIGHT-75; render_set_size(render, new_w, new_h); }; @@ -451,7 +494,8 @@ void draw_hw_picture(render_t *render, AVPicture *picture) int linesize[4]; int ret; - if(render->win_state == ROLLED) + if(render->win_state == MINIMIZED || + render->win_state == ROLLED) return; if(render->caps & HW_TEX_BLIT) @@ -502,6 +546,7 @@ void draw_hw_picture(render_t *render, AVPicture *picture) blit_bitmap(bitmap, render->rcvideo.l, CAPTION_HEIGHT+render->rcvideo.t, render->rcvideo.r, render->rcvideo.b); + render->last_bitmap = bitmap; // printf("blit_bitmap\n"); @@ -546,6 +591,7 @@ void draw_sw_picture(render_t *render, AVPicture *picture) blit_bitmap(&render->bitmap[0], render->rcvideo.l, render->rcvideo.t+CAPTION_HEIGHT, render->rcvideo.r, render->rcvideo.b); + render->last_bitmap = &render->bitmap[0]; } void render_draw_client(render_t *render) @@ -554,6 +600,11 @@ void render_draw_client(render_t *render) render->win_state == ROLLED) return; + if(player_state == PAUSE) + { + main_render->draw(main_render, &frames[vfx].picture); + }; + if(render->layout & HAS_TOP) draw_bar(0, CAPTION_HEIGHT, render->win_width, render->rctop.b, 0); @@ -569,3 +620,6 @@ void render_draw_client(render_t *render) } + + +