+++ /dev/null
-#include "../libzmpeg3.h"
-
-static void
-toc_error()
-{
- zerr( "frame accurate seeking without a table of contents \n"
- "is no longer supported. Use mpeg3toc <mpeg file> <table of contents>\n"
- "to generate a table of contents and load the table of contents instead.\n");
-}
-
-void zvideo_t::
-cache_frame()
-{
- if( output_src[0] ) {
- int coded_size = coded_picture_width * coded_picture_height;
- int chrom_size = chrom_width * chrom_height;
- track->frame_cache->put_frame(framenum-1,
- output_src[0], output_src[1], output_src[2],
- coded_size, chrom_size, chrom_size);
- }
-}
-
-int zvideo_t::
-drop_frames(long frames, int cache_it)
-{
- int result = 0;
- long frame_number = framenum + frames;
-//zmsgs("drop frames framenum %d frames %ld\n", framenum, frames);
-
-/* Read the selected number of frames and skip b-frames */
- while(!result && frame_number > framenum ) {
- if( cache_it ) {
- result = read_frame_backend(0);
- if( !result && ref_frames > 1 )
- cache_frame();
- }
- else {
-//zmsgs("framenum %d frame_offset "_LX" last_packet_start "_LX" repeat %d/%d",
-// framenum,track->frame_offsets[framenum+1],vstream->demuxer->last_packet_start,
-// repeat_fields, current_field);
- result = read_frame_backend(frame_number - framenum);
-//zmsgs(" type %c\n","XIPBD"[pict_type]);
- }
- }
-
- return result;
-}
-
-int zbits_t::
-next_start_code()
-{
-//zmsg("1\n");
- /* search forwards */
- prev_byte_align();
- int64_t stream_end = demuxer->stream_end;
- if( demuxer->src->is_transport_stream() )
- demuxer->stream_end = demuxer->program_byte + MAX_TS_PROBE;
- else if( demuxer->src->is_program_stream() )
- demuxer->stream_end = demuxer->program_byte + MAX_PGM_PROBE;
- int zcode = -1, result = -1;
-
- while( !eof() ) {
- int bits = (uint8_t)zcode!=0 ? 24 : 8;
- zcode = (zcode<<bits) | get_bits_noptr(bits);
- if( (zcode&0xffffff) == PACKET_START_CODE_PREFIX ) {
- zcode = (zcode<<8) + get_byte_noptr();
- reset(result = zcode);
-//zmsgs("5 %04x\n",zcode);
- break;
- }
- }
-
- demuxer->stream_end = stream_end;
- return result;
-}
-
-/* Line up on the beginning of the next code. */
-int zbits_t::
-next_code(uint32_t zcode)
-{
- while(!eof() && show_bits_noptr(32) != zcode ) {
- get_byte_noptr();
- }
- return eof();
-}
-
-/* Line up on the beginning of the previous code. */
-int zdemuxer_t::
-prev_code(uint32_t zcode)
-{
- uint32_t current_code = 0;
-#define PREV_CODE_MACRO { current_code >>= 8; \
- current_code |= ((uint32_t)read_prev_char()) << 24; }
-
- PREV_CODE_MACRO
- PREV_CODE_MACRO
- PREV_CODE_MACRO
- PREV_CODE_MACRO
-
- while( !bof() && current_code != zcode ) {
- PREV_CODE_MACRO
- }
- return bof();
-}
-
-int zvideo_t::
-seek_byte(int64_t byte)
-{
- byte_seek = byte;
- return 0;
-}
-
-int zvideo_t::
-seek_frame(long frame)
-{
- frame_seek = frame;
- return 0;
-}
-
-int zvideo_t::
-rewind_video(int preload)
-{
- vstream->reset();
- framenum = 0;
- if( track->frame_offsets )
- vstream->seek_byte(track->frame_offsets[0]);
- else
- vstream->seek_byte(0);
- track->reset_pts();
- repeat_data = ref_frames = 0;
- last_number = framenum = -1;
- return preload ? read_frame_backend(0) : 0;
-}
-
-int zvideo_t::
-seek()
-{
- int result = 0;
- int64_t byte;
- long frame_number;
- int debug = 0;
- demuxer_t *demux = vstream->demuxer;
-
-/* Must do seeking here so files which don't use video don't seek. */
-/* Seeking is done in the demuxer */
-/* Seek to absolute byte */
- if( byte_seek >= 0 ) {
- byte = byte_seek;
- byte_seek = -1;
- if( byte != demux->tell_byte() ) {
- demux->seek_byte(byte);
- track->reset_pts();
- if( byte > 0 ) {
- //zmsg("1\n");
- demux->start_reverse();
- //zmsgs("1 "_LD"\n", demux->tell_byte());
- for( int i=0; i<2; ++i ) { /* Rewind 2 I-frames */
- if( has_gops ?
- demux->prev_code(GOP_START_CODE) :
- demux->prev_code(SEQUENCE_START_CODE) ) break;
- }
- //zmsgs("2 "_LD"\n", demux->tell_byte());
- demux->start_forward();
- if( track->frame_offsets ) {
- int64_t offset = demux->tell_byte();
- for( int k=0; k<track->total_keyframe_numbers; ++k ) {
- frame_number = track->keyframe_numbers[k];
- if( track->frame_offsets[frame_number] >= offset ) {
- /* first entry is special */
- framenum = frame_number>0 ? frame_number-1 : 0;
- break;
- }
- }
- }
- else {
- /* framenum no longer accurate, clear subtitles */
- reset_subtitles();
- }
- }
- else { /* Read first frame */
- rewind_video();
- }
- vstream->reset();
- repeat_data = ref_frames = 0;
- //zmsgs("4 "_LD"\n", demux->tell_byte());
- while( !result && !demux->eof() && demux->tell_byte() < byte ) {
- result = read_frame_backend(0);
- }
- }
- }
- else if( frame_seek >= 0 ) {
- /* Seek to a frame number */
- frame_number = frame_seek;
- frame_seek = -1;
- if( frame_number != framenum ) {
- if( debug ) zmsgs("%d\n", __LINE__);
- if( frame_number < 0 ) frame_number = 0;
- if( frame_number > maxframe ) frame_number = maxframe;
- if(debug) zmsgs("%d %ld %d\n", __LINE__, frame_number, framenum);
- /* Seek to I frame in table of contents. */
- /* Determine time between seek position and previous subtitle. */
- /* Subtract time difference from subtitle display time. */
- if( frame_number > 0 && track->frame_offsets ) {
- if( debug ) zmsgs("%d\n", __LINE__);
- track->frame_cache->reset();
- if( debug ) zmsgs("%d\n", __LINE__);
- if( frame_number < framenum ||
- frame_number-framenum > SEEK_THRESHOLD ) {
- int idx = track->find_keyframe_index(frame_number);
- /* back up 2 I frames, data may reference old refframes */
- if( --idx < 0 ) idx = 0;
- idx = track->keyframe_numbers[idx];
- byte = track->frame_offsets[idx];
- /* maybe lots of frames in one block, move is to earliest frame */
- while( idx > 0 && track->frame_offsets[idx-1] == byte ) --idx;
- if( debug ) zmsgs("%ld idx=%d, byte="_LD"\n", frame_number,idx,byte);
- framenum = idx-1;
- vstream->seek_byte(byte);
- track->reset_pts();
- repeat_data = ref_frames = 0;
- /* get the first I-frame. It does not count in the frame sequence */
- /* phys order is IBBPBBPBB... presentation order is BBIBBPBB... */
- result = read_frame_backend(0);
- }
- if( debug ) zmsgs("%d %ld %d\n", __LINE__,frame_number,framenum);
- if( !result && frame_number > framenum ) {
- /* Read up to current frame */
- int n = frame_number - framenum;
- result = drop_frames(n, n < MAX_CACHE_FRAMES ? 1 : 0);
- if( debug ) zmsgs("%d\n", __LINE__);
- }
- }
- else if( frame_number == 0 ) {
- result = rewind_video();
- }
- else {
- /* No support for seeking without table of contents */
- toc_error();
- result = 1;
- }
- }
- }
- else if( framenum < 0 ) { /* preload */
- result = rewind_video(1);
- }
- else
- return 0;
-
- seek_time = 0;
- return result;
-}
-
-int zvideo_t::
-previous_frame()
-{
- int result = 0;
- int64_t target_byte = 0;
- demuxer_t *demux = vstream->demuxer;
- if( demux->tell_byte() <= 0 ) return 1;
- /* Get location of end of previous picture */
- demux->start_reverse();
- result = demux->prev_code(PICTURE_START_CODE);
- if( !result ) result = demux->prev_code(PICTURE_START_CODE);
- if( !result ) result = demux->prev_code(PICTURE_START_CODE);
- if( !result ) target_byte = demux->tell_byte();
- if( !result ) { /* Rewind 2 I-frames */
- if( has_gops )
- result = demux->prev_code(GOP_START_CODE);
- else
- result = demux->prev_code(SEQUENCE_START_CODE);
- }
-
- if( !result )
- {
- if( has_gops )
- result = demux->prev_code(GOP_START_CODE);
- else
- result = demux->prev_code(SEQUENCE_START_CODE);
- }
-
- demux->start_forward();
- vstream->reset();
-
- result = 0; /* Read up to correct byte */
- repeat_data = ref_frames = 0;
- while( !result && !demux->eof() && demux->tell_byte() < target_byte ) {
- result = read_frame_backend(0);
- }
- repeat_data = 0;
-
- return 0;
-}
-