/******************************************************************* MPEG VIDEO Stream read module *******************************************************************/ #include #include #include "program_stream.h" #define VIDEO_STREAM_C #include "video_stream.h" int open_video_stream(char *path, VIDEO_STREAM *out); int close_video_stream(VIDEO_STREAM *p); int vs_get_bits(VIDEO_STREAM *in, int num_of_bits); int vs_read_bits(VIDEO_STREAM *in, int num_of_bits); int vs_erase_bits(VIDEO_STREAM *in, int num_of_bits); int vs_next_start_code(VIDEO_STREAM *in); __int64 video_stream_tell(VIDEO_STREAM *p); __int64 video_stream_seek(VIDEO_STREAM *p, __int64 offset, int origin); static int fill_bits(VIDEO_STREAM *p); static int video_stream_getc(VIDEO_STREAM *p); static unsigned char *find_next_start_code_in_current_buffer(VIDEO_STREAM *in); /*******************************************************************/ int open_video_stream(char *path, VIDEO_STREAM *out) { memset(out, 0, sizeof(VIDEO_STREAM)); strcpy(out->path, path); out->fd = _open(path, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL); if(out->fd == -1){ return 0; } out->close = _close; out->read = _read; out->seek = _lseeki64; out->tell = _telli64; out->buffer_size = out->read(out->fd, out->buffer+VIDEO_STREAM_BUFFER_MARGIN, VIDEO_STREAM_BUFFER_SIZE); if(out->buffer_size == 0){ return 0; } out->current = out->buffer+VIDEO_STREAM_BUFFER_MARGIN; fill_bits(out); vs_next_start_code(out); if(vs_read_bits(out, 32) == 0x1ba){ /* program_stream */ out->close(out->fd); out->fd = ps_open(path, PES_STREAM_TYPE_VIDEO); if(out->fd == -1){ return 0; } out->close = ps_close; out->read = ps_read; out->seek = ps_seek; out->tell = ps_tell; } out->file_length = out->seek(out->fd, 0, SEEK_END); out->seek(out->fd, 0, SEEK_SET); out->buffer_size = out->read(out->fd, out->buffer+VIDEO_STREAM_BUFFER_MARGIN, VIDEO_STREAM_BUFFER_SIZE); return 1; } /*******************************************************************/ int close_video_stream(VIDEO_STREAM *p) { p->close(p->fd); return 1; } /*******************************************************************/ int vs_get_bits(VIDEO_STREAM *in, int num_of_bits) { int r; r = 0; while(num_of_bits){ if(num_of_bits <= in->bits_rest){ r |= (in->bits >> (in->bits_rest - num_of_bits)); in->bits_rest -= num_of_bits; fill_bits(in); return r; }else{ num_of_bits -= in->bits_rest; r |= (in->bits << num_of_bits); in->bits_rest = 0; fill_bits(in); if(in->bits_rest == 0){ num_of_bits = 0; } } } return r; } /*******************************************************************/ int vs_read_bits(VIDEO_STREAM *in, int num_of_bits) { if(num_of_bits <= in->bits_rest){ return in->bits >> (in->bits_rest - num_of_bits); }else{ return in->bits << (num_of_bits - in->bits_rest); } } /*******************************************************************/ int vs_erase_bits(VIDEO_STREAM *in, int num_of_bits) { while(num_of_bits){ if(num_of_bits <= in->bits_rest){ in->bits_rest -= num_of_bits; fill_bits(in); return 1; }else{ num_of_bits -= in->bits_rest; in->bits_rest = 0; fill_bits(in); if(in->bits_rest == 0){ return 0; } } } return 1; } /*******************************************************************/ int vs_next_start_code(VIDEO_STREAM *in) { int i,n; unsigned char *p; n = in->bits_rest / 8; in->current -= n; if(in->current < in->buffer + VIDEO_STREAM_BUFFER_MARGIN){ for(i=0;icurrent[i] = (unsigned char)((in->bits >> ((n-i-1)*8)) & 0xff); } } while( (p = find_next_start_code_in_current_buffer(in)) == NULL ){ memcpy(in->buffer, in->buffer+in->buffer_size, VIDEO_STREAM_BUFFER_MARGIN); in->current = in->buffer+VIDEO_STREAM_BUFFER_MARGIN-2; in->last_position = in->tell(in->fd); in->buffer_size = in->read(in->fd, in->buffer+VIDEO_STREAM_BUFFER_MARGIN, VIDEO_STREAM_BUFFER_SIZE); if(in->buffer_size == 0){ return 0; } } in->current = p; in->bits_rest = 0; fill_bits(in); return 1; } /*******************************************************************/ __int64 video_stream_tell(VIDEO_STREAM *p) { __int64 r,n; n = p->current - p->buffer - (p->bits_rest / 8); if(n < VIDEO_STREAM_BUFFER_MARGIN){ r = p->last_position; }else{ r = p->tell(p->fd); r -= p->buffer_size; } r -= VIDEO_STREAM_BUFFER_MARGIN; r += n; return r; } /*******************************************************************/ __int64 video_stream_seek(VIDEO_STREAM *p, __int64 offset, int origin) { p->seek(p->fd, offset, origin); p->buffer_size = p->read(p->fd, p->buffer+VIDEO_STREAM_BUFFER_MARGIN, VIDEO_STREAM_BUFFER_SIZE); p->current = p->buffer+VIDEO_STREAM_BUFFER_MARGIN; p->bits_rest = 0; fill_bits(p); return video_stream_tell(p); } /*-----------------------------------------------------------------*/ static int fill_bits(VIDEO_STREAM *p) { int i,n,c; n = sizeof(int)*8 - p->bits_rest; n >>= 3; p->bits &= ( (1 << p->bits_rest) - 1); for(i=0;ibits <<= 8; p->bits |= c; p->bits_rest += 8; }else{ return 0; } } return 1; } /*-----------------------------------------------------------------*/ static int video_stream_getc(VIDEO_STREAM *p) { int r; if(p->current < p->buffer + p->buffer_size + VIDEO_STREAM_BUFFER_MARGIN){ r = p->current[0]; p->current += 1; return r; }else{ p->last_position = p->tell(p->fd); p->buffer_size = p->read(p->fd, p->buffer+VIDEO_STREAM_BUFFER_MARGIN, VIDEO_STREAM_BUFFER_SIZE); p->current = p->buffer+VIDEO_STREAM_BUFFER_MARGIN; if(p->buffer_size == 0){ return EOF; } r = p->current[0]; p->current += 1; return r; } } /*-----------------------------------------------------------------*/ static unsigned char *find_next_start_code_in_current_buffer(VIDEO_STREAM *in) { int i; unsigned char *p,*last; static int jump_table[256] = { 2, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, }; static const unsigned char pattern[3] = { 0, 0, 1, }; i = 0; p = in->current; last = in->buffer + VIDEO_STREAM_BUFFER_MARGIN + in->buffer_size - 2; while(i<3){ if( p < last ){ if(p[i] == pattern[i]){ i++; }else{ i = 0; p += jump_table[p[3]]; } }else{ return NULL; } } return p; }