00001
00002 #include "oxp_mpeg_codec.h"
00003
00004
00005
00006 extern "C" {
00007 typedef unsigned char uint8_t;
00008 typedef unsigned int uint32_t;
00009 #define this c_this
00010 #include <mpeg2dec/video_out.h>
00011 #include <mpeg2dec/mpeg2.h>
00012 #include <mpeg2dec/mm_accel.h>
00013 #undef this
00014 }
00015
00016 #include <vcl_cstdio.h>
00017 #include <vcl_cassert.h>
00018 #include <vcl_cstdlib.h>
00019 #include <vcl_cstring.h>
00020 #include <vcl_string.h>
00021 #include <vcl_iostream.h>
00022
00023 #include <vul/vul_file.h>
00024
00025 #include <oxp/oxp_yuv_to_rgb.h>
00026 #include <oxp/oxp_bunch_of_files.h>
00027 #include <oxp/oxp_vob_frame_index.h>
00028
00029 static bool verbose = false;
00030
00031
00032 static void my_draw(vo_frame_t *frame);
00033 static void my_field(vo_frame_t *, int);
00034 static vo_frame_t *my_get_frame(vo_instance_t *self, int flags);
00035 static void my_close(vo_instance_t *self);
00036 static int my_setup(vo_instance_t *self, int width, int height);
00037
00038
00039 static int demux(oxp_mpeg_codec_data* impl, unsigned char const *buf, unsigned char const *end, int flags);
00040
00041 struct oxp_mpeg_codec_data : vo_instance_t {
00042 struct decode_request {
00043 int frame;
00044 int x0, y0, w, h;
00045 unsigned char* buf;
00046 bool done;
00047 };
00048 enum output_format_t {
00049 grey, rgb
00050 };
00051 struct frame_plus_index : public vo_frame_t {
00052 int frame;
00053 };
00054
00055 oxp_bunch_of_files fp;
00056 oxp_vob_frame_index idx;
00057 int w;
00058 int h;
00059 int frame_number;
00060 int demux_track;
00061 int demux_pid;
00062 output_format_t output_format;
00063 int ring_buffer_pos;
00064 frame_plus_index *ring_buffer[8];
00065 uint32_t accel;
00066 mpeg2dec_t decoder;
00067 unsigned char (*ppm_frame)[3];
00068 decode_request* pending_decode;
00069
00070
00071
00072 bool seek_to_iframe_before(int desired);
00073 frame_plus_index *make_frame();
00074 void convert_frame(frame_plus_index* frame, decode_request* p);
00075 int decode_mpeg2(unsigned char const *start, unsigned char const *end);
00076 void destroy_frame(vo_frame_t *frame);
00077 void draw_grey(unsigned char *frame);
00078 void draw(unsigned char (*frame)[3]);
00079
00080 void decode_at_least_one();
00081 bool decode_until_desired(int f,
00082 void* buf,
00083 int bbox_x0,
00084 int bbox_y0,
00085 int bbox_w,
00086 int bbox_h);
00087 };
00088
00089
00090 oxp_mpeg_codec::oxp_mpeg_codec()
00091 {
00092 impl_ = new oxp_mpeg_codec_data;
00093
00094 impl_->pending_decode = 0;
00095 impl_->vo_instance_t::setup = &my_setup;
00096 impl_->vo_instance_t::close = &my_close;
00097 impl_->vo_instance_t::get_frame = &my_get_frame;
00098
00099 for (int i=0; i<8; ++i)
00100 impl_->ring_buffer[i] = 0;
00101 impl_->ring_buffer_pos = 0;
00102
00103 impl_->accel = MM_ACCEL_MLIB;
00104 vo_accel(impl_->accel);
00105
00106
00107 mpeg2_init(&impl_->decoder, impl_->accel, impl_);
00108
00109 impl_->ppm_frame = 0;
00110 impl_->demux_track = 0;
00111 impl_->demux_pid = 0;
00112 impl_->output_format = oxp_mpeg_codec_data::rgb;
00113 }
00114
00115 bool oxp_mpeg_codec_data::seek_to_iframe_before(int frame)
00116 {
00117 int start_frame_index;
00118 int lba = idx.frame_to_lba_of_prev_I_frame(frame, &start_frame_index);
00119
00120 typedef oxp_bunch_of_files::offset_t index_t;
00121 index_t byte = index_t(lba) * 2048;
00122
00123 if (verbose)
00124 vcl_cerr << __FILE__ << ": seek_to_iframe_before: Frame " << frame
00125 << " -> Start at closest frame " << start_frame_index
00126 << ", LBA " << lba << ", byte " << byte << '\n';
00127 if (lba < 0)
00128 {
00129 vcl_cerr << __FILE__ << ": ERROR!\n";
00130 return false;
00131 }
00132 if (!fp.seek(byte))
00133 {
00134 vcl_cerr << "oxp_mpeg_codec_data::seek_to_iframe_before: ERROR!\n";
00135 return false;
00136 }
00137 frame_number = start_frame_index-1;
00138 return true;
00139 }
00140
00141
00142
00143
00144
00145
00146 void oxp_mpeg_codec_data::decode_at_least_one()
00147 {
00148 int starting_frame_number = frame_number;
00149 int n;
00150 unsigned char buf[2048];
00151 while ((n = fp.read(buf, sizeof buf)) > 0) {
00152 unsigned char* start = &buf[0];
00153 unsigned char* end = start + n;
00154 if (demux_track)
00155 {
00156 if (::demux(this, start, end, 0))
00157 return;
00158 }
00159 else if (demux_pid)
00160 vcl_abort();
00161 else
00162
00163 this->decode_mpeg2(start, end);
00164
00165 if (frame_number > starting_frame_number)
00166 return;
00167 }
00168 }
00169
00170
00171
00172 bool oxp_mpeg_codec_data::decode_until_desired(int f,
00173 void* buf,
00174 int bbox_x0,
00175 int bbox_y0,
00176 int bbox_w,
00177 int bbox_h)
00178 {
00179 decode_request r;
00180 r.frame = f;
00181 r.buf = (unsigned char*)buf;
00182 r.x0 = bbox_x0;
00183 r.y0 = bbox_y0;
00184 r.w = bbox_w;
00185 r.h = bbox_h;
00186 r.done = false;
00187
00188
00189 for (int i = 0; i < 8; ++i)
00190 if (ring_buffer[i] && ring_buffer[i]->frame == f)
00191 {
00192 if (verbose)
00193 vcl_cerr << __FILE__ << ": decode_until_desired: Found frame " << f << " in ring buffer\n";
00194 convert_frame(ring_buffer[i], &r);
00195 r.done = true;
00196 return true;
00197 }
00198
00199
00200 if (f <= frame_number)
00201 {
00202 if (verbose)
00203 vcl_cerr << __FILE__ << ": decode_until_desired: Need to seek for " << f << '\n';
00204 return false;
00205 }
00206
00207
00208 pending_decode = &r;
00209
00210 unsigned char fbuf[2048];
00211 int n;
00212 while ((n = fp.read(fbuf, sizeof fbuf)) > 0)
00213 {
00214 unsigned char* start = &fbuf[0];
00215 unsigned char* end = start + n;
00216 if (demux_track)
00217 {
00218 if (::demux(this, start, end, 0))
00219 return r.done;
00220 }
00221 else if (demux_pid)
00222 vcl_abort();
00223 else
00224
00225 this->decode_mpeg2(start, end);
00226
00227 if (r.done)
00228 {
00229 pending_decode = 0;
00230 return true;
00231 }
00232 }
00233
00234 return false;
00235 }
00236
00237 int oxp_mpeg_codec_data::decode_mpeg2(unsigned char const *start, unsigned char const *end)
00238 {
00239 return mpeg2_decode_data(&decoder, const_cast<uint8_t*>(start), const_cast<uint8_t*>(end));
00240 }
00241
00242
00243
00244 static
00245 int my_setup(vo_instance_t *self, int width, int height)
00246 {
00247 if (verbose)
00248 vcl_cerr << __FILE__ << ": setup(" << width << ", " << height << ")\n";
00249 oxp_mpeg_codec_data *impl = (oxp_mpeg_codec_data*)self;
00250 impl->w = width;
00251 impl->h = height;
00252
00253 impl->frame_number = 0;
00254
00255 impl->ppm_frame = (uint8_t (*)[3]) vcl_malloc(3 * width * height);
00256
00257 return 0;
00258 }
00259
00260 static
00261 void my_close(vo_instance_t *self)
00262 {
00263 if (verbose) vcl_cerr << __FILE__ << ": close()\n";
00264 oxp_mpeg_codec_data *impl = (oxp_mpeg_codec_data*)self;
00265
00266 vcl_free(impl->ppm_frame);
00267 }
00268
00269 static
00270 vo_frame_t *
00271 my_get_frame(vo_instance_t *self, int flags)
00272 {
00273 #if 0
00274 #define VO_TOP_FIELD 1
00275 #define VO_BOTTOM_FIELD 2
00276 #define VO_BOTH_FIELDS (VO_TOP_FIELD | VO_BOTTOM_FIELD)
00277 #define VO_PREDICTION_FLAG 4
00278 #endif
00279 if (verbose)
00280 vcl_cerr << __FILE__ << ": get(" << flags << ")\n";
00281 oxp_mpeg_codec_data *impl = (oxp_mpeg_codec_data*)self;
00282
00283 if (! impl->ring_buffer[impl->ring_buffer_pos])
00284 impl->ring_buffer[impl->ring_buffer_pos] = impl->make_frame();
00285
00286 vo_frame_t *frame = impl->ring_buffer[impl->ring_buffer_pos ++];
00287 if (impl->ring_buffer_pos >= 8)
00288 impl->ring_buffer_pos = 0;
00289
00290 return frame;
00291 }
00292
00293
00294 oxp_mpeg_codec_data::frame_plus_index*
00295 oxp_mpeg_codec_data::make_frame()
00296 {
00297 frame_plus_index *frame = (frame_plus_index*) vcl_malloc(sizeof(frame_plus_index));
00298 if (verbose)
00299 vcl_cerr << __FILE__ << ": make_frame() : frame = " << frame << '\n';
00300 frame->base[0] = (uint8_t*) vcl_malloc( w * h );
00301 frame->base[1] = (uint8_t*) vcl_malloc((w>>1)*(h>>1));
00302 frame->base[2] = (uint8_t*) vcl_malloc((w>>1)*(h>>1));
00303 frame->copy = 0;
00304 frame->field = my_field;
00305 frame->draw = my_draw;
00306 frame->instance = this;
00307 frame->frame = -1;
00308 return frame;
00309 }
00310
00311 #if 0
00312 static
00313 void my_copy(vo_frame_t *f, uint8_t **b)
00314 {
00315 if (verbose) vcl_printf("my_copy()\n");
00316 }
00317 #endif
00318
00319 static
00320 void my_field(vo_frame_t *, int)
00321 {
00322 if (verbose) vcl_cout << "my_field()\n";
00323 }
00324
00325 static
00326 void my_draw(vo_frame_t *frame_p)
00327 {
00328 if (verbose)
00329 vcl_cout << "draw: frame = " << frame_p << "\nmy_draw()\n";
00330 oxp_mpeg_codec_data *impl = (oxp_mpeg_codec_data*)frame_p->instance;
00331 oxp_mpeg_codec_data::frame_plus_index* frame =
00332 static_cast<oxp_mpeg_codec_data::frame_plus_index*>(frame_p);
00333
00334 ++impl->frame_number;
00335 frame->frame = impl->frame_number;
00336
00337 oxp_mpeg_codec_data::decode_request* p = impl->pending_decode;
00338 if (!p)
00339
00340 return;
00341
00342
00343 if (p->frame == impl->frame_number)
00344 {
00345 if (verbose)
00346 vcl_cerr << __FILE__ << ": Found " << impl->frame_number << '\n';
00347 impl->convert_frame(frame, p);
00348 p->done = true;
00349 }
00350 else if (verbose)
00351 {
00352 if (impl->frame_number < p->frame)
00353 vcl_cerr << __FILE__ << ": Skipping " << impl->frame_number << " waiting for " << p->frame << '\n';
00354 else
00355 vcl_cerr << __FILE__ << ": Queuing " << impl->frame_number << " having got " << p->frame << '\n';
00356 }
00357 }
00358
00359 void oxp_mpeg_codec_data::convert_frame(frame_plus_index* frame,
00360 decode_request* p)
00361 {
00362
00363
00364
00365 uint8_t *Y = frame->base[0];
00366 uint8_t *U = frame->base[1];
00367 uint8_t *V = frame->base[2];
00368
00369 if (this->output_format == oxp_mpeg_codec_data::grey)
00370 {
00371
00372
00373
00374
00375
00376 int c = 0;
00377 for (int i=p->y0; i<p->h; ++i)
00378 for (int j=p->x0; j<p->w; ++j, ++c)
00379
00380 p->buf[c]= Y[i*p->w+j];
00381 }
00382 else
00383 {
00384
00385
00386
00387
00388 int c = 0;
00389 for (int i=p->y0; i<p->h; ++i)
00390 for (int j=p->x0; j<p->w; ++j, c+=3)
00391
00392 oxp_yuv_to_rgb(Y[i*w+j],
00393 U[(i>>1)*(p->w>>1)+(j>>1)],
00394 V[(i>>1)*(p->w>>1)+(j>>1)],
00395 &p->buf[c]);
00396 }
00397 }
00398
00399
00400 void oxp_mpeg_codec_data::destroy_frame(vo_frame_t *frame)
00401 {
00402 assert(frame->instance == this);
00403 vcl_free(frame->base[0]); frame->base[0] = (uint8_t*)0xDEADBEEF;
00404 vcl_free(frame->base[1]); frame->base[1] = (uint8_t*)0xDEADBEEF;
00405 vcl_free(frame->base[2]); frame->base[2] = (uint8_t*)0xDEADBEEF;
00406 vcl_free(frame);
00407 }
00408
00409
00410 oxp_mpeg_codec::~oxp_mpeg_codec()
00411 {
00412 if (impl_)
00413 {
00414
00415 vcl_cerr << "oxp_mpeg_codec: WARNING: deleting before close() was called\n";
00416
00417
00418
00419
00420 for (int i=0; i<8; ++i)
00421 if (impl_->ring_buffer[i])
00422 {
00423 impl_->destroy_frame(impl_->ring_buffer[i]);
00424 impl_->ring_buffer[i] = 0;
00425 }
00426
00427 delete impl_;
00428 impl_ = 0;
00429 }
00430 }
00431
00432
00433 void oxp_mpeg_codec::close()
00434 {
00435 if (impl_)
00436 {
00437
00438 mpeg2_close(&impl_->decoder);
00439
00440
00441 vo_close(impl_);
00442
00443 for (int i=0; i<8; ++i)
00444 if (impl_->ring_buffer[i])
00445 {
00446 impl_->destroy_frame(impl_->ring_buffer[i]);
00447 impl_->ring_buffer[i] = 0;
00448 }
00449
00450 delete impl_;
00451 impl_ = 0;
00452 }
00453 }
00454
00455
00456
00457 bool oxp_mpeg_codec::get_section(int position,
00458 void* ib,
00459 int x0,
00460 int y0,
00461 int xs,
00462 int ys) const
00463 {
00464 position += 2;
00465
00466 const int FRAMES_TO_FFWD_RATHER_THAN_SEEK = 20;
00467 if (impl_->frame_number < position + 8 &&
00468 impl_->frame_number > position - FRAMES_TO_FFWD_RATHER_THAN_SEEK)
00469 if (impl_->decode_until_desired(position, ib, x0, y0, xs, ys))
00470 return true;
00471
00472
00473 if (!impl_->seek_to_iframe_before(position))
00474 return false;
00475
00476 return impl_->decode_until_desired(position, ib, x0, y0, xs, ys);
00477 }
00478
00479
00480
00481
00482
00483
00484 int oxp_mpeg_codec::put_section(int position,
00485 void* ib,
00486 int x0, int y0,
00487 int xs, int ys)
00488 {
00489 vcl_cerr << "oxp_mpeg_codec::put_section not implemented\n";
00490 return -1;
00491 }
00492
00493
00494
00495
00496 bool oxp_mpeg_codec::probe(vcl_string const& fname)
00497 {
00498 if (verbose)
00499 vcl_cerr << "oxp_mpeg_codec::probe[" << fname << "]\n";
00500
00501
00502 if (vcl_FILE* fp = vcl_fopen(fname.c_str(), "rb"))
00503 {
00504 unsigned int buf = 0xffffffffu;
00505 vcl_fread(&buf, 1, 4, fp);
00506 vcl_fclose(fp);
00507
00508 bool ok = false;
00509 if (buf == 0x000001b3 || buf == 0xb3010000)
00510 ok=true;
00511 if (buf == 0x000001ba || buf == 0xba010000)
00512 ok=true;
00513
00514 if (ok)
00515 return true;
00516 }
00517
00518 vcl_string fn(fname);
00519
00520 bool p = (vul_file::size((fn + ".lst").c_str()) > 0);
00521 if (verbose)
00522 vcl_cerr << "oxp_mpeg_codec::probe[" << fname << "] -> " << (p ? "true" : "false") << '\n';
00523 return p;
00524 }
00525
00526 bool oxp_mpeg_codec::load(vcl_string const& fname, char mode)
00527 {
00528
00529 bool is_mpeg = false;
00530 bool is_vob = false;
00531 {
00532 vcl_FILE* fp = vcl_fopen(fname.c_str(), "rb");
00533 if (fp)
00534 {
00535 unsigned int buf = 0xffffffffu;
00536 vcl_fread(&buf, 1, 4, fp);
00537 vcl_fclose(fp);
00538
00539 if (buf == 0x000001b3 || buf == 0xb3010000)
00540 is_mpeg = true;
00541 if (buf == 0x000001ba || buf == 0xba010000)
00542 is_vob = true;
00543 }
00544 }
00545
00546 if (is_mpeg || is_vob)
00547 {
00548 impl_->fp.open_1(fname.c_str());
00549 impl_->decode_at_least_one();
00550
00551
00552 char buf[1024];
00553 vcl_strcpy(buf, fname.c_str());
00554 char* p = vcl_strrchr(buf, '.');
00555 if (!p)
00556 p = buf + vcl_strlen(buf)-1;
00557 vcl_strcpy(p, ".idx");
00558 vcl_cerr << "Trying index file [" << buf << "] ... ";
00559 if (vul_file::size(buf) > 0)
00560 {
00561 vcl_cerr << " loading ...";
00562 impl_->idx.load(buf);
00563 }
00564 else
00565 {
00566 vcl_cerr << " not present, will not be able to seek\n";
00567 impl_->idx.add(0, 0);
00568 }
00569
00570
00571 impl_->demux_track = is_vob ? 0xe0 : 0;
00572 }
00573 else
00574 {
00575
00576 vcl_string fn = fname;
00577
00578 impl_->fp.open((fn + ".lst").c_str());
00579
00580 impl_->decode_at_least_one();
00581
00582 impl_->idx.load((fn + ".idx").c_str());
00583
00584 impl_->demux_track = 0xe0;
00585 }
00586
00587 return true;
00588 }
00589
00590
00591
00592 void oxp_mpeg_codec::set_demux_video()
00593 {
00594 impl_->demux_track = 0xe0;
00595 }
00596
00597 void oxp_mpeg_codec::set_output_format_grey()
00598 {
00599 impl_->output_format = oxp_mpeg_codec_data::grey;
00600 }
00601
00602 void oxp_mpeg_codec::set_output_format_rgb()
00603 {
00604 impl_->output_format = oxp_mpeg_codec_data::rgb;
00605 }
00606
00607 #if 0
00608 void my_decoder::dummy_chunk()
00609 {
00610
00611 static unsigned char const dummy[] = { 0, 0, 1, 0xB1 };
00612 decode(dummy, dummy + sizeof dummy);
00613 }
00614 #endif
00615
00616
00617
00618 #define DEMUX_PAYLOAD_START 1
00619 static int demux(oxp_mpeg_codec_data* impl, unsigned char const *buf, unsigned char const *end, int flags)
00620 {
00621 static int mpeg1_skip_table[16] = { 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 #define DEMUX_HEADER 0
00638 #define DEMUX_DATA 1
00639 #define DEMUX_SKIP 2
00640 static int state = DEMUX_SKIP;
00641 static int state_bytes = 0;
00642 static uint8_t head_buf[264];
00643
00644 uint8_t * header;
00645 int bytes;
00646 int len;
00647
00648 #define NEEDBYTES(x) \
00649 do { \
00650 int missing = (x) - bytes; \
00651 if (missing > 0) { \
00652 if (header == head_buf) { \
00653 if (missing <= end - buf) { \
00654 vcl_memcpy(header + bytes, buf, missing); \
00655 buf += missing; \
00656 bytes = (x); \
00657 } \
00658 else { \
00659 vcl_memcpy(header + bytes, buf, end - buf); \
00660 state_bytes = bytes + end - buf; \
00661 return 0; \
00662 } \
00663 } \
00664 else { \
00665 vcl_memcpy(head_buf, header, bytes); \
00666 state = DEMUX_HEADER; \
00667 state_bytes = bytes; \
00668 return 0; \
00669 } \
00670 } \
00671 } while (false)
00672
00673 #define DONEBYTES(x) \
00674 do { \
00675 if (header != head_buf) \
00676 buf = header + (x); \
00677 } while (false)
00678
00679
00680 if (flags & DEMUX_PAYLOAD_START)
00681 goto payload_start;
00682 switch (state) {
00683 case DEMUX_HEADER:
00684 if (state_bytes > 0)
00685 {
00686 header = head_buf;
00687 bytes = state_bytes;
00688 goto continue_header;
00689 }
00690 break;
00691 case DEMUX_DATA:
00692 if (impl->demux_pid || (state_bytes > end - buf))
00693 {
00694 impl->decode_mpeg2(buf, end);
00695 state_bytes -= end - buf;
00696 return 0;
00697 }
00698 impl->decode_mpeg2(buf, buf + state_bytes);
00699 buf += state_bytes;
00700 break;
00701 case DEMUX_SKIP:
00702 if (impl->demux_pid || (state_bytes > end - buf))
00703 {
00704 state_bytes -= end - buf;
00705 return 0;
00706 }
00707 buf += state_bytes;
00708 break;
00709 }
00710
00711 while (true) {
00712 if (impl->demux_pid)
00713 {
00714 state = DEMUX_SKIP;
00715 return 0;
00716 }
00717 payload_start:
00718 header = const_cast<unsigned char*>(buf);
00719 bytes = end - buf;
00720 continue_header:
00721 NEEDBYTES(4);
00722 if (header[0] || header[1] || (header[2] != 1))
00723 {
00724 if (impl->demux_pid)
00725 {
00726 state = DEMUX_SKIP;
00727 return 0;
00728 }
00729 else if (header != head_buf)
00730 {
00731 buf++;
00732 goto payload_start;
00733 }
00734 else
00735 {
00736 header[0] = header[1];
00737 header[1] = header[2];
00738 header[2] = header[3];
00739 bytes = 3;
00740 goto continue_header;
00741 }
00742 }
00743 if (impl->demux_pid)
00744 {
00745 if ((header[3] >= 0xe0) && (header[3] <= 0xef))
00746 goto pes;
00747 vcl_cerr << "bad stream id " << header[3] << '\n';
00748 vcl_exit(1);
00749 }
00750 switch (header[3]) {
00751 case 0xb9:
00752
00753
00754 return 1;
00755 case 0xba:
00756 NEEDBYTES(12);
00757 if ((header[4] & 0xc0) == 0x40)
00758 {
00759 NEEDBYTES(14);
00760 len = 14 + (header[13] & 7);
00761 NEEDBYTES(len);
00762 DONEBYTES(len);
00763
00764 }
00765 else if ((header[4] & 0xf0) == 0x20)
00766 {
00767 DONEBYTES(12);
00768
00769 }
00770 else
00771 {
00772 vcl_cerr << "weird pack header\n";
00773 vcl_exit(1);
00774 }
00775 break;
00776 default:
00777 if (header[3] == impl->demux_track)
00778 {
00779 pes:
00780 NEEDBYTES(7);
00781 if ((header[6] & 0xc0) == 0x80)
00782 {
00783 NEEDBYTES(9);
00784 len = 9 + header[8];
00785 NEEDBYTES(len);
00786
00787 }
00788 else
00789 {
00790 len = 7;
00791 while ((header-1)[len] == 0xff) {
00792 len++;
00793 NEEDBYTES(len);
00794 if (len == 23)
00795 {
00796 vcl_cerr << "too much stuffing\n";
00797 break;
00798 }
00799 }
00800 if (((header-1)[len] & 0xc0) == 0x40)
00801 {
00802 len += 2;
00803 NEEDBYTES(len);
00804 }
00805 len += mpeg1_skip_table[(header - 1)[len] >> 4];
00806 NEEDBYTES(len);
00807
00808 }
00809 DONEBYTES(len);
00810 bytes = 6 + (header[4] << 8) + header[5] - len;
00811 if (impl->demux_pid || (bytes > end - buf))
00812 {
00813 impl->decode_mpeg2(buf, end);
00814 state = DEMUX_DATA;
00815 state_bytes = bytes - (end - buf);
00816 return 0;
00817 }
00818 else if (bytes <= 0)
00819 continue;
00820 impl->decode_mpeg2(buf, buf + bytes);
00821 buf += bytes;
00822 }
00823 else if (header[3] < 0xb9)
00824 {
00825 vcl_cerr << "looks like a video stream, not system stream\n";
00826 vcl_exit(1);
00827 }
00828 else
00829 {
00830 NEEDBYTES(6);
00831 DONEBYTES(6);
00832 bytes = (header[4] << 8) + header[5];
00833 if (bytes > end - buf)
00834 {
00835 state = DEMUX_SKIP;
00836 state_bytes = bytes - (end - buf);
00837 return 0;
00838 }
00839 buf += bytes;
00840 }
00841 }
00842 }
00843 }
00844
00845 #if 0
00846 static void ts_loop(void)
00847 {
00848 #define PACKETS (BUFFER_SIZE / 188)
00849 int packets;
00850 do {
00851 packets = vcl_fread(buffer, 188, PACKETS, in_file);
00852 for (int i = 0; i < packets; i++)
00853 {
00854 uint8_t * buf = buffer + i * 188;
00855 uint8_t * end = buf + 188;
00856 if (buf[0] != 0x47)
00857 {
00858 vcl_cerr << "bad sync byte\n";
00859 vcl_exit(1);
00860 }
00861 int pid = ((buf[1] << 8) + buf[2]) & 0x1fff;
00862 if (pid != impl->demux_pid)
00863 continue;
00864 uint8_t * data = buf + 4;
00865 if (buf[3] & 0x20)
00866 {
00867 data = buf + 5 + buf[4];
00868 if (data > end)
00869 continue;
00870 }
00871 if (buf[3] & 0x10)
00872 demux(data, end, (buf[1] & 0x40) ? DEMUX_PAYLOAD_START : 0);
00873 }
00874 } while (packets == PACKETS);
00875 }
00876 #endif
00877
00878 int oxp_mpeg_codec::get_width() const
00879 {
00880 return impl_->w;
00881 }
00882
00883 int oxp_mpeg_codec::get_height() const
00884 {
00885 return impl_->h;
00886 }