Mercurial > mplayer.hg
comparison mencoder.c @ 14964:92e234f53156
EDL for mencoder, patch by Oded (ods15)
Committed with a few minor fixes. Needs documentation still.
author | rfelker |
---|---|
date | Sat, 19 Mar 2005 20:55:51 +0000 |
parents | 7e7b077b7a50 |
children | 576b810a034d |
comparison
equal
deleted
inserted
replaced
14963:1c021862e1af | 14964:92e234f53156 |
---|---|
268 static void parse_end_at(); | 268 static void parse_end_at(); |
269 static char * end_at_string=0; | 269 static char * end_at_string=0; |
270 //static uint8_t* flip_upside_down(uint8_t* dst, const uint8_t* src, int width, int height); | 270 //static uint8_t* flip_upside_down(uint8_t* dst, const uint8_t* src, int width, int height); |
271 | 271 |
272 #include "get_path.c" | 272 #include "get_path.c" |
273 | |
274 #ifdef USE_EDL | |
275 #include "edl.h" | |
276 static edl_record_ptr edl_records = NULL; ///< EDL entries memory area | |
277 static edl_record_ptr next_edl_record = NULL; ///< only for traversing edl_records | |
278 static short edl_muted; ///< Stores whether EDL is currently in muted mode. | |
279 static short edl_seeking; ///< When non-zero, stream is seekable. | |
280 static short edl_seek_type; ///< When non-zero, frames are discarded instead of seeking. | |
281 static short edl_skip; ///< -1 OR the value of in_size of an already read frame. | |
282 /** \brief Seeks for EDL | |
283 \return 1 for success, 0 for failure, 2 for EOF. | |
284 */ | |
285 int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, float * frame_time, unsigned char ** start, int framecopy); | |
286 #endif | |
273 | 287 |
274 #include "cfg-mplayer-def.h" | 288 #include "cfg-mplayer-def.h" |
275 #include "cfg-mencoder.h" | 289 #include "cfg-mencoder.h" |
276 | 290 |
277 #ifdef USE_DVDREAD | 291 #ifdef USE_DVDREAD |
1313 } | 1327 } |
1314 | 1328 |
1315 play_n_frames=play_n_frames_mf; | 1329 play_n_frames=play_n_frames_mf; |
1316 if (curfile && end_at_type == END_AT_TIME) end_at += mux_v->timer; | 1330 if (curfile && end_at_type == END_AT_TIME) end_at += mux_v->timer; |
1317 | 1331 |
1332 #ifdef USE_EDL | |
1333 if (edl_filename) { | |
1334 if (edl_records) free_edl(edl_records); | |
1335 next_edl_record = edl_records = edl_parse_file(); | |
1336 edl_muted = 0; | |
1337 edl_seeking = 1; | |
1338 edl_skip = -1; | |
1339 } | |
1340 #endif | |
1341 | |
1318 while(!at_eof){ | 1342 while(!at_eof){ |
1319 | 1343 |
1320 float frame_time=0; | 1344 float frame_time=0; |
1321 int blit_frame=0; | 1345 int blit_frame=0; |
1322 float a_pts=0; | 1346 float a_pts=0; |
1331 | 1355 |
1332 if(play_n_frames>=0){ | 1356 if(play_n_frames>=0){ |
1333 --play_n_frames; | 1357 --play_n_frames; |
1334 if(play_n_frames<0) break; | 1358 if(play_n_frames<0) break; |
1335 } | 1359 } |
1360 | |
1361 #ifdef USE_EDL | |
1362 goto_redo_edl: | |
1363 if (next_edl_record && sh_video && sh_video->pts >= next_edl_record->start_sec) { | |
1364 if (next_edl_record->action == EDL_SKIP && edl_seeking) { | |
1365 float last_pos = d_video->pts; | |
1366 int result; | |
1367 mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_SKIP: start [%f], stop [%f], length [%f]\n", | |
1368 next_edl_record->start_sec, next_edl_record->stop_sec, next_edl_record->length_sec); | |
1369 | |
1370 result = edl_seek(next_edl_record, demuxer, d_audio, mux_a, &frame_time, &start, mux_v->codec==VCODEC_COPY); | |
1371 | |
1372 if (result == 2) break; // EOF | |
1373 else if (result == 0) edl_seeking = 0; // no seeking | |
1374 else { // sucess | |
1375 edl_muted = 0; | |
1376 if (last_pos >= sh_video->pts) { | |
1377 // backwards seek detected!! Forget about this EDL skip altogether. | |
1378 next_edl_record = next_edl_record->next; | |
1379 } | |
1380 else for (next_edl_record = edl_records; next_edl_record; next_edl_record = next_edl_record->next) { | |
1381 /* note the use of stop_sec, | |
1382 meaning if by some magical way we landed in the MIDDLE of a censored area, | |
1383 in the next loop it will jump out of it. | |
1384 */ | |
1385 if (next_edl_record->stop_sec > sh_video->pts) break; // we got to the right place. | |
1386 if (next_edl_record->action == EDL_MUTE) edl_muted = !edl_muted; // toggle mute each time. | |
1387 } | |
1388 | |
1389 /* for a pedantic EDL, that doesn't show even a single | |
1390 frame from the "censored" area, uncomment next line. */ | |
1391 goto goto_redo_edl; | |
1392 } | |
1393 } else if (next_edl_record->action == EDL_MUTE) { | |
1394 edl_muted = !edl_muted; // This variable does nothing for now. | |
1395 mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_MUTE: [%f]\n", next_edl_record->start_sec ); | |
1396 next_edl_record=next_edl_record->next; | |
1397 } | |
1398 } | |
1399 #endif | |
1400 | |
1336 | 1401 |
1337 if(sh_audio){ | 1402 if(sh_audio){ |
1338 // get audio: | 1403 // get audio: |
1339 while(mux_a->timer-audio_preload<mux_v->timer){ | 1404 while(mux_a->timer-audio_preload<mux_v->timer){ |
1340 int len=0; | 1405 int len=0; |
1488 } | 1553 } |
1489 } | 1554 } |
1490 | 1555 |
1491 // get video frame! | 1556 // get video frame! |
1492 | 1557 |
1558 #ifdef USE_EDL | |
1559 if (edl_skip != -1) { in_size = edl_skip; edl_skip = -1; } | |
1560 else | |
1561 #endif | |
1493 in_size=video_read_frame(sh_video,&frame_time,&start,force_fps); | 1562 in_size=video_read_frame(sh_video,&frame_time,&start,force_fps); |
1494 if(in_size<0){ at_eof=1; break; } | 1563 if(in_size<0){ at_eof=1; break; } |
1495 sh_video->timer+=frame_time; ++decoded_frameno; | 1564 sh_video->timer+=frame_time; ++decoded_frameno; |
1496 frame_time /= playback_speed; | 1565 frame_time /= playback_speed; |
1497 | 1566 |
2048 return 0; | 2117 return 0; |
2049 } | 2118 } |
2050 #endif | 2119 #endif |
2051 | 2120 |
2052 static float stop_time(demuxer_t* demuxer, muxer_stream_t* mux_v) { | 2121 static float stop_time(demuxer_t* demuxer, muxer_stream_t* mux_v) { |
2053 // demuxer is for future support for EDL | |
2054 float timeleft = -1; | 2122 float timeleft = -1; |
2055 if (play_n_frames >= 0) timeleft = mux_v->timer + play_n_frames * (double)(mux_v->h.dwScale) / mux_v->h.dwRate; | 2123 if (play_n_frames >= 0) timeleft = mux_v->timer + play_n_frames * (double)(mux_v->h.dwScale) / mux_v->h.dwRate; |
2056 if (end_at_type == END_AT_TIME && (timeleft > end_at || timeleft == -1)) timeleft = end_at; | 2124 if (end_at_type == END_AT_TIME && (timeleft > end_at || timeleft == -1)) timeleft = end_at; |
2125 #ifdef USE_EDL | |
2126 if (next_edl_record && demuxer && demuxer->video) { // everything is OK to be checked | |
2127 float tmp = mux_v->timer + next_edl_record->start_sec - demuxer->video->pts; | |
2128 if (timeleft == -1 || timeleft > tmp) { | |
2129 // There's less time in EDL than what we already know | |
2130 if (next_edl_record->action == EDL_SKIP && edl_seeking) { | |
2131 timeleft = tmp; | |
2132 } else if (next_edl_record->action == EDL_MUTE) { | |
2133 //timeleft = next_edl_record->start_sec - demuxer->video->pts; | |
2134 // For the moment (and probably forever) EDL mute doesn't work in MEncoder | |
2135 } | |
2136 } | |
2137 } | |
2138 #endif | |
2057 return timeleft; | 2139 return timeleft; |
2058 } | 2140 } |
2141 | |
2142 #ifdef USE_EDL | |
2143 int edl_seek(edl_record_ptr next_edl_record, demuxer_t* demuxer, demux_stream_t *d_audio, muxer_stream_t* mux_a, float * frame_time, unsigned char ** start, int framecopy) { | |
2144 sh_audio_t * sh_audio = d_audio->sh; | |
2145 sh_video_t * sh_video = demuxer->video ? demuxer->video->sh : NULL; | |
2146 vf_instance_t * vfilter = sh_video ? sh_video->vfilter : NULL; | |
2147 | |
2148 if (!sh_video) return 0; | |
2149 if (sh_video->pts >= next_edl_record->stop_sec) return 1; // nothing to do... | |
2150 | |
2151 if (!edl_seek_type) { | |
2152 if(demux_seek(demuxer, next_edl_record->stop_sec - sh_video->pts, 0)){ | |
2153 sh_video->pts = demuxer->video->pts; | |
2154 //if (vo_vobsub) vobsub_seek(vo_vobsub,sh_video->pts); | |
2155 resync_video_stream(sh_video); | |
2156 //if(vo_spudec) spudec_reset(vo_spudec); | |
2157 return 1; | |
2158 } | |
2159 // non-seekable stream. | |
2160 return 0; | |
2161 } | |
2162 | |
2163 // slow seek, read every frame. | |
2164 | |
2165 while (!interrupted) { | |
2166 float a_pts = 0.; | |
2167 int in_size; | |
2168 | |
2169 in_size = video_read_frame(sh_video, frame_time, start, force_fps); | |
2170 if(in_size<0) return 2; | |
2171 sh_video->timer += *frame_time; | |
2172 | |
2173 if (sh_audio) { | |
2174 a_pts = d_audio->pts + (ds_tell_pts(d_audio) - sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; | |
2175 while (sh_video->pts > a_pts) { | |
2176 if (mux_a->h.dwSampleSize) { | |
2177 int len; | |
2178 len = mux_a->wf->nAvgBytesPerSec * (sh_video->pts - a_pts); | |
2179 len/= mux_a->h.dwSampleSize; if(len<1) len=1; | |
2180 len*= mux_a->h.dwSampleSize; | |
2181 demux_read_data(sh_audio->ds,mux_a->buffer,len); | |
2182 } else { | |
2183 ds_get_packet(sh_audio->ds,(unsigned char**) &mux_a->buffer); | |
2184 } | |
2185 a_pts = d_audio->pts + (ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; | |
2186 } | |
2187 } | |
2188 | |
2189 if (sh_video->pts >= next_edl_record->stop_sec) { | |
2190 edl_skip = in_size; | |
2191 if (!framecopy || (sh_video->ds->flags & 1)) return 1; | |
2192 } | |
2193 | |
2194 if (vfilter) { | |
2195 int softskip = (vfilter->control(vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) == CONTROL_TRUE); | |
2196 decode_video(sh_video, *start, in_size, !softskip); | |
2197 } | |
2198 | |
2199 mp_msg(MSGT_MENCODER, MSGL_STATUS, | |
2200 "EDL SKIP: Start: %.2f End: %.2lf Current: V: %.2f A: %.2f \r", | |
2201 next_edl_record->start_sec, next_edl_record->stop_sec, | |
2202 sh_video->pts, a_pts); | |
2203 } | |
2204 if (interrupted) return 2; | |
2205 return 1; | |
2206 } | |
2207 #endif |