lists.zerezo.com
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
***BOGO*** [MPlayer-dev-eng] [PATCHES] Edit Decision Lists
- Date: Sun, 22 Jun 2008 20:35:24 +0200
- From: "Olivier Rolland" <billl@xxxxxxxxxxxx>
- Subject: ***BOGO*** [MPlayer-dev-eng] [PATCHES] Edit Decision Lists
Hi,
Here are two patches dealing with EDL support in mencoder.
The first one is related to this bug
http://bugzilla.mplayerhq.hu/show_bug.cgi?id=4: it gets rid of
potential timestamp resets by using demuxer->stream_pts (if defined)
instead of demuxer->video->sh->pts. Ultimately,
demuxer->video->sh->pts (and the like) are replaced by calls to
demuxer_get_current_time (demuxer). It's a little bit different with
the audio stream because of the calc_a_pts function, that's why I'm
using static variables to store previous values to detect pts resets.
All in all, with this patch, the functionnal behaviour is exactely the
same with movies without timestamp resets.
I've made a few tests with DVDs, AVIs, OGMs and MKVs with and without
-hr-edl-seek and didn't have any regression.
The second patch is less functional. It simply cleans out the EDL code
in mencoder by removing unneeded parameters and tests, replacing a
goto with a while and moving the EDL code from the main loop to its
own function.
I guess something similar can be done for mplayer.
Regards,
Olivier Rolland
Index: mencoder.c
===================================================================
--- mencoder.c (révision 27100)
+++ mencoder.c (copie de travail)
@@ -274,9 +274,9 @@
/** \brief Seeks slowly by dumping frames.
\return 1 for success, 2 for EOF.
*/
-static int slowseek(float end_pts, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy, int print_info);
+static int slowseek(float end_pts, demuxer_t *demuxer, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy, int print_info);
/// Deletes audio or video as told by -delay to sync
-static void fixdelay(demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy);
+static void fixdelay(demuxer_t *demuxer, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy);
#include "edl.h"
static edl_record_ptr edl_records = NULL; ///< EDL entries memory area
@@ -410,6 +410,8 @@
audio_encoding_params_t aparams;
audio_encoder_t *aencoder = NULL;
+float pts;
+
user_correct_pts = 0;
mp_msg_init();
@@ -1104,7 +1106,7 @@
next_edl_record = edl_records = edl_parse_file();
}
-if (sh_audio && audio_delay != 0.) fixdelay(d_video, d_audio, mux_a, &frame_data, mux_v->codec==VCODEC_COPY);
+if (sh_audio && audio_delay != 0.) fixdelay(demuxer, d_video, d_audio, mux_a, &frame_data, mux_v->codec==VCODEC_COPY);
while(!at_eof){
@@ -1127,21 +1129,23 @@
break;
}
+ pts = demuxer_get_current_time(demuxer);
goto_redo_edl:
- if (next_edl_record && sh_video && sh_video->pts >= next_edl_record->start_sec) {
+ if (next_edl_record && sh_video && pts >= next_edl_record->start_sec) {
if (next_edl_record->action == EDL_SKIP && edl_seeking) {
- float last_pos = d_video->pts;
+ float last_pos = pts;
int result;
mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_SKIP: start [%f], stop [%f], length [%f]\n",
next_edl_record->start_sec, next_edl_record->stop_sec, next_edl_record->length_sec);
result = edl_seek(next_edl_record, demuxer, d_audio, mux_a, &frame_data, mux_v->codec==VCODEC_COPY);
+ pts = demuxer_get_current_time(demuxer);
if (result == 2) { at_eof=1; break; } // EOF
else if (result == 0) edl_seeking = 0; // no seeking
else { // sucess
edl_muted = 0;
- if (last_pos >= sh_video->pts) {
+ if (last_pos >= pts) {
// backwards seek detected!! Forget about this EDL skip altogether.
next_edl_record = next_edl_record->next;
}
@@ -1150,7 +1154,7 @@
meaning if by some magical way we landed in the MIDDLE of a censored area,
in the next loop it will jump out of it.
*/
- if (next_edl_record->stop_sec > sh_video->pts) break; // we got to the right place.
+ if (next_edl_record->stop_sec > pts) break; // we got to the right place.
if (next_edl_record->action == EDL_MUTE) edl_muted = !edl_muted; // toggle mute each time.
}
@@ -1622,7 +1626,7 @@
if (play_n_frames >= 0) timeleft = mux_v->timer + play_n_frames * (double)(mux_v->h.dwScale) / mux_v->h.dwRate;
if (end_at.type == END_AT_TIME && (timeleft > end_at.pos || timeleft == -1)) timeleft = end_at.pos;
if (next_edl_record && demuxer && demuxer->video) { // everything is OK to be checked
- float tmp = mux_v->timer + next_edl_record->start_sec - demuxer->video->pts;
+ float tmp = mux_v->timer + next_edl_record->start_sec - demuxer_get_current_time(demuxer);
if (timeleft == -1 || timeleft > tmp) {
// There's less time in EDL than what we already know
if (next_edl_record->action == EDL_SKIP && edl_seeking) {
@@ -1639,8 +1643,14 @@
static float calc_a_pts(demux_stream_t *d_audio) {
sh_audio_t * sh_audio = d_audio ? d_audio->sh : NULL;
float a_pts = 0.;
- if (sh_audio)
- a_pts = d_audio->pts + (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
+ if (sh_audio) {
+ static float d_audio_pts_prec = 0., a_pts_base = 0.;
+ if (d_audio->pts + 0.5 < d_audio_pts_prec)
+ a_pts_base += d_audio_pts_prec;
+ d_audio_pts_prec = d_audio->pts;
+
+ a_pts = a_pts_base + d_audio->pts + (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
+ }
return a_pts;
}
@@ -1679,13 +1689,13 @@
return a_pts;
}
-static int slowseek(float end_pts, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy, int print_info) {
+static int slowseek(float end_pts, demuxer_t *demuxer, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy, int print_info) {
sh_video_t * sh_video = d_video->sh;
vf_instance_t * vfilter = sh_video ? sh_video->vfilter : NULL;
int done = 0;
while (!interrupted) {
- float a_pts = 0.;
+ float pts, a_pts = 0.;
if (!frame_data->already_read) { // when called after fixdelay, a frame is already read
frame_data->in_size = video_read_frame(sh_video, &frame_data->frame_time, &frame_data->start, force_fps);
@@ -1694,7 +1704,8 @@
}
frame_data->already_read = 0;
- a_pts = forward_audio(sh_video->pts - frame_data->frame_time + audio_delay, d_audio, mux_a);
+ pts = demuxer_get_current_time(demuxer);
+ a_pts = forward_audio(pts - frame_data->frame_time + audio_delay, d_audio, mux_a);
if (done) {
// wait for keyframe in case of -ovc copy
@@ -1703,7 +1714,7 @@
return 1;
}
}
- if (sh_video->pts >= end_pts) done = 1;
+ if (pts >= end_pts) done = 1;
if (vfilter) {
int softskip = (vfilter->control(vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) == CONTROL_TRUE);
@@ -1715,16 +1726,16 @@
if (print_info) mp_msg(MSGT_MENCODER, MSGL_STATUS,
MSGTR_EdlSkipStartEndCurrent,
next_edl_record->start_sec, next_edl_record->stop_sec,
- sh_video->pts, a_pts);
+ pts, a_pts);
}
if (interrupted) return 2;
return 1;
}
-static void fixdelay(demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
+static void fixdelay(demuxer_t *demuxer, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
// TODO: Find a way to encode silence instead of deleting video
sh_video_t * sh_video = d_video->sh;
- float a_pts;
+ float pts, a_pts;
// demux_seek has a weirdness that sh_video->pts is meaningless,
// until a single frame is read... Same for audio actually too.
@@ -1734,27 +1745,29 @@
sh_video->timer += frame_data->frame_time;
frame_data->already_read = 1;
- a_pts = forward_audio(sh_video->pts - frame_data->frame_time + audio_delay, d_audio, mux_a);
+ pts = demuxer_get_current_time(demuxer);
+ a_pts = forward_audio(pts - frame_data->frame_time + audio_delay, d_audio, mux_a);
if (audio_delay > 0) return;
- else if (sh_video->pts - frame_data->frame_time + audio_delay >= a_pts) return;
+ else if (pts - frame_data->frame_time + audio_delay >= a_pts) return;
- slowseek(a_pts - audio_delay, d_video, d_audio, mux_a, frame_data, framecopy, 0);
+ slowseek(a_pts - audio_delay, demuxer, d_video, d_audio, mux_a, frame_data, framecopy, 0);
}
static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
sh_video_t * sh_video = demuxer->video ? demuxer->video->sh : NULL;
+ float pts = demuxer_get_current_time(demuxer);
if (!sh_video) return 0;
- if (sh_video->pts >= next_edl_record->stop_sec) return 1; // nothing to do...
+ if (pts >= next_edl_record->stop_sec) return 1; // nothing to do...
if (!edl_seek_type) {
- if(demux_seek(demuxer, next_edl_record->stop_sec - sh_video->pts, audio_delay, 0)){
+ if(demux_seek(demuxer, next_edl_record->stop_sec - pts, audio_delay, 0)){
sh_video->pts = demuxer->video->pts;
//if (vo_vobsub) vobsub_seek(vo_vobsub,sh_video->pts);
resync_video_stream(sh_video);
//if(vo_spudec) spudec_reset(vo_spudec);
- if (audio_delay != 0.0) fixdelay(demuxer->video, d_audio, mux_a, frame_data, framecopy);
+ if (audio_delay != 0.0) fixdelay(demuxer, demuxer->video, d_audio, mux_a, frame_data, framecopy);
return 1;
}
// non-seekable stream.
@@ -1763,5 +1776,5 @@
// slow seek, read every frame.
- return slowseek(next_edl_record->stop_sec, demuxer->video, d_audio, mux_a, frame_data, framecopy, 1);
+ return slowseek(next_edl_record->stop_sec, demuxer, demuxer->video, d_audio, mux_a, frame_data, framecopy, 1);
}
--- mencoder.c.orig 2008-06-22 20:15:54.000000000 +0200
+++ mencoder.c 2008-06-22 20:16:01.000000000 +0200
@@ -287,7 +287,7 @@
/** \brief Seeks for EDL
\return 1 for success, 0 for failure, 2 for EOF.
*/
-static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy);
+static void edl_update(demuxer_t *demuxer, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_v, muxer_stream_t* mux_a, s_frame_data * frame_data);
#include "cfg-mencoder.h"
@@ -410,8 +410,6 @@
audio_encoding_params_t aparams;
audio_encoder_t *aencoder = NULL;
-float pts;
-
user_correct_pts = 0;
mp_msg_init();
@@ -1129,45 +1127,7 @@
break;
}
- pts = demuxer_get_current_time(demuxer);
-goto_redo_edl:
- if (next_edl_record && sh_video && pts >= next_edl_record->start_sec) {
- if (next_edl_record->action == EDL_SKIP && edl_seeking) {
- float last_pos = pts;
- int result;
- mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_SKIP: start [%f], stop [%f], length [%f]\n",
- next_edl_record->start_sec, next_edl_record->stop_sec, next_edl_record->length_sec);
-
- result = edl_seek(next_edl_record, demuxer, d_audio, mux_a, &frame_data, mux_v->codec==VCODEC_COPY);
- pts = demuxer_get_current_time(demuxer);
-
- if (result == 2) { at_eof=1; break; } // EOF
- else if (result == 0) edl_seeking = 0; // no seeking
- else { // sucess
- edl_muted = 0;
- if (last_pos >= pts) {
- // backwards seek detected!! Forget about this EDL skip altogether.
- next_edl_record = next_edl_record->next;
- }
- else for (next_edl_record = edl_records; next_edl_record; next_edl_record = next_edl_record->next) {
- /* note the use of stop_sec,
- meaning if by some magical way we landed in the MIDDLE of a censored area,
- in the next loop it will jump out of it.
- */
- if (next_edl_record->stop_sec > pts) break; // we got to the right place.
- if (next_edl_record->action == EDL_MUTE) edl_muted = !edl_muted; // toggle mute each time.
- }
-
- /* for a pedantic EDL, that doesn't show even a single
- frame from the "censored" area, uncomment next line. */
- goto goto_redo_edl;
- }
- } else if (next_edl_record->action == EDL_MUTE) {
- edl_muted = !edl_muted; // This variable does nothing for now.
- mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_MUTE: [%f]\n", next_edl_record->start_sec );
- next_edl_record=next_edl_record->next;
- }
- }
+ edl_update(demuxer, d_video, d_audio, mux_v, mux_a, &frame_data);
if(sh_audio){
@@ -1754,19 +1714,16 @@
slowseek(a_pts - audio_delay, demuxer, d_video, d_audio, mux_a, frame_data, framecopy, 0);
}
-static int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
+static int edl_seek(demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, s_frame_data * frame_data, int framecopy) {
sh_video_t * sh_video = demuxer->video ? demuxer->video->sh : NULL;
float pts = demuxer_get_current_time(demuxer);
- if (!sh_video) return 0;
if (pts >= next_edl_record->stop_sec) return 1; // nothing to do...
if (!edl_seek_type) {
if(demux_seek(demuxer, next_edl_record->stop_sec - pts, audio_delay, 0)){
- sh_video->pts = demuxer->video->pts;
- //if (vo_vobsub) vobsub_seek(vo_vobsub,sh_video->pts);
resync_video_stream(sh_video);
- //if(vo_spudec) spudec_reset(vo_spudec);
+ sh_video->pts = demuxer->video->pts;
if (audio_delay != 0.0) fixdelay(demuxer, demuxer->video, d_audio, mux_a, frame_data, framecopy);
return 1;
}
@@ -1778,3 +1735,58 @@
return slowseek(next_edl_record->stop_sec, demuxer, demuxer->video, d_audio, mux_a, frame_data, framecopy, 1);
}
+
+static void edl_update(demuxer_t *demuxer, demux_stream_t *d_video, demux_stream_t *d_audio, muxer_stream_t* mux_v, muxer_stream_t* mux_a, s_frame_data * frame_data) {
+ float pts;
+
+ if (!next_edl_record)
+ return;
+
+ if (!d_video || !d_video->sh) {
+ mp_msg(MSGT_MENCODER, MSGL_ERR, MSGTR_EdlNOsh_video);
+ free_edl(edl_records);
+ next_edl_record = NULL;
+ edl_records = NULL;
+ return;
+ }
+
+ pts = demuxer_get_current_time(demuxer);
+ if (pts >= next_edl_record->start_sec) {
+ if (next_edl_record->action == EDL_SKIP && edl_seeking) {
+ while (pts >= next_edl_record->start_sec) {
+ float last_pos = pts;
+ int result;
+
+ mp_msg(MSGT_MENCODER, MSGL_DBG4, "EDL_SKIP: start [%f], stop [%f], length [%f]\n",
+ next_edl_record->start_sec, next_edl_record->stop_sec, next_edl_record->length_sec);
+
+ result = edl_seek(demuxer, d_audio, mux_a, frame_data, mux_v->codec==VCODEC_COPY);
+ pts = demuxer_get_current_time(demuxer);
+
+ if (result == 2) { at_eof=1; break; } // EOF
+ else if (result == 0) { edl_seeking = 0; break; } // no seeking
+ else { // sucess
+ edl_muted = 0;
+ if (last_pos >= pts) {
+ // backwards seek detected!! Forget about this EDL skip altogether.
+ next_edl_record = next_edl_record->next;
+ } else {
+ for (next_edl_record = edl_records; next_edl_record; next_edl_record = next_edl_record->next) {
+ /* note the use of stop_sec,
+ meaning if by some magical way we landed in the MIDDLE of a censored area,
+ in the next loop it will jump out of it.
+ */
+ if (next_edl_record->stop_sec > pts) break; // we got to the right place.
+ if (next_edl_record->action == EDL_MUTE) edl_muted = !edl_muted; // toggle mute each time.
+ }
+ }
+ }
+ }
+
+ } else if (next_edl_record->action == EDL_MUTE) {
+ edl_muted = !edl_muted; // This variable does nothing for now.
+ mp_msg(MSGT_MENCODER, MSGL_DBG4, "EDL_MUTE: [%f]\n", next_edl_record->start_sec );
+ next_edl_record=next_edl_record->next;
+ }
+ }
+}
_______________________________________________
MPlayer-dev-eng mailing list
MPlayer-dev-eng@xxxxxxxxxxxx
https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng