@ -16,19 +16,24 @@ video_buffer_init(struct video_buffer *vb, struct fps_counter *fps_counter,
goto error_0 ;
}
vb - > pending_frame = av_frame_alloc ( ) ;
if ( ! vb - > pending_frame ) {
goto error_1 ;
}
vb - > rendering_frame = av_frame_alloc ( ) ;
if ( ! vb - > rendering_frame ) {
goto error_1 ;
goto error_ 2 ;
}
bool ok = sc_mutex_init ( & vb - > mutex ) ;
if ( ! ok ) {
goto error_ 2 ;
goto error_ 3 ;
}
vb - > render_expired_frames = render_expired_frames ;
if ( render_expired_frames ) {
ok = sc_cond_init ( & vb - > render ing_frame_consumed_cond) ;
ok = sc_cond_init ( & vb - > pend ing_frame_consumed_cond) ;
if ( ! ok ) {
sc_mutex_destroy ( & vb - > mutex ) ;
goto error_2 ;
@ -40,12 +45,14 @@ video_buffer_init(struct video_buffer *vb, struct fps_counter *fps_counter,
// there is initially no rendering frame, so consider it has already been
// consumed
vb - > render ing_frame_consumed = true ;
vb - > pend ing_frame_consumed = true ;
return true ;
error_ 2 :
error_ 3 :
av_frame_free ( & vb - > rendering_frame ) ;
error_2 :
av_frame_free ( & vb - > pending_frame ) ;
error_1 :
av_frame_free ( & vb - > decoding_frame ) ;
error_0 :
@ -55,19 +62,28 @@ error_0:
void
video_buffer_destroy ( struct video_buffer * vb ) {
if ( vb - > render_expired_frames ) {
sc_cond_destroy ( & vb - > render ing_frame_consumed_cond) ;
sc_cond_destroy ( & vb - > pend ing_frame_consumed_cond) ;
}
sc_mutex_destroy ( & vb - > mutex ) ;
av_frame_free ( & vb - > rendering_frame ) ;
av_frame_free ( & vb - > pending_frame ) ;
av_frame_free ( & vb - > decoding_frame ) ;
}
static void
video_buffer_swap_ frames ( struct video_buffer * vb ) {
video_buffer_swap_ decoding_ frame( struct video_buffer * vb ) {
sc_mutex_assert ( & vb - > mutex ) ;
AVFrame * tmp = vb - > decoding_frame ;
vb - > decoding_frame = vb - > rendering_frame ;
vb - > rendering_frame = tmp ;
vb - > decoding_frame = vb - > pending_frame ;
vb - > pending_frame = tmp ;
}
static void
video_buffer_swap_rendering_frame ( struct video_buffer * vb ) {
sc_mutex_assert ( & vb - > mutex ) ;
AVFrame * tmp = vb - > rendering_frame ;
vb - > rendering_frame = vb - > pending_frame ;
vb - > pending_frame = tmp ;
}
void
@ -76,31 +92,38 @@ video_buffer_offer_decoded_frame(struct video_buffer *vb,
sc_mutex_lock ( & vb - > mutex ) ;
if ( vb - > render_expired_frames ) {
// wait for the current (expired) frame to be consumed
while ( ! vb - > render ing_frame_consumed & & ! vb - > interrupted ) {
sc_cond_wait ( & vb - > render ing_frame_consumed_cond, & vb - > mutex ) ;
while ( ! vb - > pend ing_frame_consumed & & ! vb - > interrupted ) {
sc_cond_wait ( & vb - > pend ing_frame_consumed_cond, & vb - > mutex ) ;
}
} else if ( ! vb - > render ing_frame_consumed) {
} else if ( ! vb - > pend ing_frame_consumed) {
fps_counter_add_skipped_frame ( vb - > fps_counter ) ;
}
video_buffer_swap_ frames ( vb ) ;
video_buffer_swap_ decoding_ frame( vb ) ;
* previous_frame_skipped = ! vb - > render ing_frame_consumed;
vb - > render ing_frame_consumed = false ;
* previous_frame_skipped = ! vb - > pend ing_frame_consumed;
vb - > pend ing_frame_consumed = false ;
sc_mutex_unlock ( & vb - > mutex ) ;
}
const AVFrame *
video_buffer_consume_rendered_frame ( struct video_buffer * vb ) {
sc_mutex_assert ( & vb - > mutex ) ;
assert ( ! vb - > rendering_frame_consumed ) ;
vb - > rendering_frame_consumed = true ;
video_buffer_take_rendering_frame ( struct video_buffer * vb ) {
sc_mutex_lock ( & vb - > mutex ) ;
assert ( ! vb - > pending_frame_consumed ) ;
vb - > pending_frame_consumed = true ;
fps_counter_add_rendered_frame ( vb - > fps_counter ) ;
video_buffer_swap_rendering_frame ( vb ) ;
if ( vb - > render_expired_frames ) {
// unblock video_buffer_offer_decoded_frame()
sc_cond_signal ( & vb - > rendering_frame_consumed_cond ) ;
sc_cond_signal ( & vb - > pend ing_frame_consumed_cond) ;
}
sc_mutex_unlock ( & vb - > mutex ) ;
// rendering_frame is only written from this thread, no need to lock
return vb - > rendering_frame ;
}
@ -111,6 +134,6 @@ video_buffer_interrupt(struct video_buffer *vb) {
vb - > interrupted = true ;
sc_mutex_unlock ( & vb - > mutex ) ;
// wake up blocking wait
sc_cond_signal ( & vb - > render ing_frame_consumed_cond) ;
sc_cond_signal ( & vb - > pend ing_frame_consumed_cond) ;
}
}