diff options
-rw-r--r-- | src/rmd_cache_audio.c | 3 | ||||
-rw-r--r-- | src/rmd_cache_frame.c | 14 | ||||
-rw-r--r-- | src/rmd_encode_image_buffer.c | 19 | ||||
-rw-r--r-- | src/rmd_encode_image_buffer.h | 3 | ||||
-rw-r--r-- | src/rmd_flush_to_ogg.c | 2 | ||||
-rw-r--r-- | src/rmd_load_cache.c | 111 | ||||
-rw-r--r-- | src/rmd_types.h | 15 |
7 files changed, 86 insertions, 81 deletions
diff --git a/src/rmd_cache_audio.c b/src/rmd_cache_audio.c index 0ac011f..0a3be39 100644 --- a/src/rmd_cache_audio.c +++ b/src/rmd_cache_audio.c @@ -99,7 +99,10 @@ void *rmdCacheSoundBuffer(ProgData *pdata) { fwrite(jackbuf, 1, write_size, pdata->cache_data->afp); #endif } + + pthread_mutex_lock(&pdata->avd_mutex); pdata->avd -= pdata->periodtime; + pthread_mutex_unlock(&pdata->avd_mutex); } fclose(pdata->cache_data->afp); diff --git a/src/rmd_cache_frame.c b/src/rmd_cache_frame.c index c2e37bf..5c0ea5b 100644 --- a/src/rmd_cache_frame.c +++ b/src/rmd_cache_frame.c @@ -105,7 +105,7 @@ void *rmdCacheImageBuffer(ProgData *pdata) { v_short_blocks[blocknum_x * blocknum_y]; unsigned long long int total_bytes = 0; unsigned long long int total_received_bytes = 0; - unsigned int capture_frameno = 0; + unsigned int capture_frameno = 0, last_capture_frameno = 0; rmdThreadsSetName("rmdCacheImages"); @@ -181,8 +181,8 @@ void *rmdCacheImageBuffer(ProgData *pdata) { } strncpy(fheader.frame_prefix, "FRAM", 4); - fheader.frameno = ++frameno; - fheader.current_total = pdata->frames_total; + fheader.capture_frameno = capture_frameno; + frameno++; fheader.Ynum = ynum; fheader.Unum = unum; @@ -255,7 +255,9 @@ void *rmdCacheImageBuffer(ProgData *pdata) { nbytes += rmdFlushBlock(NULL, 0, 0, 0, 0, fp, ucfp, 1); /**@________________@**/ - pdata->avd += pdata->frametime; + pthread_mutex_lock(&pdata->avd_mutex); + pdata->avd += pdata->frametime * (capture_frameno - last_capture_frameno); + pthread_mutex_unlock(&pdata->avd_mutex); if (nbytes > CACHE_FILE_SIZE_LIMIT) { if (rmdSwapCacheFilesWrite(pdata->cache_data->imgdata, nth_cache, &fp, &ucfp)) { @@ -279,6 +281,8 @@ void *rmdCacheImageBuffer(ProgData *pdata) { nth_cache++; nbytes = 0; } + + last_capture_frameno = capture_frameno; } total_bytes += nbytes; @@ -307,7 +311,7 @@ void *rmdCacheImageBuffer(ProgData *pdata) { fprintf(stderr, "Saved %d frames in a total of %d requests\n", frameno, - pdata->frames_total); + capture_frameno); fflush(stderr); if (!pdata->args.zerocompression) { diff --git a/src/rmd_encode_image_buffer.c b/src/rmd_encode_image_buffer.c index d83c694..5b08620 100644 --- a/src/rmd_encode_image_buffer.c +++ b/src/rmd_encode_image_buffer.c @@ -95,7 +95,7 @@ void *rmdEncodeImageBuffer(ProgData *pdata) { //this function is meant to be called normally //not through a thread of it's own -void rmdSyncEncodeImageBuffer(ProgData *pdata) { +void rmdSyncEncodeImageBuffer(ProgData *pdata, unsigned int n_frames) { EncData *enc_data = pdata->enc_data; if (theora_encode_YUVin(&enc_data->m_th_st, &enc_data->yuv)) { @@ -103,14 +103,23 @@ void rmdSyncEncodeImageBuffer(ProgData *pdata) { return; } - if (theora_encode_packetout(&enc_data->m_th_st, !pdata->running, &enc_data->m_ogg_pckt1) == 1) { + 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); - + /* TODO: this is the only real difference from what's open-coded above, + * investigate why this is done this way and make the thread just call + * this function instead of duplicating it. + */ if (!pdata->running) enc_data->m_ogg_ts.e_o_s = 1; - - pdata->avd += pdata->frametime; pthread_mutex_unlock(&pdata->libogg_mutex); } + + pdata->avd += pdata->frametime * n_frames; } diff --git a/src/rmd_encode_image_buffer.h b/src/rmd_encode_image_buffer.h index e5ca3db..d011e26 100644 --- a/src/rmd_encode_image_buffer.h +++ b/src/rmd_encode_image_buffer.h @@ -34,6 +34,7 @@ * feed a yuv buffer to the theora encoder and submit outcome to * the ogg stream. * \param pdata ProgData struct containing all program data +* \param n_frames number of frames to encode from image buffer */ void *rmdEncodeImageBuffer(ProgData *pdata); @@ -44,7 +45,7 @@ void *rmdEncodeImageBuffer(ProgData *pdata); * \param pdata ProgData struct containing all program data * */ -void rmdSyncEncodeImageBuffer(ProgData *pdata); +void rmdSyncEncodeImageBuffer(ProgData *pdata, unsigned int n_frames); #endif diff --git a/src/rmd_flush_to_ogg.c b/src/rmd_flush_to_ogg.c index b4ca6fb..6c5a0d8 100644 --- a/src/rmd_flush_to_ogg.c +++ b/src/rmd_flush_to_ogg.c @@ -127,7 +127,7 @@ void *rmdFlushToOgg(ProgData *pdata) { while (!pdata->th_encoding_clean) pthread_cond_wait(&pdata->theora_lib_clean, &pdata->theora_lib_mutex); pthread_mutex_unlock(&pdata->theora_lib_mutex); - rmdSyncEncodeImageBuffer(pdata); + rmdSyncEncodeImageBuffer(pdata, 1); } } diff --git a/src/rmd_load_cache.c b/src/rmd_load_cache.c index 417b3dc..0d94a37 100644 --- a/src/rmd_load_cache.c +++ b/src/rmd_load_cache.c @@ -161,6 +161,14 @@ static int rmdReadFrame(CachedFrame *frame, FILE *ucfp, gzFile ifp) { return 0; } +static int read_header(ProgData *pdata, gzFile ifp, FILE *ucfp, FrameHeader *fheader) { + if (!pdata->args.zerocompression) { + return gzread(ifp, fheader, sizeof(FrameHeader)) == sizeof(FrameHeader); + } else { + return fread(fheader, sizeof(FrameHeader), 1, ucfp) == 1; + } +} + void *rmdLoadCache(ProgData *pdata) { yuv_buffer *yuv = &pdata->enc_data->yuv; @@ -171,9 +179,6 @@ void *rmdLoadCache(ProgData *pdata) { CachedFrame frame; int nth_cache = 1, audio_end = 0, - extra_frames = 0, //total number of duplicated frames - missing_frames = 0, //if this is found >0 current run will not load - //a frame but it will proccess the previous thread_exit = 0, //0 success, -1 couldn't find files,1 couldn't remove blocknum_x = pdata->enc_data->yuv.y_width / Y_UNIT_WIDTH, blocknum_y = pdata->enc_data->yuv.y_height / Y_UNIT_WIDTH, @@ -184,6 +189,7 @@ void *rmdLoadCache(ProgData *pdata) { u_int32_t YBlocks[(yuv->y_width * yuv->y_height) / Y_UNIT_BYTES], UBlocks[(yuv->uv_width * yuv->uv_height) / UV_UNIT_BYTES], VBlocks[(yuv->uv_width * yuv->uv_height) / UV_UNIT_BYTES]; + unsigned int last_capture_frameno = 0; rmdThreadsSetName("rmdEncodeCache"); @@ -225,70 +231,60 @@ void *rmdLoadCache(ProgData *pdata) { //If sound finishes first,we go on with the video. //If video ends we will do one more run to flush audio in the ogg file while (pdata->running) { + //video load and encoding if (pdata->avd <= 0 || pdata->args.nosound || audio_end) { - if (missing_frames > 0) { - extra_frames++; - missing_frames--; - rmdSyncEncodeImageBuffer(pdata); - } else if (((!pdata->args.zerocompression) && - (gzread(ifp, frame.header, sizeof(FrameHeader)) == - sizeof(FrameHeader) )) || - ((pdata->args.zerocompression) && - (fread(frame.header, sizeof(FrameHeader), 1, ucfp) == 1))) { - //sync - missing_frames += frame.header->current_total - - (extra_frames + frame.header->frameno); + + if (read_header(pdata, ifp, ucfp, frame.header)) { + if (pdata->frames_total) { fprintf(stdout, "\r[%d%%] ", - ((frame.header->frameno + extra_frames) * 100) / pdata->frames_total); + ((frame.header->capture_frameno) * 100) / pdata->capture_frameno); } else fprintf(stdout, "\r[%d frames rendered] ", - (frame.header->frameno + extra_frames)); + (frame.header->capture_frameno)); fflush(stdout); - if ( (frame.header->Ynum <= blocknum_x * blocknum_y) && - (frame.header->Unum <= blocknum_x * blocknum_y) && - (frame.header->Vnum <= blocknum_x * blocknum_y) && - !rmdReadFrame( &frame, - (pdata->args.zerocompression ? ucfp : NULL), - (pdata->args.zerocompression ? NULL : ifp)) - ) { - - //load the blocks for each buffer - if (frame.header->Ynum) - for (int j = 0; j < frame.header->Ynum; j++) - rmdLoadBlock( yuv->y, - &frame.YData[j * blockszy], - frame.YBlocks[j], - yuv->y_width, - yuv->y_height, - Y_UNIT_WIDTH); - if (frame.header->Unum) - for (int j = 0; j < frame.header->Unum; j++) - rmdLoadBlock( yuv->u, - &frame.UData[j * blockszuv], - frame.UBlocks[j], - yuv->uv_width, - yuv->uv_height, - UV_UNIT_WIDTH); - if (frame.header->Vnum) - for (int j = 0; j < frame.header->Vnum; j++) - rmdLoadBlock( yuv->v, - &frame.VData[j * blockszuv], - frame.VBlocks[j], - yuv->uv_width, - yuv->uv_height, - UV_UNIT_WIDTH); - - //encode. This is not made in a thread since - //now blocking is not a problem - //and this way sync problems - //can be avoided more easily. - rmdSyncEncodeImageBuffer(pdata); - } else { + + if ( (frame.header->Ynum > blocknum_x * blocknum_y) || + (frame.header->Unum > blocknum_x * blocknum_y) || + (frame.header->Vnum > blocknum_x * blocknum_y) || + rmdReadFrame( &frame, + pdata->args.zerocompression ? ucfp : NULL, + pdata->args.zerocompression ? NULL : ifp) < 0) { + raise(SIGINT); continue; } + + //load the blocks for each buffer + if (frame.header->Ynum) + for (int j = 0; j < frame.header->Ynum; j++) + rmdLoadBlock( yuv->y, + &frame.YData[j * blockszy], + frame.YBlocks[j], + yuv->y_width, + yuv->y_height, + Y_UNIT_WIDTH); + if (frame.header->Unum) + for (int j = 0; j < frame.header->Unum; j++) + rmdLoadBlock( yuv->u, + &frame.UData[j * blockszuv], + frame.UBlocks[j], + yuv->uv_width, + yuv->uv_height, + UV_UNIT_WIDTH); + if (frame.header->Vnum) + for (int j = 0; j < frame.header->Vnum; j++) + rmdLoadBlock( yuv->v, + &frame.VData[j * blockszuv], + frame.VBlocks[j], + yuv->uv_width, + yuv->uv_height, + UV_UNIT_WIDTH); + + rmdSyncEncodeImageBuffer(pdata, fheader.capture_frameno - last_capture_frameno); + + last_capture_frameno = fheader.capture_frameno; } else { if (rmdSwapCacheFilesRead( pdata->cache_data->imgdata, nth_cache, @@ -299,7 +295,6 @@ void *rmdLoadCache(ProgData *pdata) { fprintf(stderr, "\t[Cache File %d]", nth_cache); nth_cache++; } - continue; } //audio load and encoding } else { diff --git a/src/rmd_types.h b/src/rmd_types.h index f01083c..b7c27a8 100644 --- a/src/rmd_types.h +++ b/src/rmd_types.h @@ -349,19 +349,12 @@ struct _ProgData { //We need the total number of blocks //for each plane. -//The number of the frame compared to the -//number of time expirations at the time of -//caching, will enable us to make up for lost frames. - - typedef struct _FrameHeader{ char frame_prefix[4]; //always FRAM - u_int32_t frameno, //number of frame(cached frames) - current_total; //number of frames that should have been - //taken at time of caching this one - u_int32_t Ynum, //number of changed blocks in the Y plane - Unum, //number of changed blocks in the U plane - Vnum; //number of changed blocks in the V plane + u_int32_t capture_frameno; //number of frame + u_int32_t Ynum, //number of changed blocks in the Y plane + Unum, //number of changed blocks in the U plane + Vnum; //number of changed blocks in the V plane }FrameHeader; #endif |