00001
00002 #ifndef vidl2_ffmpeg_istream_v1_txx_
00003 #define vidl2_ffmpeg_istream_v1_txx_
00004 #include "vidl2_ffmpeg_istream.h"
00005
00006
00007
00008
00009
00010
00011
00012 #include "vidl2_ffmpeg_init.h"
00013 #include "vidl2_frame.h"
00014 #include "vidl2_ffmpeg_convert.h"
00015
00016 #include <vcl_string.h>
00017 #include <vcl_iostream.h>
00018
00019 extern "C" {
00020 #if FFMPEG_IN_SEVERAL_DIRECTORIES
00021 #include <libavcodec/avcodec.h>
00022 #include <libavformat/avformat.h>
00023 #else
00024 #include <ffmpeg/avcodec.h>
00025 #include <ffmpeg/avformat.h>
00026 #endif
00027 }
00028
00029
00030
00031 struct vidl2_ffmpeg_istream::pimpl
00032 {
00033 pimpl()
00034 : fmt_cxt_( NULL ),
00035 vid_index_( -1 ),
00036 vid_str_( NULL ),
00037 last_dts( 0 ),
00038 frame_( NULL ),
00039 num_frames_( 0 ),
00040 cur_frame_( NULL ),
00041 deinterlace_( false ),
00042 frame_number_offset_( 0 )
00043 {
00044 }
00045
00046 AVFormatContext* fmt_cxt_;
00047 int vid_index_;
00048 AVStream* vid_str_;
00049
00050
00051 int64_t last_dts;
00052
00053
00054
00055
00056
00057
00058 AVFrame* frame_;
00059
00060
00061 int num_frames_;
00062
00063
00064 vil_memory_chunk_sptr contig_memory_;
00065
00066
00067 mutable vidl2_frame_sptr cur_frame_;
00068
00069
00070 bool deinterlace_;
00071
00072
00073
00074 unsigned frame_number_offset_;
00075 };
00076
00077
00078
00079
00080
00081 vidl2_ffmpeg_istream::
00082 vidl2_ffmpeg_istream()
00083 : is_( new vidl2_ffmpeg_istream::pimpl )
00084 {
00085 vidl2_ffmpeg_init();
00086 }
00087
00088
00089
00090 vidl2_ffmpeg_istream::
00091 vidl2_ffmpeg_istream(const vcl_string& filename)
00092 : is_( new vidl2_ffmpeg_istream::pimpl )
00093 {
00094 vidl2_ffmpeg_init();
00095 open(filename);
00096 }
00097
00098
00099
00100 vidl2_ffmpeg_istream::
00101 ~vidl2_ffmpeg_istream()
00102 {
00103 close();
00104 delete is_;
00105 }
00106
00107
00108 bool
00109 vidl2_ffmpeg_istream::
00110 open(const vcl_string& filename)
00111 {
00112
00113 close();
00114
00115
00116 int err;
00117 if ( ( err = av_open_input_file( &is_->fmt_cxt_, filename.c_str(), NULL, 0, NULL ) ) != 0 ) {
00118 return false;
00119 }
00120
00121
00122 if ( av_find_stream_info( is_->fmt_cxt_ ) < 0 ) {
00123 return false;
00124 }
00125
00126
00127 is_->vid_index_ = -1;
00128 for ( unsigned int i = 0; i < is_->fmt_cxt_->nb_streams; ++i ) {
00129 #if LIBAVFORMAT_BUILD <= 4628
00130 AVCodecContext *enc = &is_->fmt_cxt_->streams[i]->codec;
00131 #else
00132 AVCodecContext *enc = is_->fmt_cxt_->streams[i]->codec;
00133 #endif
00134 if ( enc->codec_type == CODEC_TYPE_VIDEO ) {
00135 is_->vid_index_ = i;
00136 break;
00137 }
00138 }
00139 if ( is_->vid_index_ == -1 ) {
00140 return false;
00141 }
00142
00143 dump_format( is_->fmt_cxt_, 0, filename.c_str(), 0 );
00144 #if LIBAVFORMAT_BUILD <= 4628
00145 AVCodecContext *enc = &is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00146 #else
00147 AVCodecContext *enc = is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00148 #endif
00149
00150 AVCodec* codec = avcodec_find_decoder(enc->codec_id);
00151 if ( !codec || avcodec_open( enc, codec ) < 0 ) {
00152 return false;
00153 }
00154
00155 #if LIBAVFORMAT_BUILD <= 4623
00156 if (enc->frame_rate>1000 && enc->frame_rate_base==1)
00157 enc->frame_rate_base=1000;
00158 #endif
00159
00160 is_->vid_str_ = is_->fmt_cxt_->streams[ is_->vid_index_ ];
00161 is_->frame_ = avcodec_alloc_frame();
00162
00163 is_->num_frames_ = 0;
00164 while (advance())
00165 ++is_->num_frames_;
00166
00167
00168 #if LIBAVFORMAT_BUILD <= 4616
00169 av_seek_frame( is_->fmt_cxt_, is_->vid_index_, 0 );
00170 #else
00171 av_seek_frame( is_->fmt_cxt_, is_->vid_index_, 0, AVSEEK_FLAG_BACKWARD );
00172 #endif
00173
00174 return true;
00175 }
00176
00177
00178
00179 void
00180 vidl2_ffmpeg_istream::
00181 close()
00182 {
00183 if ( is_->frame_ ) {
00184 av_free( is_->frame_ );
00185 is_->frame_ = 0;
00186 }
00187
00188 is_->num_frames_ = 0;
00189 is_->contig_memory_ = 0;
00190 is_->vid_index_ = -1;
00191 if ( is_->vid_str_ ) {
00192 #if LIBAVFORMAT_BUILD <= 4628
00193 avcodec_close( &is_->vid_str_->codec );
00194 #else
00195 avcodec_close( is_->vid_str_->codec );
00196 #endif
00197 is_->vid_str_ = 0;
00198 }
00199 if ( is_->fmt_cxt_ ) {
00200 av_close_input_file( is_->fmt_cxt_ );
00201 is_->fmt_cxt_ = 0;
00202 }
00203 }
00204
00205
00206
00207 bool
00208 vidl2_ffmpeg_istream::
00209 is_open() const
00210 {
00211 return is_->frame_;
00212 }
00213
00214
00215
00216 bool
00217 vidl2_ffmpeg_istream::
00218 is_valid() const
00219 {
00220 return is_open() && is_->frame_->data[0] != 0;
00221 }
00222
00223
00224
00225 bool
00226 vidl2_ffmpeg_istream::
00227 is_seekable() const
00228 {
00229 return true;
00230 }
00231
00232
00233
00234
00235 int
00236 vidl2_ffmpeg_istream::num_frames() const
00237 {
00238 return is_->num_frames_;
00239 }
00240
00241
00242
00243 unsigned int
00244 vidl2_ffmpeg_istream::
00245 frame_number() const
00246 {
00247
00248 if ( !is_valid() ) {
00249 return static_cast<unsigned int>(-1);
00250 }
00251
00252 return ((is_->last_dts - is_->vid_str_->start_time)
00253 #if LIBAVFORMAT_BUILD <= 4623
00254 * is_->vid_str_->r_frame_rate / is_->vid_str_->r_frame_rate_base
00255 + AV_TIME_BASE/2) / AV_TIME_BASE
00256 #else
00257 * is_->vid_str_->r_frame_rate.num / is_->vid_str_->r_frame_rate.den
00258 * is_->vid_str_->time_base.num + is_->vid_str_->time_base.den/2)
00259 / is_->vid_str_->time_base.den
00260 #endif
00261 - is_->frame_number_offset_;
00262 }
00263
00264
00265
00266 unsigned int
00267 vidl2_ffmpeg_istream
00268 ::width() const
00269 {
00270
00271 if ( !is_open() ) {
00272 return 0;
00273 }
00274 #if LIBAVFORMAT_BUILD <= 4628
00275 AVCodecContext* enc = &is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00276 #else
00277 AVCodecContext* enc = is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00278 #endif
00279 return enc->width;
00280 }
00281
00282
00283
00284 unsigned int
00285 vidl2_ffmpeg_istream
00286 ::height() const
00287 {
00288
00289 if ( !is_open() ) {
00290 return 0;
00291 }
00292 #if LIBAVFORMAT_BUILD <= 4628
00293 AVCodecContext* enc = &is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00294 #else
00295 AVCodecContext* enc = is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00296 #endif
00297 return enc->height;
00298 }
00299
00300
00301
00302 vidl2_pixel_format
00303 vidl2_ffmpeg_istream
00304 ::format() const
00305 {
00306
00307 if ( !is_open() ) {
00308 return VIDL2_PIXEL_FORMAT_UNKNOWN;
00309 }
00310 #if LIBAVFORMAT_BUILD <= 4628
00311 AVCodecContext* enc = &is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00312 #else
00313 AVCodecContext* enc = is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00314 #endif
00315 vidl2_pixel_format fmt = vidl2_pixel_format_from_ffmpeg(enc->pix_fmt);
00316 if (fmt == VIDL2_PIXEL_FORMAT_UNKNOWN)
00317 return VIDL2_PIXEL_FORMAT_RGB_24;
00318 return fmt;
00319 }
00320
00321
00322
00323 double
00324 vidl2_ffmpeg_istream
00325 ::frame_rate() const
00326 {
00327
00328 if ( !is_open() ) {
00329 return 0.0;
00330 }
00331 #if LIBAVFORMAT_BUILD <= 4623
00332 return static_cast<double>(is_->vid_str_->r_frame_rate)
00333 / is_->vid_str_->r_frame_rate_base
00334 / AV_TIME_BASE;
00335 #else
00336 return static_cast<double>(is_->vid_str_->time_base.num)/is_->vid_str_->time_base.den
00337 * static_cast<double>(is_->vid_str_->r_frame_rate.num) / is_->vid_str_->r_frame_rate.den;
00338 #endif
00339 }
00340
00341
00342
00343 bool
00344 vidl2_ffmpeg_istream::
00345 advance()
00346 {
00347
00348 if ( !is_open() ) {
00349 return false;
00350 }
00351
00352 #if LIBAVFORMAT_BUILD <= 4628
00353 AVCodecContext* codec = &is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00354 #else
00355 AVCodecContext* codec = is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00356 #endif
00357
00358 AVPacket pkt;
00359 int got_picture = 0;
00360
00361 while ( got_picture == 0 )
00362 {
00363 if ( av_read_frame( is_->fmt_cxt_, &pkt ) < 0 ) {
00364 break;
00365 }
00366 is_->last_dts = pkt.dts;
00367
00368
00369 if (pkt.stream_index==is_->vid_index_)
00370 {
00371 if ( codec->codec_id == CODEC_ID_RAWVIDEO ) {
00372 avpicture_fill( (AVPicture*)is_->frame_, pkt.data,
00373 codec->pix_fmt,
00374 codec->width,
00375 codec->height );
00376 is_->frame_->pict_type = FF_I_TYPE;
00377 got_picture = 1;
00378 } else {
00379 avcodec_decode_video( codec,
00380 is_->frame_, &got_picture,
00381 pkt.data, pkt.size );
00382 }
00383 }
00384 av_free_packet( &pkt );
00385 }
00386
00387
00388
00389
00390 if ( !got_picture ) {
00391 avcodec_decode_video( codec,
00392 is_->frame_, &got_picture,
00393 NULL, 0 );
00394 #if LIBAVFORMAT_BUILD <= 4623
00395 is_->last_dts += AV_TIME_BASE * is_->vid_str_->r_frame_rate_base / is_->vid_str_->r_frame_rate;
00396 #else
00397 is_->last_dts += int64_t(is_->vid_str_->time_base.den) * is_->vid_str_->r_frame_rate.den
00398 / is_->vid_str_->time_base.num / is_->vid_str_->r_frame_rate.num;
00399 #endif
00400 }
00401
00402
00403
00404 if (is_->cur_frame_)
00405 is_->cur_frame_->invalidate();
00406 is_->cur_frame_ = 0;
00407
00408 if ( ! got_picture ) {
00409 is_->frame_->data[0] = NULL;
00410 }
00411
00412 return got_picture != 0;
00413 }
00414
00415
00416
00417 vidl2_frame_sptr
00418 vidl2_ffmpeg_istream::read_frame()
00419 {
00420 if (advance())
00421 return current_frame();
00422 return NULL;
00423 }
00424
00425
00426
00427 vidl2_frame_sptr
00428 vidl2_ffmpeg_istream::current_frame()
00429 {
00430
00431 if ( !is_valid() ) {
00432 return NULL;
00433 }
00434 #if LIBAVFORMAT_BUILD <= 4628
00435 AVCodecContext* enc = &is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00436 #else
00437 AVCodecContext* enc = is_->fmt_cxt_->streams[is_->vid_index_]->codec;
00438 #endif
00439
00440 if ( !is_->cur_frame_ && is_->frame_->data[0] != 0 )
00441 {
00442 int width = enc->width;
00443 int height = enc->height;
00444
00445
00446 if ( is_->deinterlace_ ) {
00447 avpicture_deinterlace( (AVPicture*)is_->frame_, (AVPicture*)is_->frame_,
00448 enc->pix_fmt, width, height );
00449 }
00450
00451
00452 vidl2_pixel_format fmt = vidl2_pixel_format_from_ffmpeg(enc->pix_fmt);
00453 if (fmt == VIDL2_PIXEL_FORMAT_UNKNOWN)
00454 {
00455 int size = width*height*3;
00456 if (!is_->contig_memory_)
00457 is_->contig_memory_ = new vil_memory_chunk(size, VIL_PIXEL_FORMAT_BYTE);
00458 else
00459 is_->contig_memory_->set_size(size, VIL_PIXEL_FORMAT_BYTE);
00460
00461 AVPicture rgb_frame;
00462 avpicture_fill(&rgb_frame, (uint8_t*)is_->contig_memory_->data(), PIX_FMT_RGB24, width, height);
00463 img_convert(&rgb_frame, PIX_FMT_RGB24, (AVPicture*)is_->frame_, enc->pix_fmt, width, height);
00464 is_->cur_frame_ = new vidl2_shared_frame(is_->contig_memory_->data(),width,height,
00465 VIDL2_PIXEL_FORMAT_RGB_24);
00466 }
00467 else
00468 {
00469
00470
00471
00472 AVPicture test_frame;
00473 avpicture_fill(&test_frame, is_->frame_->data[0], enc->pix_fmt, width, height);
00474 if (test_frame.data[1] == is_->frame_->data[1] &&
00475 test_frame.data[2] == is_->frame_->data[2] &&
00476 test_frame.linesize[0] == is_->frame_->linesize[0] &&
00477 test_frame.linesize[1] == is_->frame_->linesize[1] &&
00478 test_frame.linesize[2] == is_->frame_->linesize[2] )
00479 {
00480 is_->cur_frame_ = new vidl2_shared_frame(is_->frame_->data[0], width, height, fmt);
00481 }
00482
00483 else
00484 {
00485 if (!is_->contig_memory_){
00486 int size = avpicture_get_size( enc->pix_fmt, width, height );
00487 is_->contig_memory_ = new vil_memory_chunk(size, VIL_PIXEL_FORMAT_BYTE);
00488 }
00489 avpicture_fill(&test_frame, (uint8_t*)is_->contig_memory_->data(), enc->pix_fmt, width, height);
00490 img_copy(&test_frame, (AVPicture*)is_->frame_, enc->pix_fmt, width, height);
00491
00492 is_->cur_frame_ = new vidl2_shared_frame(is_->contig_memory_->data(),width,height,fmt);
00493 }
00494 }
00495 }
00496
00497
00498
00499
00500 if ( enc->codec_id == CODEC_ID_MPEG2VIDEO &&
00501 vcl_string("avi") == is_->fmt_cxt_->iformat->name ) {
00502 is_->frame_number_offset_ = 1;
00503 }
00504
00505 return is_->cur_frame_;
00506 }
00507
00508
00509
00510
00511 bool
00512 vidl2_ffmpeg_istream::
00513 seek_frame(unsigned int frame)
00514 {
00515
00516 if ( !is_open() ) {
00517 return false;
00518 }
00519
00520 #if LIBAVFORMAT_BUILD <= 4623
00521 int64_t frame_size = int64_t(AV_TIME_BASE) * is_->vid_str_->r_frame_rate_base
00522 / is_->vid_str_->r_frame_rate;
00523 int64_t req_timestamp = int64_t(AV_TIME_BASE) * frame * is_->vid_str_->r_frame_rate_base
00524 / is_->vid_str_->r_frame_rate + is_->vid_str_->start_time;
00525 #else
00526 int64_t frame_size = int64_t(is_->vid_str_->time_base.den) * is_->vid_str_->r_frame_rate.den
00527 / is_->vid_str_->time_base.num / is_->vid_str_->r_frame_rate.num;
00528 int64_t req_timestamp = int64_t(is_->vid_str_->time_base.den) * frame * is_->vid_str_->r_frame_rate.den
00529 / is_->vid_str_->time_base.num / is_->vid_str_->r_frame_rate.num + is_->vid_str_->start_time;
00530 #endif
00531
00532 if ( req_timestamp > frame_size/2 )
00533 req_timestamp -= frame_size/2;
00534 else
00535 req_timestamp = 0;
00536
00537
00538 #if LIBAVFORMAT_BUILD <= 4616
00539 int seek = av_seek_frame( is_->fmt_cxt_, is_->vid_index_, req_timestamp );
00540 #else
00541 int seek = av_seek_frame( is_->fmt_cxt_, is_->vid_index_, req_timestamp, AVSEEK_FLAG_BACKWARD );
00542 #endif
00543
00544 if ( seek < 0 )
00545 return false;
00546
00547 while ( true )
00548 {
00549 if ( ! advance() ) {
00550 return false;
00551 }
00552 if ( is_->last_dts >= req_timestamp ) {
00553 if ( is_->last_dts >= req_timestamp + frame_size ) {
00554 vcl_cerr << "Warning: seek went into the future!\n";
00555 return false;
00556 }
00557 return true;
00558 }
00559 }
00560 }
00561
00562 #endif // vidl2_ffmpeg_istream_v1_txx_