Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 6132 → Rev 6133

/contrib/media/fplay/video.c
28,35 → 28,38
 
render_t *main_render;
 
int width;
int height;
 
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);
int fini_winlib();
 
void flush_video(vst_t *vst)
{
int i;
vframe_t *vframe, *tmp;
 
for(i = 0; i < 4; i++)
mutex_lock(&vst->output_lock);
mutex_lock(&vst->input_lock);
 
list_for_each_entry_safe(vframe, tmp, &vst->output_list, list)
list_move_tail(&vframe->list, &vst->input_list);
 
list_for_each_entry(vframe, &vst->output_list, list)
{
vst->vframe[i].pts = 0;
vst->vframe[i].ready = 0;
};
vst->vfx = 0;
vst->dfx = 0;
vframe->pts = 0;
vframe->ready = 0;
}
 
mutex_unlock(&vst->input_lock);
mutex_unlock(&vst->output_lock);
 
frames_count = 0;
};
 
int init_video(vst_t *vst)
{
int i;
 
width = vst->vCtx->width;
height = vst->vCtx->height;
 
Frame = av_frame_alloc();
if ( Frame == NULL )
{
64,45 → 67,45
return 0;
};
 
mutex_lock(&vst->decoder_lock);
 
create_thread(video_thread, vst, 1024*1024);
 
delay(50);
return 1;
};
 
static double dts = 0.0;
 
int decode_video(vst_t* vst)
{
AVPacket pkt;
double pts;
int frameFinished;
double current_clock;
 
if(vst->vframe[vst->dfx].ready != 0 )
if(vst->decoder_frame == NULL)
{
mutex_lock(&vst->input_lock);
if(list_empty(&vst->input_list))
{
mutex_unlock(&vst->input_lock);
return -1;
}
vst->decoder_frame = list_first_entry(&vst->input_list, vframe_t, list);
list_del(&vst->decoder_frame->list);
mutex_unlock(&vst->input_lock);
 
vframe_t *vframe = vst->decoder_frame;
};
 
if( get_packet(&vst->q_video, &pkt) == 0 )
{
return 0;
};
 
/*
current_clock = -90.0 + get_master_clock();
 
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 *= av_q2d(video_time_base)*1000.0;
*/
if( 1 /*pts > current_clock*/)
{
frameFinished = 0;
if(dts == 0)
dts = pkt.pts;
 
vst->vCtx->reordered_opaque = pkt.pts;
 
mutex_lock(&vst->gpu_lock);
 
if(avcodec_decode_video2(vst->vCtx, Frame, &frameFinished, &pkt) <= 0)
110,35 → 113,67
 
if(frameFinished)
{
vframe_t *vframe;
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 = av_frame_get_best_effort_timestamp(Frame);
pts *= av_q2d(video_time_base);
 
dst_pic = &vst->vframe[vst->dfx].picture;
vframe = vst->decoder_frame;
dst_pic = &vframe->picture;
 
if(vst->hwdec == 0)
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);
else
va_convert_picture(vst, vst->vCtx->width, vst->vCtx->height, dst_pic);
va_create_planar(vst, vframe);
 
vst->vframe[vst->dfx].pts = pts*1000.0;
vst->vframe[vst->dfx].ready = 1;
vst->dfx = (vst->dfx + 1) & 3;
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->ready = 1;
 
 
mutex_lock(&vst->output_lock);
 
if(list_empty(&vst->output_list))
list_add_tail(&vframe->list, &vst->output_list);
else
{
vframe_t *cur;
 
cur = list_first_entry(&vst->output_list,vframe_t,list);
if(vframe->pkt_pts < cur->pkt_pts)
{
list_add_tail(&vframe->list, &vst->output_list);
}
else
{
list_for_each_entry_reverse(cur,&vst->output_list,list)
{
if(vframe->pkt_pts > cur->pkt_pts)
{
list_add(&vframe->list, &cur->list);
break;
};
};
};
};
mutex_unlock(&vst->output_lock);
 
 
// printf("decoded index: %d pts: %f pkt_pts %f pkt_dts %f\n",
// vst->dfx, vst->vframe[vst->dfx].pts,
// vst->vframe[vst->dfx].pkt_pts, vst->vframe[vst->dfx].pkt_dts);
 
vst->decoder_frame = NULL;
frames_count++;
dts = 0;
};
av_frame_unref(Frame);
mutex_unlock(&vst->gpu_lock);
 
};
av_free_packet(&pkt);
 
return 1;
357,8 → 392,6
return 0;
};
 
#define VERSION_A 1
 
void render_time(render_t *render)
{
progress_t *prg = main_render->win->panel.prg;
367,8 → 400,6
double ctime; /* milliseconds */
double fdelay; /* milliseconds */
 
//again:
 
if(player_state == CLOSED)
{
render->win->win_command = WIN_CLOSED;
390,51 → 421,38
return;
};
 
 
#ifdef VERSION_A
if(vst->vframe[vst->vfx].ready == 1 )
mutex_lock(&vst->output_lock);
if(list_empty(&vst->output_list))
{
mutex_unlock(&vst->output_lock);
delay(1);
}
else
{
vframe_t *vframe;
int sys_time;
 
vframe = list_first_entry(&vst->output_list, vframe_t, list);
list_del(&vframe->list);
mutex_unlock(&vst->output_lock);
 
ctime = get_master_clock();
fdelay = (vst->vframe[vst->vfx].pts - ctime);
fdelay = (vframe->pkt_pts - ctime);
 
// printf("pts %f time %f delay %f\n",
// frames[vfx].pts, ctime, fdelay);
 
if(fdelay > 15.0)
{
delay((int)fdelay/10);
// return;
};
#if 0
ctime = get_master_clock();
fdelay = (vst->vframe[vst->vfx].pts - ctime);
 
// while(fdelay > 0)
// {
// yield();
// ctime = get_master_clock();
// fdelay = (frames[vfx].pts - ctime);
// }
// printf("output index: %d pts: %f pkt_pts %f pkt_dts %f\n",
// vframe->index,vframe->pts,vframe->pkt_pts,vframe->pkt_dts);
 
// sys_time = get_tick_count();
main_render->draw(main_render, vframe);
 
// if(fdelay < 0)
// printf("systime %d pts %f time %f delay %f\n",
// sys_time*10, frames[vfx].pts, ctime, fdelay);
 
printf("pts %f time %f delay %f\n",
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, &vst->vframe[vst->vfx].picture);
if(main_render->win->win_state != FULLSCREEN)
{
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;
prg->current = vframe->pkt_pts * 1000;
lvl->current = vframe->index & 1 ? sound_level_1 : sound_level_0;
 
send_message(&prg->ctrl, PRG_PROGRESS, 0, 0);
 
443,72 → 461,15
}
 
frames_count--;
vst->vframe[vst->vfx].ready = 0;
vst->vfx = (vst->vfx + 1) & 3;
}
else delay(1);
vframe->ready = 0;
 
#else
 
if(vst->vframe[vfx].ready == 1 )
{
ctime = get_master_clock();
fdelay = (vst->vrame[vst->vfx].pts - ctime);
 
// printf("pts %f time %f delay %f\n",
// frames[vfx].pts, ctime, fdelay);
 
if(fdelay < 0.0 )
{
int next_vfx;
fdelay = 0;
next_vfx = (vst->vfx+1) & 3;
if( vst->vrame[next_vfx].ready == 1 )
{
if(vst->vrame[next_vfx].pts <= ctime)
{
vst->vrame[vst->vfx].ready = 0; // skip this frame
vst->vfx = (vst->vfx + 1) & 3;
mutex_lock(&vst->input_lock);
list_add_tail(&vframe->list, &vst->input_list);
mutex_unlock(&vst->input_lock);
}
else
{
if( (vst->vrame[next_vfx].pts - ctime) <
( ctime - frames[vst->vfx].pts) )
{
vst->vrame[vst->vfx].ready = 0; // skip this frame
vst->vfx = (vst->vfx + 1) & 3;
fdelay = (vst->vrame[next_vfx].pts - ctime);
}
}
};
};
 
if(fdelay > 10.0)
{
int val = fdelay;
printf("pts %f time %f delay %d\n",
vst->vrame[vst->vfx].pts, ctime, val);
delay(val/10);
};
 
ctime = get_master_clock();
fdelay = (vst->vrame[vst->vfx].pts - ctime);
 
printf("pts %f time %f delay %f\n",
vst->vrame[vst->vfx].pts, ctime, fdelay);
 
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);
vst->vrame[vst->vfx].ready = 0;
vst->vfx = (vst->vfx + 1) & 3;
}
else yield();
#endif
 
}
 
 
extern char *movie_file;
 
int video_thread(void *param)
519,7 → 480,7
init_winlib();
 
MainWindow = create_window(movie_file,0,
10,10,width,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;
 
528,6 → 489,7
main_render = create_render(vst, MainWindow, HW_TEX_BLIT|HW_BIT_BLIT);
if( main_render == NULL)
{
mutex_unlock(&vst->decoder_lock);
printf("Cannot create render\n\r");
return 0;
};
537,6 → 499,8
render_draw_client(main_render);
player_state = PLAY;
 
mutex_unlock(&vst->decoder_lock);
 
run_render(MainWindow, main_render);
 
__sync_and_and_fetch(&threads_running,~VIDEO_THREAD);
548,8 → 512,8
};
 
 
void draw_hw_picture(render_t *render, AVPicture *picture);
void draw_sw_picture(render_t *render, AVPicture *picture);
void draw_hw_picture(render_t *render, vframe_t *vframe);
void draw_sw_picture(render_t *render, vframe_t *vframe);
 
render_t *create_render(vst_t *vst, window_t *win, uint32_t flags)
{
783,8 → 747,26
return;
};
 
void draw_hw_picture(render_t *render, AVPicture *picture)
static void render_hw_planar(render_t *render, vframe_t *vframe)
{
vst_t *vst = render->vst;
planar_t *planar = vframe->planar;
 
if(vframe->is_hw_pic != 0 && vframe->format != AV_PIX_FMT_NONE)
{
mutex_lock(&render->vst->gpu_lock);
 
pxBlitPlanar(planar, render->rcvideo.l,
CAPTION_HEIGHT+render->rcvideo.t,
render->rcvideo.r, render->rcvideo.b,0,0);
mutex_unlock(&render->vst->gpu_lock);
 
}
};
 
void draw_hw_picture(render_t *render, vframe_t *vframe)
{
AVPicture *picture;
int dst_width;
int dst_height;
bitmap_t *bitmap;
794,6 → 776,8
int linesize[4];
enum AVPixelFormat format;
 
vst_t *vst = render->vst;
 
if(render->win->win_state == MINIMIZED ||
render->win->win_state == ROLLED)
return;
809,9 → 793,16
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, format,
if(vst->hwdec)
{
render_hw_planar(render, vframe);
return;
};
 
picture = &vframe->picture;
 
format = render->vst->hwdec == 0 ? render->ctx_format : AV_PIX_FMT_BGRA;
cvt_ctx = sws_getCachedContext(cvt_ctx, 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)
829,7 → 820,6
return ;
}
 
// printf("sws_getCachedContext\n");
data[0] = bitmap_data;
data[1] = bitmap_data+1;
data[2] = bitmap_data+2;
874,8 → 864,9
render->target&= 1;
}
 
void draw_sw_picture(render_t *render, AVPicture *picture)
void draw_sw_picture(render_t *render, vframe_t *vframe)
{
AVPicture *picture;
uint8_t *bitmap_data;
uint32_t bitmap_pitch;
uint8_t *data[4];
885,6 → 876,8
render->win->win_state == ROLLED)
return;
 
picture = &vframe->picture;
 
cvt_ctx = sws_getCachedContext(cvt_ctx,
render->ctx_width, render->ctx_height,
render->ctx_format,
937,9 → 930,9
 
if(player_state == PAUSE)
{
if(vst->vframe[vst->vfx].ready == 1 )
main_render->draw(main_render, &vst->vframe[vst->vfx].picture);
else
// 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);
}