@ -7,9 +7,9 @@
# include "util/log.h"
bool
video_buffer_init ( struct video_buffer * vb , bool render_expired_frames ) {
vb - > decoding _frame = av_frame_alloc ( ) ;
if ( ! vb - > decoding _frame) {
video_buffer_init ( struct video_buffer * vb , bool wait_consumer ) {
vb - > producer _frame = av_frame_alloc ( ) ;
if ( ! vb - > producer _frame) {
goto error_0 ;
}
@ -18,8 +18,8 @@ video_buffer_init(struct video_buffer *vb, bool render_expired_frames) {
goto error_1 ;
}
vb - > rendering _frame = av_frame_alloc ( ) ;
if ( ! vb - > rendering _frame) {
vb - > consumer _frame = av_frame_alloc ( ) ;
if ( ! vb - > consumer _frame) {
goto error_2 ;
}
@ -28,73 +28,72 @@ video_buffer_init(struct video_buffer *vb, bool render_expired_frames) {
goto error_3 ;
}
vb - > render_expired_frames = render_expired_frames ;
if ( render_expired_frames ) {
vb - > wait_consumer = wait_consumer ;
if ( wait_consumer ) {
ok = sc_cond_init ( & vb - > pending_frame_consumed_cond ) ;
if ( ! ok ) {
sc_mutex_destroy ( & vb - > mutex ) ;
goto error_2 ;
}
// interrupted is not used if expired frames are not rendered
// since offering a frame will never block
// interrupted is not used if wait_consumer is disabled since offering
// a frame will never block
vb - > interrupted = false ;
}
// there is initially no rendering frame, so consider it has already been
// consumed
// there is initially no frame, so consider it has already been consumed
vb - > pending_frame_consumed = true ;
return true ;
error_3 :
av_frame_free ( & vb - > rendering _frame) ;
av_frame_free ( & vb - > consumer _frame) ;
error_2 :
av_frame_free ( & vb - > pending_frame ) ;
error_1 :
av_frame_free ( & vb - > decoding _frame) ;
av_frame_free ( & vb - > producer _frame) ;
error_0 :
return false ;
}
void
video_buffer_destroy ( struct video_buffer * vb ) {
if ( vb - > render_expired_frames ) {
if ( vb - > wait_consumer ) {
sc_cond_destroy ( & vb - > pending_frame_consumed_cond ) ;
}
sc_mutex_destroy ( & vb - > mutex ) ;
av_frame_free ( & vb - > rendering _frame) ;
av_frame_free ( & vb - > consumer _frame) ;
av_frame_free ( & vb - > pending_frame ) ;
av_frame_free ( & vb - > decoding _frame) ;
av_frame_free ( & vb - > producer _frame) ;
}
static void
video_buffer_swap_ decoding _frame( struct video_buffer * vb ) {
video_buffer_swap_ producer _frame( struct video_buffer * vb ) {
sc_mutex_assert ( & vb - > mutex ) ;
AVFrame * tmp = vb - > decoding _frame;
vb - > decoding _frame = vb - > pending_frame ;
AVFrame * tmp = vb - > producer _frame;
vb - > producer _frame = vb - > pending_frame ;
vb - > pending_frame = tmp ;
}
static void
video_buffer_swap_ rendering _frame( struct video_buffer * vb ) {
video_buffer_swap_ consumer _frame( struct video_buffer * vb ) {
sc_mutex_assert ( & vb - > mutex ) ;
AVFrame * tmp = vb - > rendering _frame;
vb - > rendering _frame = vb - > pending_frame ;
AVFrame * tmp = vb - > consumer _frame;
vb - > consumer _frame = vb - > pending_frame ;
vb - > pending_frame = tmp ;
}
void
video_buffer_ offer_decoded _frame( struct video_buffer * vb ,
bool * previous_frame_skipped ) {
video_buffer_ producer_offer _frame( struct video_buffer * vb ,
bool * previous_frame_skipped ) {
sc_mutex_lock ( & vb - > mutex ) ;
if ( vb - > render_expired_frames ) {
if ( vb - > wait_consumer ) {
// wait for the current (expired) frame to be consumed
while ( ! vb - > pending_frame_consumed & & ! vb - > interrupted ) {
sc_cond_wait ( & vb - > pending_frame_consumed_cond , & vb - > mutex ) ;
}
}
video_buffer_swap_ decoding _frame( vb ) ;
video_buffer_swap_ producer _frame( vb ) ;
* previous_frame_skipped = ! vb - > pending_frame_consumed ;
vb - > pending_frame_consumed = false ;
@ -103,26 +102,26 @@ video_buffer_offer_decoded_frame(struct video_buffer *vb,
}
const AVFrame *
video_buffer_ take_rendering _frame( struct video_buffer * vb ) {
video_buffer_ consumer_ take_frame( struct video_buffer * vb ) {
sc_mutex_lock ( & vb - > mutex ) ;
assert ( ! vb - > pending_frame_consumed ) ;
vb - > pending_frame_consumed = true ;
video_buffer_swap_ rendering _frame( vb ) ;
video_buffer_swap_ consumer _frame( vb ) ;
if ( vb - > render_expired_frames ) {
if ( vb - > wait_consumer ) {
// unblock video_buffer_offer_decoded_frame()
sc_cond_signal ( & vb - > pending_frame_consumed_cond ) ;
}
sc_mutex_unlock ( & vb - > mutex ) ;
// rendering _frame is only written from this thread, no need to lock
return vb - > rendering _frame;
// consumer _frame is only written from this thread, no need to lock
return vb - > consumer _frame;
}
void
video_buffer_interrupt ( struct video_buffer * vb ) {
if ( vb - > render_expired_frames ) {
if ( vb - > wait_consumer ) {
sc_mutex_lock ( & vb - > mutex ) ;
vb - > interrupted = true ;
sc_mutex_unlock ( & vb - > mutex ) ;