00001
00002 #include "vidl_vil1_mpegcodec.h"
00003 #include <vidl_vil1/vidl_vil1_yuv_2_rgb.h>
00004 #include <vcl_cstring.h>
00005 #include <vcl_iostream.h>
00006 #include <vcl_cassert.h>
00007 #include <vcl_cstdlib.h>
00008 #include <vul/vul_file.h>
00009 #include <vil1/vil1_image.h>
00010 #include <vil1/vil1_memory_image_of.h>
00011 #include <vil1/vil1_rgb_byte.h>
00012 #undef sprintf // Works around a bug in libintl.h
00013 #include <vcl_cstdio.h>
00014
00015 extern "C" {
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 extern uint32_t vo_mm_accel;
00041
00042 int libvo_common_alloc_frames (vo_instance_t * instance, int width, int height,
00043 int frame_size,
00044 void (* copy) (vo_frame_t *, uint8_t **),
00045 void (* field) (vo_frame_t *, int),
00046 void (* draw) (vo_frame_t *));
00047 void libvo_common_free_frames (vo_instance_t * instance);
00048 vo_frame_t * libvo_common_get_frame (vo_instance_t * instance, int prediction);
00049
00050 #define MODE_RGB 0x1
00051 #define MODE_BGR 0x2
00052
00053 extern void (* yuv2rgb) (uint8_t * image, uint8_t * py,
00054 uint8_t * pu, uint8_t * pv, int h_size, int v_size,
00055 int rgb_stride, int y_stride, int uv_stride);
00056
00057 void yuv2rgb_init (int bpp, int mode);
00058 int yuv2rgb_init_mmxext (int bpp, int mode);
00059 int yuv2rgb_init_mmx (int bpp, int mode);
00060 int yuv2rgb_init_mlib (int bpp, int mode);
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 static void internal_draw_frame (vidl_vil1_mpegcodec_data * instance,
00075 vo_frame_t * frame,
00076 unsigned char * buf)
00077 {
00078 uint8_t *Y = frame->base[0];
00079 uint8_t *U = frame->base[1];
00080 uint8_t *V = frame->base[2];
00081 decode_request * p = instance->pending_decode;
00082
00083 int c = 0;
00084 int w = instance->width;
00085
00086
00087 int roix = p->x0;
00088 int roiy = p->y0;
00089 int roiw = p->w;
00090 int roih = p->h;
00091
00092 int wh = w>>1;
00093
00094 if (instance->output_format == vidl_vil1_mpegcodec_data::GREY)
00095 {
00096
00097 for (int i=roiy; i<(roiy+roih); ++i)
00098 for (int j=roix; j<(roix+roiw); ++j, ++c)
00099 buf[c]= Y[i*p->w+j];
00100 }
00101 else
00102 {
00103
00104 for (int i=roiy; i<(roiy+roih); ++i)
00105 for (int j=roix; j<(roix+roiw); ++j, c+=3)
00106 {
00107 int arg = (i>>1)*(wh)+(j>>1);
00108
00109 vidl_vil1_yuv_2_rgb(Y[i*w+j],
00110 U[arg],
00111 V[arg],
00112 &(buf[c]));
00113 }
00114 }
00115 return;
00116 }
00117
00118 static int internal_setup (vo_instance_t * instance_,
00119 int width,
00120 int height,
00121 void (* draw_frame) (vo_frame_t *))
00122 {
00123 vidl_vil1_mpegcodec_data * instance;
00124
00125 instance = (vidl_vil1_mpegcodec_data *) instance_;
00126
00127 instance->close = libvo_common_free_frames;
00128 instance->get_frame = libvo_common_get_frame;
00129 instance->width = width;
00130 instance->height = height;
00131
00132
00133
00134 decode_request * p = instance->pending_decode;
00135 if ((p->x0+p->w)>width) p->w = width - p->x0;
00136 if ((p->y0+p->h)>height) p->h = height - p->y0;
00137
00138 int hh = height>>1;
00139 vcl_sprintf(instance->header, "P5\n\n%d %d\n255\n", width, hh * 3);
00140 return libvo_common_alloc_frames ((vo_instance_t *) instance,
00141 width,
00142 height,
00143 sizeof (vo_frame_t),
00144 0, 0, draw_frame);
00145 }
00146
00147 static void vil1_im_draw_frame (vo_frame_t * frame)
00148 {
00149 vidl_vil1_mpegcodec_data * instance;
00150
00151 instance = (vidl_vil1_mpegcodec_data *) frame->instance;
00152 int n = ++(instance->framenum);
00153 if ( n < 0)
00154 return;
00155
00156 decode_request * p = instance->pending_decode;
00157 if (!p)
00158 {
00159 vcl_cerr << __FILE__ ": vil1_im_draw_frame(): decode request was never set\n";
00160 return;
00161 }
00162
00163 frame_buffer * fb = instance->buffers;
00164
00165 if (p->rt == decode_request::SEEK)
00166 {
00167 if (instance->framenum == p->position )
00168 p->done = true;
00169
00170 internal_draw_frame (instance, frame, fb->next(n));
00171 }
00172 else if (p->rt == decode_request::FILE_GRAB)
00173 internal_draw_frame (instance, frame, fb->next(n));
00174
00175 return;
00176 }
00177
00178
00179
00180
00181 static int vil1_im_setup (vo_instance_t * instance, int width, int height)
00182 {
00183 return internal_setup (instance, width, height, vil1_im_draw_frame);
00184 }
00185
00186
00187 vo_instance_t * vo_vil_im_open (void)
00188 {
00189 vidl_vil1_mpegcodec_data * instance;
00190
00191 instance = new vidl_vil1_mpegcodec_data;
00192
00193
00194 instance->setup = vil1_im_setup;
00195 instance->framenum = -2;
00196 return (vo_instance_t *) instance;
00197 }
00198
00199
00200 vidl_vil1_mpegcodec::vidl_vil1_mpegcodec()
00201 {
00202 decoder_ = 0;
00203 buffers_ = new frame_buffer;
00204 inited = false;
00205 set_number_frames(-1);
00206 }
00207
00208 vidl_vil1_mpegcodec::~vidl_vil1_mpegcodec()
00209 {
00210 vcl_cout << "vidl_vil1_mpegcodec::~vidl_vil1_mpegcodec. entering\n";
00211 if (decoder_) decoder_->print();
00212 buffers_->print();
00213 vcl_cout << "first frame number in memory is: " << buffers_->first_frame_num() << vcl_endl;
00214 delete buffers_;
00215 if (decoder_) delete decoder_;
00216
00217 vcl_cout << "vidl_vil1_mpegcodec::~vidl_vil1_mpegcodec. exiting\n";
00218 }
00219
00220 void
00221 vidl_vil1_mpegcodec::set_grey_scale(bool grey)
00222 {
00223 if (!decoder_)
00224 {
00225 vcl_cout << "vidl_vil1_mpegcodec::set_gray_scale. need to load file first.\n";
00226 return;
00227 }
00228
00229 if (grey) decoder_->output_->output_format = vidl_vil1_mpegcodec_data::GREY;
00230 else decoder_->output_->output_format = vidl_vil1_mpegcodec_data::RGB;
00231 }
00232
00233
00234
00235
00236
00237 vidl_vil1_codec_sptr vidl_vil1_mpegcodec::load(vcl_string const& fname, char )
00238 {
00239
00240
00241
00242 if (this->probe(fname))
00243 {
00244 decoder_ = new vidl_vil1_mpegcodec_helper(vo_vil_im_open,
00245 fname,
00246 buffers_);
00247 return this;
00248 }
00249 return 0;
00250 }
00251
00252 bool
00253 vidl_vil1_mpegcodec::get_section(int position,
00254 void* ib,
00255 int x0,
00256 int y0,
00257 int width,
00258 int height) const
00259 {
00260 assert(inited == true);
00261 assert(x0+width <= this->width());
00262 assert(y0+height <= this->height());
00263
00264
00265
00266
00267 if (position < buffers_->first_frame_num())
00268 {
00269 decode_request req;
00270 req.rt = decode_request::REWIND;
00271 req.position = position;
00272 req.x0 = x0;
00273 req.y0 = y0;
00274 req.w = width;
00275 req.h = height;
00276 req.done = false;
00277 decoder_->execute(&req);
00278 buffers_->reset();
00279
00280 req.rt = decode_request::SEEK;
00281
00282 decoder_->execute(&req);
00283 }
00284
00285
00286 else if (position > decoder_->get_last_frame())
00287 {
00288 decode_request req;
00289 req.rt = decode_request::SEEK;
00290 req.position = position;
00291 req.x0 = x0;
00292 req.y0 = y0;
00293 req.w = width;
00294 req.h = height;
00295 req.done = false;
00296 decoder_->execute(&req);
00297 }
00298
00299 else
00300 {
00301 if ((decoder_->get_last_frame() - position) < 10)
00302 {
00303 decode_request req;
00304 req.rt = decode_request::FILE_GRAB;
00305 req.position = position;
00306 req.x0 = x0;
00307 req.y0 = y0;
00308 req.w = width;
00309 req.h = height;
00310 req.done = false;
00311
00312
00313
00314
00315 decoder_->execute(&req);
00316 decoder_->execute(&req);
00317 }
00318 }
00319
00320 unsigned char * buf = buffers_->get_buff(position);
00321 vcl_memcpy(ib,(void *) buf,((this->get_bytes_pixel())*width*height));
00322
00323 return true;
00324 }
00325
00326 bool
00327 vidl_vil1_mpegcodec::probe(vcl_string const& fname)
00328 {
00329 vcl_string exten = vul_file::extension(fname);
00330 bool isthere = vul_file::exists(fname) && (exten == ".mpeg" ||
00331 exten == ".mpe" ||
00332 exten == ".mpg" ||
00333 exten == ".mp2" ||
00334 exten == ".mp1");
00335
00336 return isthere;
00337 }
00338
00339 void
00340 vidl_vil1_mpegcodec::set_demux_video()
00341 {
00342 decoder_->demux_track_ = 0xe0;
00343 }
00344
00345 void
00346 vidl_vil1_mpegcodec::set_pid(vcl_string pid)
00347 {
00348 decoder_->demux_pid_ = vcl_strtol(pid.c_str(),0,16);
00349 }
00350
00351
00352
00353 bool
00354 vidl_vil1_mpegcodec::init()
00355 {
00356 if (inited) return true;
00357
00358
00359
00360
00361
00362
00363 decode_request req;
00364 req.rt = decode_request::SKIP;
00365 req.position = 0;
00366 req.x0 = 0;
00367 req.y0 = 0;
00368 req.w = 1000;
00369 req.h = 1000;
00370 req.done = false;
00371
00372 decoder_->init();
00373
00374
00375
00376
00377
00378 if (this->length() == -1)
00379 {
00380 while (decoder_->execute(&req) != -1);
00381 this->set_number_frames(decoder_->get_last_frame());
00382 }
00383 else decoder_->execute(&req);
00384
00385 req.rt = decode_request::REWIND;
00386 decoder_->execute(&req);
00387
00388
00389
00390 int w = decoder_->get_width();
00391 int h = decoder_->get_height();
00392
00393
00394
00395 int b;
00396 this->set_width(w);
00397 this->set_height(h);
00398 if (decoder_->get_format() == vidl_vil1_mpegcodec_data::RGB)
00399 b=24;
00400 else
00401 b=8;
00402 set_bits_pixel(b);
00403
00404
00405 buffers_->init(w,h,b);
00406
00407
00408 req.rt = decode_request::SEEK;
00409 req.position = 20;
00410 req.x0 = 0;
00411 req.y0 = 0;
00412 req.w = w;
00413 req.h = h;
00414 req.done = false;
00415
00416 decoder_->execute(&req);
00417
00418
00419 inited = true;
00420 return true;
00421 }
00422
00423 #if 0
00424
00425
00426
00427
00428 vil1_image *
00429 vidl_vil1_mpegcodec::get_image(int frame_position,
00430 int x0,
00431 int y0,
00432 int width,
00433 int height)
00434 {
00435 vil1_image * frame = 0;
00436
00437 int indy = width * height * this->get_bytes_pixel();
00438 unsigned char ib[indy];
00439 this->get_section(frame_position,(void*)ib,x0,y0,width,height);
00440
00441 if (decoder_->get_format() == vidl_vil1_mpegcodec_data::GREY)
00442 frame = new vil1_memory_image_of<unsigned char >(&ib[0],this->width(),this->height());
00443 else
00444 {
00445 int w = this->width();
00446 int h = this->height();
00447 vil1_rgb_byte bites[w*h];
00448 int c=0;
00449 for (int i=0; i<(w*h); i++,c+=3)
00450 bites[i] = vil1_rgb_byte(ib[c],ib[c+1],ib[c+2]);
00451 frame = new vil1_memory_image_of<vil1_rgb_byte >(&bites[0],w,h);
00452 }
00453 return frame;
00454 }
00455 #endif // 0