From 48dae516a3fadc46eaf3228eb519728e2a3961e6 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Mon, 13 Jul 2020 14:58:21 -0700 Subject: encode_image_buffer: duplicate missed frames When the encoder finds the encoded - captured frameno delta > 1 it needs to fill the gap somehow. With how things are currently architected, the old yuv countents are gone so there's only the current frame available for filling. The newer theoraenc.h API exposes a theora_control() parameter for this purpose, so I've also added a theoraenc.h include implicitly bumping the libtheora dependency. But by now it shouldn't matter, and the rest of rmd should probably get updated to use the new theora API eventually anyways. I'm still uncertain what role pdata->avd will play in the long-run, but leaving its maintenance for now. --- src/rmd_encode_image_buffer.c | 47 ++++++++++++++++++++++++++----------------- src/rmd_types.h | 1 + 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/rmd_encode_image_buffer.c b/src/rmd_encode_image_buffer.c index f5e8b36..57ac5ce 100644 --- a/src/rmd_encode_image_buffer.c +++ b/src/rmd_encode_image_buffer.c @@ -34,14 +34,21 @@ void *rmdEncodeImageBuffer(ProgData *pdata) { - unsigned int encode_frameno = 0; + unsigned int encode_frameno = 0, last_encode_frameno = 0; rmdThreadsSetName("rmdEncodeImages"); pdata->th_encoding_clean = 0; while (pdata->running) { - EncData *enc_data = pdata->enc_data; + EncData *enc_data = pdata->enc_data; + unsigned int n_frames; + int r; + + pthread_mutex_lock(&pdata->pause_mutex); + while (pdata->paused) + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); pthread_mutex_lock(&pdata->img_buff_ready_mutex); while (pdata->running && encode_frameno >= pdata->capture_frameno) @@ -49,25 +56,29 @@ void *rmdEncodeImageBuffer(ProgData *pdata) { encode_frameno = pdata->capture_frameno; pthread_mutex_unlock(&pdata->img_buff_ready_mutex); - pthread_mutex_lock(&pdata->pause_mutex); - while (pdata->paused) - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - pthread_mutex_lock(&pdata->yuv_mutex); - if (theora_encode_YUVin(&enc_data->m_th_st, &enc_data->yuv)) { + r = theora_encode_YUVin(&enc_data->m_th_st, &enc_data->yuv); + pthread_mutex_unlock(&pdata->yuv_mutex); + if (r) { fprintf(stderr, "Encoder not ready!\n"); - pthread_mutex_unlock(&pdata->yuv_mutex); - } else { - pthread_mutex_unlock(&pdata->yuv_mutex); - - if (theora_encode_packetout(&enc_data->m_th_st, 0, &enc_data->m_ogg_pckt1) == 1) { - pthread_mutex_lock(&pdata->libogg_mutex); - ogg_stream_packetin(&enc_data->m_ogg_ts, &enc_data->m_ogg_pckt1); - pdata->avd += pdata->frametime; - pthread_mutex_unlock(&pdata->libogg_mutex); - } + continue; } + + n_frames = encode_frameno - last_encode_frameno; + if (n_frames > 1) + theora_control( &enc_data->m_th_st, + TH_ENCCTL_SET_DUP_COUNT, + (void *)&(int){n_frames - 1}, + sizeof(int)); + + while (theora_encode_packetout(&enc_data->m_th_st, 0, &enc_data->m_ogg_pckt1) > 0) { + pthread_mutex_lock(&pdata->libogg_mutex); + ogg_stream_packetin(&enc_data->m_ogg_ts, &enc_data->m_ogg_pckt1); + pdata->avd += pdata->frametime; + pthread_mutex_unlock(&pdata->libogg_mutex); + } + + last_encode_frameno = encode_frameno; } //last packet diff --git a/src/rmd_types.h b/src/rmd_types.h index 159434a..f01083c 100644 --- a/src/rmd_types.h +++ b/src/rmd_types.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3