summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rmd_cache_audio.c3
-rw-r--r--src/rmd_cache_frame.c14
-rw-r--r--src/rmd_encode_image_buffer.c19
-rw-r--r--src/rmd_encode_image_buffer.h3
-rw-r--r--src/rmd_flush_to_ogg.c2
-rw-r--r--src/rmd_load_cache.c111
-rw-r--r--src/rmd_types.h15
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
© All Rights Reserved