00001 #ifndef Impala_Core_Stream_RgbDataSrcLavc_old_h
00002 #define Impala_Core_Stream_RgbDataSrcLavc_old_h
00003
00004 #include <string>
00005 #include <iostream>
00006 #include <vector>
00007
00008
00009
00010
00011
00012 #include "Basis/CmdOptions.h"
00013 #include "Util/Database.h"
00014 #include "Util/IOBuffer.h"
00015
00016
00017 #include "Link/Lavc/Lavc.h"
00018
00019 #include "Link/DiskImage/DiskImageFuncs.h"
00020 #include "Core/Stream/RgbDataSrcInfo.h"
00021 #include "Core/Stream/LavcProtocolDataServer.h"
00022 #include "Core/Table/TableTem.h"
00023
00024 #ifdef USE_IFILE
00025 #include "Core/Stream/LavcProtocolLocalFile.h"
00026 #endif
00027
00028
00029 namespace Impala
00030 {
00031 namespace Core
00032 {
00033 namespace Stream
00034 {
00035
00036
00037 class LAVCException : public std::exception
00038 {
00039 String mWhat;
00040 int mType;
00041
00042 public:
00043
00044 LAVCException(const String what, int type) : mWhat(what), mType(type) {}
00045 ~LAVCException() throw() {}
00046 virtual const char* what() const throw() { return mWhat.c_str(); }
00047 };
00048
00049
00050 class RgbDataSrcLavc_old : public RgbDataSrcInfo
00051 {
00052
00053 typedef Array::Array2dVec3UInt8 Array2dVec3UInt8;
00054
00055 public:
00056
00057 RgbDataSrcLavc_old(int src, CString srcName, Util::Database* db,
00058 IndexMode mode = READIDX)
00059 : RgbDataSrcInfo(src, srcName, db,
00060 DetermineInfoName(srcName, mode, db), true)
00061 {
00062 CmdOptions& options = CmdOptions::GetInstance();
00063 mValid = false;
00064 mMode = mode;
00065 mBufferedFrameNr = -1;
00066 mFixCnt = 0;
00067 mLastFixNr = 0;
00068
00069 mLastFrame = mFrameCnt = LASTFRAME_UNKNOWN;
00070 mSrcName = StringReplaceAll(srcName, "\\", "/", false);
00071 mPacket = 0;
00072
00073 mFixIndexIfBroken = options.GetBool("fixIdx", true);
00074 if (!mFixIndexIfBroken)
00075 {
00076 ILOG_WARN("Index will NOT be fixed if broken!");
00077 }
00078 SetJumpMethod(options.GetString("jmp", "pos"));
00079
00080 Init();
00081 }
00082
00083 virtual
00084 ~RgbDataSrcLavc_old()
00085 {
00086
00087 delete [] mData;
00088
00089 if (mPacket != 0)
00090 delete mPacket;
00091
00092 av_free(mFrameRGB);
00093
00094
00095 av_free(mFrame);
00096
00097
00098 sws_freeContext(mSwsContext);
00099
00100
00101 avcodec_close(mCodecCtx);
00102
00103
00104 av_close_input_file(mFormatCtx);
00105 }
00106
00107 virtual char
00108 FrameType() const
00109 {
00110 switch (mFrame->pict_type)
00111 {
00112 case FF_I_TYPE : return 'I';
00113 case FF_P_TYPE : return 'P';
00114 case FF_B_TYPE : return 'B';
00115 }
00116 return '?';
00117 }
00118
00119 virtual bool
00120 CurIsIFrame() const
00121 {
00122 return mFrame->pict_type == FF_I_TYPE;
00123 }
00124
00125
00126
00127
00128 virtual bool
00129 Valid() const
00130 {
00131 return mValid;
00132 }
00133
00134 void
00135 JumpToKeyFrame(int key)
00136 {
00137 const int64_t targetPos = GetPos(key);
00138 ILOG_DEBUG("Jumping to Keyframe " << key << " @ "
00139 << targetPos << " (" << mJumpMethod << ") " );
00140
00141
00142 Jump(targetPos, mJumpFlags, 2, 2);
00143 mCurrentFrameNr = mBufferedFrameNr = key;
00144 CheckMD5Hash(key);
00145 }
00146
00147 void
00148 Jump(int64_t newPos, int flag, int flush=0, int sync=0)
00149 {
00150 ILOG_DEBUG("Attempting jump to " << newPos << " (method: " <<
00151 mJumpMethod << ")");
00152
00153 if (mCodecCtx->codec->flush == NULL)
00154 flush = 0;
00155 else if (flush & 1)
00156 mCodecCtx->codec->flush(mCodecCtx);
00157
00158
00159 int res = av_seek_frame(mFormatCtx, mVideoStreamIndex, newPos, flag);
00160
00161
00162 if (res >= 0)
00163 {
00164 if (flush & 2)
00165 mCodecCtx->codec->flush(mCodecCtx);
00166 }
00167 else
00168 {
00169 ILOG_ERROR("av_seek_frame returned negative value: " << res <<
00170 " (" << newPos << " " << flag << " " << flush << " " << sync << ")");
00171 return;
00172 }
00173
00174 if (sync == 1)
00175 FindNextDecodedFrame(false);
00176 else
00177 if (sync == 2)
00178 FindNextDecodedFrame(true);
00179 }
00180
00181 bool
00182 FindNextDecodedFrame(const bool lookForKeyFrame)
00183 {
00184
00185
00186
00187 bool isValidFrame;
00188 bool isKeyFrame;
00189 do
00190 {
00191 const bool gotFrame = (DecodeNextFrame(isValidFrame, isKeyFrame) == 0);
00192 if (!gotFrame)
00193 return false;
00194 if (!isValidFrame)
00195 {
00196 ILOG_DEBUG("Skipping invalid frame");
00197 continue;
00198 }
00199 if (lookForKeyFrame && !isKeyFrame)
00200 {
00201 ILOG_DEBUG("Skipping non-keyframe");
00202 continue;
00203 }
00204 break;
00205 } while (true);
00206
00207 ConvertFrameToRgb();
00208 return true;
00209 }
00210
00211 private:
00212
00213 void
00214 SetJumpMethod(String jmp)
00215 {
00216 mJumpMethod = jmp;
00217 ILOG_DEBUG("Jump Method is " << mJumpMethod);
00218 if (mJumpMethod == "pos")
00219 mJumpFlags = AVSEEK_FLAG_ANY | AVSEEK_FLAG_BYTE;
00220 else
00221
00222 mJumpFlags = AVSEEK_FLAG_ANY;
00223 }
00224
00225 void
00226 Init()
00227 {
00228 try
00229 {
00230 InitFFMPEG();
00231 InitFormatCtx();
00232 InitStreams();
00233 InitCodecCtx();
00234 InitFrames();
00235
00236 if (!PrepareForReading())
00237 {
00238 mValid = false;
00239 return;
00240 }
00241
00242 if (mMode != NOCHECK)
00243 {
00244 if (mMode == READIDX && !ReadInfo())
00245 {
00246 throw LAVCException("Could not read info file for: " +
00247 mSrcName, 0);
00248 }
00249
00250 else if (mMode == WITHIDX)
00251 {
00252 if (!ReadInfo(true))
00253 PopulateIndex();
00254 }
00255
00256 else if (mMode == ADHOCIDX)
00257 {
00258
00259 PopulateIndex();
00260 }
00261
00262 else if (mMode == WRITEIDX)
00263 {
00264
00265 PopulateIndex();
00266 WriteInfo();
00267 }
00268
00269 Reset();
00270 }
00271 }
00272 catch (LAVCException& e)
00273 {
00274 mValid = false;
00275 ILOG_ERROR("Initialization failed: " << e.what());
00276 return;
00277 }
00278
00279 mValid = true;
00280 ILOG_DEBUG("Initialization succeeded");
00281 }
00282
00283 bool
00284 InitFFMPEG()
00285 {
00286 ILOG_INFO("libavcodec version : " <<
00287 (int)(LIBAVCODEC_VERSION_INT>>16) << "." <<
00288 (int)((LIBAVCODEC_VERSION_INT>>8)&0xFF) << "." <<
00289 (int)(LIBAVCODEC_VERSION_INT&0xFF));
00290
00291 ILOG_INFO("libavformat version : " <<
00292 (int)(LIBAVFORMAT_VERSION_INT>>16) << "." <<
00293 (int)((LIBAVFORMAT_VERSION_INT>>8)&0xFF) << "." <<
00294 (int)(LIBAVFORMAT_VERSION_INT&0xFF));
00295
00296 ILOG_INFO("libavutil version : " <<
00297 (int)(LIBAVUTIL_VERSION_INT>>16) << "." <<
00298 (int)((LIBAVUTIL_VERSION_INT>>8)&0xFF) << "." <<
00299 (int)(LIBAVUTIL_VERSION_INT&0xFF));
00300
00301
00302
00303
00304
00305
00306 av_log_set_level(AV_LOG_QUIET);
00307
00308
00309
00310 av_register_all();
00311 avcodec_register_all();
00312
00313 register_protocol(&LavcProtocolDataServer_protocol);
00314
00315 if (Link::DiskImage::DiskImageUsed())
00316 {
00317 ILOG_DEBUG("Registering disk image protocol..");
00318 Link::DiskImage::RegisterProtocol();
00319 }
00320
00321 #ifdef USE_IFILE
00322 ILOG_DEBUG("Registering Impala file protocol..");
00323 register_protocol(&LavcProtocolLocalFile_protocol);
00324 #endif
00325 return true;
00326 }
00327
00328
00329 bool
00330 InitFormatCtx()
00331 {
00332
00333 CmdOptions& options = CmdOptions::GetInstance();
00334 String dataServer = options.GetString("dataServer");
00335 String srcAddress = mSrcName;
00336 if (!dataServer.empty())
00337 srcAddress = "dataserver:" + mSrcName;
00338
00339 int result = av_open_input_file(&mFormatCtx,
00340 srcAddress.c_str(), NULL, 0, NULL);
00341
00342 if (result != 0)
00343 {
00344 ILOG_ERROR("Return value from av_open_input_file(): " << result);
00345 throw (LAVCException("Unable to open: " + mSrcName, 0));
00346 return false;
00347 }
00348
00349 #if LIBAVFORMAT_VERSION_INT >= ((51<<16)+(14<<8)+0) // from version 51.14.0 on
00350 if (mFormatCtx->iformat->flags & AVFMT_GENERIC_INDEX)
00351 {
00352
00353
00354 mFormatCtx->iformat->flags -= AVFMT_GENERIC_INDEX;
00355 ILOG_DEBUG("Flag cleared: mFormatCtx->iformat->flags -= " <<
00356 "AVFMT_GENERIC_INDEX");
00357
00358
00359 result = av_open_input_file(&mFormatCtx,
00360 srcAddress.c_str(), NULL, 0, NULL);
00361 }
00362 #endif
00363
00364
00365 if (av_find_stream_info(mFormatCtx) < 0)
00366 throw LAVCException("Could not find stream info in: " + mSrcName, 0);
00367
00368
00369 dump_format(mFormatCtx, 0, mSrcName.c_str(), false);
00370
00371 mFormatCtx->flags |= AVFMT_FLAG_GENPTS;
00372
00373 mBitRate = mFormatCtx->bit_rate;
00374 mFormatName = mFormatCtx->iformat->name;
00375 mFormatLName = mFormatCtx->iformat->long_name;
00376 ILOG_INFO("Format name is: " << mFormatLName << " (" << mFormatName << ")");
00377
00378 if ((mFormatName == "avi") ||
00379 (mFormatName == "mov,mp4,m4a,3gp,3g2,mj2"))
00380 {
00381 SetJumpMethod("pts");
00382 }
00383 else
00384 {
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 }
00395
00396 return true;
00397 }
00398
00399
00400 bool
00401 InitStreams()
00402 {
00403 mStreamCount = mFormatCtx->nb_streams;
00404 mVideoStreamIndex = -1;
00405 mVideoStream = 0;
00406
00407
00408 for (int i = 0; i < mStreamCount; i++)
00409 {
00410 if (mFormatCtx->streams[i]->codec->codec_type
00411 == CODEC_TYPE_VIDEO)
00412 {
00413 if (mVideoStreamIndex >= 0)
00414 throw (LAVCException("Multiple video streams found in: "
00415 + mSrcName, 0));
00416
00417 mVideoStreamIndex = i;
00418 mVideoStream = mFormatCtx->streams[i];
00419 }
00420 }
00421 if (mVideoStream == 0)
00422 throw LAVCException("Could not find video stream in: "
00423 + mSrcName, 0);
00424
00425
00426 mVideoDuration = mVideoStream->duration;
00427 const AVRational videoTimeBase =
00428 mVideoStream->time_base;
00429 mTimeBaseNum = videoTimeBase.num;
00430 mTimeBaseDen = videoTimeBase.den;
00431 mDuration = ceil(
00432 double(mVideoDuration) * mTimeBaseNum / mTimeBaseDen
00433 );
00434 mDurationSec = mDuration;
00435 mDurationHour = mDurationSec / 3600;
00436 mDurationSec %= 3600;
00437 mDurationMin = mDurationSec / 60;
00438 mDurationSec %= 60;
00439
00440
00441 mFrameRateNum = mVideoStream->r_frame_rate.num;
00442 mFrameRateDen = mVideoStream->r_frame_rate.den;
00443 const double fractionsPerSec = double(mTimeBaseDen) / mTimeBaseNum;
00444 const double secondsPerFrame = double(mFrameRateDen) / mFrameRateNum;
00445 const double fractionsPerFrame = fractionsPerSec * secondsPerFrame;
00446 const double frameCount = mVideoDuration / fractionsPerFrame;
00447 mFrameCountCalculated = ceil(frameCount);
00448 ILOG_DEBUG("Frame count estimate based on video duration: " <<
00449 mFrameCountCalculated);
00450
00451 return true;
00452 }
00453
00454
00455 bool InitCodecCtx()
00456 {
00457
00458 mCodecCtx = mVideoStream->codec;
00459
00460
00461 mCodec = avcodec_find_decoder(mCodecCtx->codec_id);
00462 if (mCodec == NULL)
00463 throw LAVCException("Codec not found for: " + mSrcName, 0);
00464
00465
00466 if (avcodec_open(mCodecCtx, mCodec) < 0)
00467 throw LAVCException("Could not open codec (id=" +
00468 MakeString(mCodecCtx->codec_id) + ", name=" +
00469 mCodecName + ") for: " + mSrcName, 0);
00470
00471 mFrameWidth = mCodecCtx->width;
00472 mFrameHeight = mCodecCtx->height;
00473
00474 mAspectRatioNum = mCodecCtx->sample_aspect_ratio.num;
00475 mAspectRatioDen = mCodecCtx->sample_aspect_ratio.den;
00476
00477 mGopSize = mCodecCtx->gop_size;
00478
00479
00480 mSwsContext = sws_getContext(
00481 mFrameWidth, mFrameHeight, mCodecCtx->pix_fmt,
00482 mFrameWidth, mFrameHeight, PIX_FMT_RGB24,
00483 SWS_BICUBIC, NULL, NULL, NULL);
00484 if (mSwsContext == NULL)
00485 throw LAVCException(
00486 "Failed to initialize image conversion context for: " +
00487 mSrcName, 0);
00488
00489
00490 char buf[5];
00491 #ifdef WIN32
00492 _snprintf(
00493 #else
00494 snprintf(
00495 #endif
00496 buf, sizeof(buf), "%c%c%c%c",
00497 mCodecCtx->codec_tag & 0xff,
00498 (mCodecCtx->codec_tag >> 8) & 0xff,
00499 (mCodecCtx->codec_tag >> 16) & 0xff,
00500 (mCodecCtx->codec_tag >> 24) & 0xff);
00501 mCodecTag = buf;
00502
00503
00504 mCodecName = mCodec->name;
00505
00506 ILOG_INFO("Opened codec (id=" << mCodecCtx->codec_id <<
00507 ", name=" << mCodecName << ") for: " << mSrcName);
00508
00509 if (mCodecName == "mpeg1video")
00510 {
00511
00512 SetJumpMethod("pos");
00513 }
00514
00515 return true;
00516 }
00517
00518 bool InitFrames()
00519 {
00520 mPacket = new AVPacket;
00521
00522
00523 mFrame = avcodec_alloc_frame();
00524
00525
00526 mFrameRGB = avcodec_alloc_frame();
00527
00528 if ((mFrameRGB == NULL) || (mFrame == NULL))
00529 throw LAVCException("Could not allocate frame memory for: "
00530 + mSrcName, 0);
00531
00532
00533 const int numBytes = avpicture_get_size(
00534 PIX_FMT_RGB24, mFrameWidth, mFrameHeight);
00535 mData = new UInt8[numBytes];
00536
00537
00538 int result = avpicture_fill( (AVPicture*) mFrameRGB,
00539 mData, PIX_FMT_RGB24, mFrameWidth, mFrameHeight);
00540
00541 return true;
00542 }
00543
00544 void
00545 Reset()
00546 {
00547 ILOG_DEBUG("Rewinding stream");
00548
00549 Int64 startPos = GetPos(mBlankFrames);
00550 if (startPos < 0)
00551 {
00552 ILOG_WARN("No position found for frame: " << mBlankFrames <<
00553 ". Trying 0 as position (which is probably fine " <<
00554 "for getting to the head of the file)");
00555 startPos = 0;
00556 }
00557
00558 const int flush = 2;
00559 const int sync = 1;
00560 Jump(startPos, mJumpFlags, flush, sync);
00561
00562 mBufferedFrameNr = mBlankFrames;
00563 mCurrentFrameNr = 0;
00564 }
00565
00566 bool
00567 PrepareForReading()
00568 {
00569 ILOG_DEBUG("Preparing for reading video stream...");
00570
00571 #ifdef FFMPEG_52
00572 ILOG_DEBUG("[PrepareForReading] stream's curdts=" << mVideoStream->cur_dts << " mPacket->dts=" << mPacket->dts << " mPacket->pts=" << mPacket->pts << " mPacket->size=" << mPacket->size << "; pb->pos=" << mFormatCtx->pb->pos);
00573 int result = av_seek_frame(mFormatCtx, mVideoStreamIndex, 0, AVSEEK_FLAG_BYTE | AVSEEK_FLAG_ANY);
00574 ILOG_DEBUG("[PrepareForReading] stream's curdts=" << mVideoStream->cur_dts << " mPacket->dts=" << mPacket->dts << " mPacket->pts=" << mPacket->pts << " mPacket->size=" << mPacket->size << "; pb->pos=" << mFormatCtx->pb->pos << "; result = " << result);
00575
00576
00577 #else
00578 ILOG_DEBUG("[PrepareForReading] stream's curdts=" << mVideoStream->cur_dts << " mPacket->dts=" << mPacket->dts << " mPacket->pts=" << mPacket->pts << " mPacket->size=" << mPacket->size << "; pb.pos=" << mFormatCtx->pb.pos);
00579 const int flags = AVSEEK_FLAG_BYTE | AVSEEK_FLAG_ANY;
00580 int result = av_seek_frame(mFormatCtx, mVideoStreamIndex, 0, flags);
00581 ILOG_DEBUG("[PrepareForReading] stream's curdts=" << mVideoStream->cur_dts << " mPacket->dts=" << mPacket->dts << " mPacket->pts=" << mPacket->pts << " mPacket->size=" << mPacket->size << "; pb.pos=" << mFormatCtx->pb.pos << "; result = " << result);
00582
00583
00584 #endif
00585
00586 if (result < 0)
00587 {
00588 ILOG_ERROR("[PrepareForReading] av_seek_frame returned " << result);
00589 return false;
00590 }
00591
00592 if (mCodecCtx->codec->flush != NULL)
00593 mCodecCtx->codec->flush(mCodecCtx);
00594
00595 mBlankFrames = 0;
00596 int currentFrameNr = -1;
00597 const bool startAtKeyFrame = false;
00598 bool isValidFrame = false;
00599 bool isKeyFrame = false;
00600 while (!isValidFrame || (startAtKeyFrame && !isKeyFrame))
00601 {
00602 const bool gotFrame = (DecodeNextFrame(isValidFrame, isKeyFrame) == 0);
00603 if (!gotFrame)
00604 return false;
00605 currentFrameNr++;
00606 if (!isValidFrame)
00607 {
00608 MarkBadFrame(currentFrameNr);
00609 mBlankFrames++;
00610 }
00611 }
00612
00613 ConvertFrameToRgb();
00614
00615 mCurrentFrameNr = mBufferedFrameNr = currentFrameNr;
00616 ILOG_DEBUG("Prepared for reading video stream; detected " << mBlankFrames << " leading invalid frame(s)");
00617 return true;
00618 }
00619
00620 bool PopulateIndex()
00621 {
00622 ILOG_DEBUG("Creating the video index!");
00623
00624 const String formatName(mFormatCtx->iformat->name);
00625 if (("mpeg" == formatName) || ("mpg" == formatName)
00626 || mCodecName == "mpeg1video")
00627 {
00628 PopulateMpegIndex();
00629 }
00630 else if (("avi" == formatName) || ("mov,mp4,m4a,3gp,3g2,mj2" == formatName))
00631 {
00632 PopulateAviIndex();
00633 }
00634 else
00635 {
00636 ILOG_WARN("Cannot an create external index for format: " << formatName);
00637 mLastFrame = mFrameCountCalculated - 1;
00638 return false;
00639
00640
00641 }
00642
00643 ILOG_DEBUG("Frame count established from populating the index: " << mLastFrame + 1);
00644 return true;
00645 }
00646
00647
00648 void
00649 PopulateMpegIndex()
00650 {
00651 AVIndexEntry *idx = mVideoStream->index_entries;
00652 if (idx && !(mFormatCtx->flags & AVFMT_FLAG_IGNIDX))
00653 {
00654 const int nrOfIndexEntries =
00655 mVideoStream->nb_index_entries;
00656 int countValidSize = 0;
00657 int countKeyFrame = 0;
00658 int indexPos = 0;
00659 while (indexPos < nrOfIndexEntries)
00660 {
00661 if (idx[indexPos].size > 0)
00662 {
00663 countValidSize++;
00664 if (idx[indexPos].flags & AVINDEX_KEYFRAME)
00665 countKeyFrame++;
00666 }
00667 indexPos++;
00668 }
00669 ILOG_INFO("Stream contains an index which will be ignored; nr of entries is " <<
00670 nrOfIndexEntries <<
00671 ", of which " << countValidSize << " have size>0" <<
00672 ", of which " << countKeyFrame << " are marked as KEYFRAME");
00673 }
00674
00675
00676 for (int i = 0; i < mBlankFrames; i++)
00677 {
00678 ILOG_DEBUG("AddIndex(" << i << ", -1, -1, " << DUMMY_FRAME_HASH << ")");
00679 AddIndex(i, -1, -1, DUMMY_FRAME_HASH);
00680 }
00681
00682 PopulateMpegIndexBase();
00683
00684 mIndexExists = true;
00685 }
00686
00687 void
00688 PopulateMpegIndexBase()
00689 {
00690 AVIndexEntry *idx = mVideoStream->index_entries;
00691
00692 typedef Column::FixedStringColumn::ColElemType FixedString;
00693
00694
00695 typedef Table::TableTem< Column::ColumnTem<Int32>,
00696 Column::ColumnTem<Int32>,
00697 Column::FixedStringColumn > FrameTable;
00698
00699
00700 typedef Table::TableTem< Column::ColumnTem<Int32>,
00701 Column::ColumnTem<Real64>,
00702 Column::ColumnTem<Int32>,
00703 Column::FixedStringColumn > KeyFrameTable;
00704
00705
00706 typedef Table::TableTem< Column::ColumnTem<Real64> > SeekPositionTable;
00707
00708 static const int HASH_SIZE = 32;
00709
00710 FrameTable frameTable(Column::ColumnTem<Int32>(1000),
00711 Column::ColumnTem<Int32>(1000),
00712 Column::FixedStringColumn(HASH_SIZE, 1000));
00713
00714 KeyFrameTable keyFrameTable(Column::ColumnTem<Int32>(1000),
00715 Column::ColumnTem<Real64>(1000),
00716 Column::ColumnTem<Int32>(1000),
00717 Column::FixedStringColumn(HASH_SIZE, 1000));
00718
00719 SeekPositionTable seekPosTable(Column::ColumnTem<Real64>(1000));
00720
00721
00722
00723
00724
00725 int64_t startPosOfBuffer = 0;
00726 int64_t lastEndPosOfBuffer = 0;
00727
00728 String prevHash = "";
00729 int lastKeyFrameNr = -1;
00730 while (mCurrentFrameNr < mLastFrame)
00731
00732 {
00733 #ifdef FFMPEG_52
00734 const int64_t& actualEndPosOfBuffer = mFormatCtx->pb->pos;
00735 #else
00736 const int64_t& actualEndPosOfBuffer = mFormatCtx->pb.pos;
00737 #endif
00738 if (actualEndPosOfBuffer < lastEndPosOfBuffer)
00739 {
00740 ILOG_ERROR("Unexpected buffer position change (from " <<
00741 lastEndPosOfBuffer << " to " << actualEndPosOfBuffer << ")");
00742 return;
00743 }
00744
00745 const bool bufferAdvanced = (actualEndPosOfBuffer > lastEndPosOfBuffer);
00746 if (bufferAdvanced)
00747 {
00748 startPosOfBuffer = lastEndPosOfBuffer;
00749 lastEndPosOfBuffer = actualEndPosOfBuffer;
00750
00751 seekPosTable.Add(startPosOfBuffer);
00752 }
00753
00754
00755 if (mCurrentFrameNr > mBufferedFrameNr)
00756 {
00757 MarkBadFrame(mCurrentFrameNr);
00758 ILOG_DEBUG("Found a bad frame where mCurrentFrameNr = " << mCurrentFrameNr << " (and mBufferedFrameNr = " << mBufferedFrameNr << ")");
00759 }
00760 else
00761 {
00762 const String hash = CalcHash_protected();
00763 const FixedString hashAsFixedStr(HASH_SIZE, (char*) hash.c_str(), false);
00764
00765 if (mFrame->pict_type == FF_I_TYPE)
00766 {
00767 int recurrence = 1;
00768 if (hash == prevHash)
00769 {
00770 recurrence = 1 + keyFrameTable.Get3(keyFrameTable.Size() - 1);
00771
00772 }
00773 else
00774 {
00775 prevHash = hash;
00776 }
00777 const Int64 position = 0;
00778 keyFrameTable.Add(mCurrentFrameNr, position, recurrence, hashAsFixedStr);
00779 lastKeyFrameNr = mCurrentFrameNr;
00780 }
00781 else if (mFrame->pict_type != FF_P_TYPE &&
00782 mFrame->pict_type != FF_B_TYPE)
00783 {
00784 ILOG_ERROR("Unexpected picture type: " << mFrame->pict_type);
00785 return;
00786 }
00787
00788 frameTable.Add(mCurrentFrameNr, lastKeyFrameNr, hashAsFixedStr);
00789 ILOG_DEBUG("Added frame to frame table: " << mCurrentFrameNr << " : " << lastKeyFrameNr << " : " << hashAsFixedStr);
00790 }
00791
00792 NextFrame();
00793 }
00794
00795
00796 keyFrameTable.Dump(0, 25);
00797
00798
00799
00800
00801 int keyFrameTableIndexMin = 0;
00802 int64_t topSafeSeekPos = 0;
00803
00804 for (int seekPosTableIndex = 0; seekPosTableIndex < seekPosTable.Size(); seekPosTableIndex++)
00805 {
00806 const int64_t seekPos = seekPosTable.Get1(seekPosTableIndex);
00807
00808
00809 const int posZero = 0;
00810 const int flush = 2;
00811 const int no_sync = 1;
00812 const int sync = 2;
00813 Jump(posZero, mJumpFlags, flush, (seekPos == posZero) ? sync : no_sync);
00814 ILOG_DEBUG("Jumped to head of file for seekPosTableIndex " << seekPosTableIndex);
00815 if (seekPos != posZero)
00816 Jump(seekPos, mJumpFlags, flush, sync);
00817 ILOG_DEBUG("Jumped to seekPos " << seekPos);
00818
00819 Array2dVec3UInt8* arr =
00820 new Array2dVec3UInt8(FrameWidth(), FrameHeight(), 0, 0,
00821 mData, true, false);
00822 const String hashOfKeyFrameJumpedTo = Array::MD5Hash(arr);
00823 delete arr;
00824
00825 int k = keyFrameTableIndexMin;
00826
00827 for (; k < keyFrameTable.Size(); k++)
00828 {
00829 const String hash(keyFrameTable.Get4(k).GetData(), HASH_SIZE);
00830 if (hash == hashOfKeyFrameJumpedTo)
00831 {
00832 ILOG_DEBUG("Key frame " << k << " matches hash of first key frame found");
00833 break;
00834 }
00835
00836 keyFrameTable.Set2(k, topSafeSeekPos);
00837 keyFrameTableIndexMin++;
00838 }
00839 if (k >= keyFrameTable.Size())
00840 {
00841 ILOG_DEBUG("At end of key frame table; no matching key frame for seek pos jumped to");
00842 break;
00843 }
00844
00845
00846
00847
00848
00849 int recurrence = 0;
00850 k = keyFrameTableIndexMin + 1;
00851 for (; k < keyFrameTable.Size(); k++)
00852 {
00853 const String hash(keyFrameTable.Get4(k).GetData(), HASH_SIZE);
00854 if (hash != hashOfKeyFrameJumpedTo)
00855 break;
00856
00857 recurrence++;
00858 }
00859
00860
00861
00862
00863 mCurrentFrameNr = mBlankFrames;
00864 int distanceToDifferentHash = 1;
00865 bool foundNextKeyFrame = false;
00866 while (true)
00867 {
00868 foundNextKeyFrame = FindNextDecodedFrame(true);
00869 if (!foundNextKeyFrame)
00870 break;
00871
00872 const String hash = CalcHash_protected();
00873 if (hash != hashOfKeyFrameJumpedTo)
00874 break;
00875
00876
00877
00878
00879 distanceToDifferentHash++;
00880 }
00881
00882
00883
00884
00885
00886 int keyFramesWithOldSafePos = 0;
00887 if (distanceToDifferentHash <= recurrence)
00888 {
00889 keyFramesWithOldSafePos = (1 + recurrence) - distanceToDifferentHash;
00890 for (int kk = 0; kk < keyFramesWithOldSafePos; kk++)
00891 {
00892 keyFrameTable.Set2(keyFrameTableIndexMin, topSafeSeekPos);
00893 keyFrameTableIndexMin++;
00894 }
00895 }
00896
00897 keyFrameTable.Set2(keyFrameTableIndexMin, seekPos);
00898 topSafeSeekPos = seekPos;
00899
00900
00901 if (!foundNextKeyFrame)
00902 {
00903 break;
00904 }
00905 }
00906
00907
00908 int64_t lastProperSeekPos = -1;
00909 int frameIndex = 0;
00910 int keyFrameIndex = 0;
00911 int nextProperKeyFrameIndex = 0;
00912 while (keyFrameIndex < keyFrameTable.Size())
00913 {
00914 int seekFrameNr = keyFrameTable.Get1(keyFrameIndex);
00915 lastProperSeekPos = keyFrameTable.Get2(keyFrameIndex);
00916 nextProperKeyFrameIndex = keyFrameIndex;
00917 while (nextProperKeyFrameIndex < keyFrameTable.Size() && keyFrameTable.Get2(nextProperKeyFrameIndex) == lastProperSeekPos)
00918 nextProperKeyFrameIndex++;
00919
00920 int nextProperSeekFrame = 1000000;
00921 if (nextProperKeyFrameIndex < keyFrameTable.Size())
00922 {
00923 nextProperSeekFrame = keyFrameTable.Get1(nextProperKeyFrameIndex);
00924 }
00925
00926 while (frameIndex < frameTable.Size() && frameTable.Get2(frameIndex) < nextProperSeekFrame)
00927 {
00928 frameTable.Set2(frameIndex, seekFrameNr);
00929 frameIndex++;
00930 }
00931
00932 keyFrameIndex = nextProperKeyFrameIndex;
00933 }
00934
00935
00936
00937 keyFrameIndex = 0;
00938 for (int i = 0; i < frameTable.Size(); i++)
00939 {
00940 const int frameNr = frameTable.Get1(i);
00941 const int keyFrameNr = frameTable.Get2(i);
00942 const String hash(frameTable.Get3(i).GetData(), HASH_SIZE);
00943 while (keyFrameTable.Get1(keyFrameIndex) < keyFrameNr)
00944 keyFrameIndex++;
00945 const int64_t seekPos = keyFrameTable.Get2(keyFrameIndex);
00946 ILOG_DEBUG("AddIndex(" << frameNr << ", " << keyFrameNr << ", " << seekPos << ", " << hash << ")");
00947 AddIndex(frameNr, keyFrameNr, seekPos, hash);
00948 }
00949 }
00950
00951 void
00952 PopulateAviIndex()
00953 {
00954 ILOG_INFO("Timestamp Based Indexing for AVI started!");
00955
00956 if (mBlankFrames > 0)
00957 {
00958
00959 ILOG_ERROR("Did not expect blank frames to have been registered here");
00960 return;
00961 }
00962
00963 const AVIndexEntry * const idx = mVideoStream->index_entries;
00964 if (!idx)
00965 {
00966 ILOG_ERROR("Stream contains no index");
00967 mFrameCnt = 0;
00968 mLastFrame = -1;
00969 return;
00970 }
00971
00972 mFrameCnt = mVideoStream->nb_index_entries;
00973 mLastFrame = mFrameCnt - 1;
00974 ILOG_INFO("FrameCount from Index: " << mFrameCnt);
00975
00976 for (int e = 0; e <= 20; e++)
00977 ILOG_DEBUG("index entry " << e << ": size=" << idx[e].size << ", flags=" << idx[e].flags << ", timestamp=" << idx[e].timestamp << ", pos=" << idx[e].pos << ", min_distance=" << idx[e].min_distance << ")");
00978
00979
00980
00981
00982 int indexPos = 0;
00983 while (indexPos < mFrameCnt &&
00984 (idx[indexPos].size <= 0 ||
00985 idx[indexPos].flags != AVINDEX_KEYFRAME))
00986 {
00987 MarkBadFrame(indexPos);
00988 AddIndex(indexPos, -1, -1, DUMMY_FRAME_HASH);
00989 ILOG_DEBUG(indexPos << " -1 -1 " << DUMMY_FRAME_HASH << " (idx[indexPos].size=" << idx[indexPos].size << ", idx[indexPos].flags=" << idx[indexPos].flags << ", idx[indexPos].timestamp=" << idx[indexPos].timestamp << ")");
00990 indexPos++;
00991 }
00992
00993 if (indexPos > 0)
00994 {
00995 mBlankFrames = mBufferedFrameNr = mCurrentFrameNr = indexPos;
00996 ILOG_INFO("Stream starts with " << mBlankFrames << " bad frame(s)");
00997 }
00998
00999
01000
01001 const int posZero = 0;
01002 const int flush = 2;
01003 const int no_sync = 1;
01004 const int sync = 2;
01005 Jump(posZero, mJumpFlags, flush, no_sync);
01006 Jump(mBlankFrames, mJumpFlags, flush, sync);
01007 ILOG_DEBUG("Jumped to head of file");
01008
01009 int lastKeyPos = -1;
01010 int64_t keyPts = -1;
01011 for (; indexPos < mFrameCnt; indexPos++)
01012
01013 {
01014 if (idx[indexPos].size <= 0)
01015 {
01016 ILOG_INFO("Bad frame at index position: " << indexPos << " (idx[indexPos].size=" << idx[indexPos].size << ", idx[indexPos].flags=" << idx[indexPos].flags << ", idx[indexPos].timestamp=" << idx[indexPos].timestamp << ")");
01017 AddIndex(indexPos, -1, -1, DUMMY_FRAME_HASH);
01018 ILOG_DEBUG(indexPos << " -1 -1 " << DUMMY_FRAME_HASH);
01019 MarkBadFrame(indexPos);
01020 mCurrentFrameNr++;
01021 mBufferedFrameNr++;
01022 continue;
01023 }
01024
01025 if (indexPos > mBlankFrames)
01026 NextFrame();
01027
01028 String frameHash;
01029 if (FrameValid(mCurrentFrameNr))
01030 {
01031 if (idx[indexPos].flags == AVINDEX_KEYFRAME )
01032 {
01033 lastKeyPos = indexPos;
01034 keyPts = idx[lastKeyPos].timestamp;
01035 }
01036 frameHash = CalcHash_protected();
01037 }
01038 else
01039 frameHash = DUMMY_FRAME_HASH;
01040
01041 AddIndex(indexPos, lastKeyPos, keyPts, frameHash);
01042 ILOG_DEBUG(indexPos << " " << lastKeyPos
01043 << " " << keyPts << " " << frameHash);
01044 }
01045
01046 mIndexExists = true;
01047 }
01048
01049
01050
01051
01052
01053
01054
01055 void
01056 PopulateTrivialIndex()
01057 {
01058 const int firstValidFrameNr = FrameNr();
01059 while (FrameNr() < mLastFrame)
01060
01061 {
01062 const int frameNr = FrameNr();
01063
01064 if (frameNr > mBufferedFrameNr)
01065 {
01066 MarkBadFrame(frameNr);
01067 ILOG_DEBUG("Found a bad frame where mCurrentFrameNr = " <<
01068 frameNr << " (and mBufferedFrameNr = " <<
01069 mBufferedFrameNr << ")");
01070
01071
01072 }
01073 else
01074 {
01075
01076
01077
01078
01079
01080
01081
01082 }
01083
01084 NextFrame();
01085 }
01086
01087
01088 }
01089
01090 bool
01091 ReadFrameData()
01092 {
01093 if (mTargetFrameNr == mCurrentFrameNr)
01094 return true;
01095
01096 if (!FrameValid(mTargetFrameNr) ||
01097 mTargetFrameNr == mBufferedFrameNr)
01098 {
01099 mCurrentFrameNr = mTargetFrameNr;
01100 return true;
01101 }
01102
01103
01104 try
01105 {
01106 if (mTargetFrameNr < mBufferedFrameNr)
01107 {
01108
01109
01110
01111 Reset();
01112 }
01113
01114 if ((mIndexExists) && (mTargetFrameNr - mBufferedFrameNr > mGopSize))
01115 {
01116 int key = GetSeekableFrame(mTargetFrameNr);
01117 ILOG_DEBUG("Jumping to Keyframe " << key << " for " << mTargetFrameNr);
01118 JumpToKeyFrame(key);
01119 }
01120
01121
01122 const int target = mTargetFrameNr;
01123 while (mCurrentFrameNr < target)
01124 {
01125
01126 const int nextFrameNr = mCurrentFrameNr + 1;
01127 bool isValidFrame = FrameValid(nextFrameNr);
01128 if (nextFrameNr != mBufferedFrameNr && isValidFrame)
01129 {
01130 bool isKeyFrame;
01131 const bool gotFrame = (DecodeNextFrame(isValidFrame, isKeyFrame) == 0);
01132 if (gotFrame)
01133 {
01134 if (!isValidFrame)
01135 {
01136 ILOG_DEBUG("[DoReadFrameData] Frame read is invalid: " <<
01137 nextFrameNr);
01138 MarkBadFrame(nextFrameNr);
01139 }
01140 else
01141 mBufferedFrameNr = nextFrameNr;
01142 }
01143 else
01144 {
01145
01146 if (mLastFrame == LASTFRAME_UNKNOWN)
01147 {
01148 mLastFrame = mCurrentFrameNr;
01149 ILOG_INFO("Adjusted last frame nr to: " << mLastFrame);
01150 }
01151 else
01152 {
01153
01154 MarkBadFrame(nextFrameNr);
01155 mCurrentFrameNr = nextFrameNr;
01156 }
01157 return true;
01158 }
01159 }
01160 mCurrentFrameNr = nextFrameNr;
01161 }
01162
01163 if (mBufferedFrameNr == mCurrentFrameNr)
01164 {
01165 ConvertFrameToRgb();
01166 if (mFormatName != "asf")
01167 CheckMD5Hash(mBufferedFrameNr);
01168 }
01169 }
01170 catch (LAVCException e)
01171 {
01172 ILOG_ERROR("Failure when going to frame: " << mTargetFrameNr << "; " << e.what());
01173 return false;
01174 }
01175
01176
01177 return true;
01178 }
01179
01180 void
01181 CheckMD5Hash(int frameNr)
01182 {
01183 if (!mIndexExists)
01184 return;
01185
01186 String refHash = GetHash(frameNr);
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198 String hash = CalcHash_protected();
01199
01200 ILOG_DEBUG("[CheckMD5Hash] frameNr=" << frameNr << " hash_calculated=" << hash << " hash_found=" << refHash);
01201
01202 mIsFrameAccurate = (hash==refHash);
01203 if (!mFixIndexIfBroken)
01204 {
01205 if (!mIsFrameAccurate)
01206 {
01207 ILOG_ERROR("Jumping to Frame("<<frameNr<<") ends in Frame("
01208 <<GetFrameFromHash(hash)<<")");
01209
01210 }
01211 return;
01212 }
01213
01214
01215 if (!mIsFrameAccurate)
01216 {
01217 if (true)
01218 {
01219 ILOG_ERROR("SK: Index is not correct for video: " << mSrcName);
01220 throw LAVCException("Index is not correct", 0);
01221 }
01222
01223
01224 if (frameNr==mLastFixNr)
01225 {
01226 mFixCnt++;
01227 if (mFixCnt>10)
01228 {
01229 String msg = "Cannot Fix video: " + mSrcName;
01230 ILOG_ERROR(msg << "; try with src=LAVC_NOIDX");
01231 throw LAVCException(msg, 0);
01232 }
01233 }
01234 else{
01235 mFixCnt=0;
01236 mLastFixNr=frameNr;
01237 }
01238
01239 ILOG_WARN("Fixing Frame Accuracy for frame "<<frameNr
01240 <<" (ended in "<<GetFrameFromHash(hash)<<")");
01241
01242
01243
01244 int BrokenKey = GetSeekableFrame(frameNr);
01245
01246 int fNr = frameNr;
01247 int cNr = mBufferedFrameNr;
01248
01249 while (--fNr)
01250 {
01251 ILOG_DEBUG("Checking for previous Non-Broken @ "<< fNr);
01252
01253 if (fNr < 0)
01254 {
01255 ILOG_ERROR("fNr is negative (" << fNr << ") and cannot be used as a column index");
01256 return;
01257 }
01258
01259 if ( (UInt32) fNr < mBlankFrames)
01260 {
01261 ILOG_DEBUG("fNr (" << fNr << ") is less than mBlankFrames (" << mBlankFrames << ")");
01262 return;
01263 }
01264 if (fNr==mBlankFrames)
01265 break;
01266
01267 if (GetSeekableFrame(fNr) != BrokenKey)
01268 break;
01269 }
01270
01271 ILOG_DEBUG("Found Previous Non-Broken frame " << fNr);
01272
01273 int PrevKey = GetSeekableFrame(fNr);
01274 if (PrevKey < 0)
01275 {
01276 ILOG_ERROR("PrevKey has negative value: " << PrevKey);
01277 return;
01278 }
01279 int64_t PrevKeyPos = GetPos(fNr);
01280 ILOG_DEBUG("Previous Non-Broken for Keyframe " << PrevKey);
01281
01282 fNr++;
01283 while (GetSeekableFrame(fNr)==BrokenKey)
01284 {
01285 ILOG_DEBUG("Resetting keyframe Information for "<<fNr);
01286 SetKey(fNr,PrevKey);
01287 SetPos(fNr,PrevKeyPos);
01288 fNr++;
01289 }
01290 ILOG_DEBUG("Retrying...");
01291
01292
01293
01294 Reset();
01295 ReadFrameData();
01296 }
01297 else
01298 {
01299 ILOG_DEBUG("Frame Accuracy OK for frame "<<frameNr);
01300 }
01301 }
01302
01303
01304 String DetermineInfoName(CString srcName, IndexMode mode, Util::Database* db)
01305 {
01306 String infoName = "";
01307 if (Link::DiskImage::DiskImageUsed())
01308 {
01309 String subPath = FileNamePath(srcName);
01310 if (subPath.substr(0, 10) == "diskimage:")
01311 {
01312 int posAfterDiskImageFileName = subPath.find("://", 10);
01313
01314
01315 const String uptoDiskImageToken =
01316 subPath.substr(0, posAfterDiskImageFileName);
01317 int diskImageFileNamePos =
01318 FileNameLastPathSepPos(uptoDiskImageToken) + 1;
01319 if (diskImageFileNamePos == String::npos)
01320 ILOG_ERROR("Disk image file was expected to be prefixed "
01321 << "with a path: " << uptoDiskImageToken);
01322
01323 String subSubPath =
01324 subPath.substr(posAfterDiskImageFileName + 1);
01325 subSubPath = StringReplaceAll(subSubPath,
01326 "0x", "0x30x", false);
01327 subSubPath = StringReplaceAll(subSubPath,
01328 "//", "/0x2F", false);
01329 subSubPath = subSubPath.substr(0, subSubPath.size() - 1);
01330 subPath = subPath.substr(diskImageFileNamePos,
01331 posAfterDiskImageFileName-diskImageFileNamePos)+subSubPath;
01332
01333 String dir = "FramePosIndex/" + subPath;
01334
01335 bool toWrite = (mode == WRITEIDX);
01336 bool silent = (mode != READIDX);
01337
01338 if (toWrite)
01339 db->MakeDir(dir);
01340
01341 String fname = FileNameTail(srcName) + ".info";
01342 infoName = db->GetFilePath(dir, fname, toWrite, silent);
01343 }
01344 else
01345 infoName = srcName + ".info";
01346 }
01347 return infoName;
01348 }
01349
01350
01351 int
01352 DecodeNextFrame(bool& isValidFrame, bool& isKeyFrame)
01353 {
01354
01355
01356 const int MAX_READ_FAILURES = Impala::Max(15, 5 * mGopSize);
01357 int nrOfReadFailures = 0;
01358
01359 int atEndOfFile =
01360 #ifdef FFMPEG_52
01361 url_feof(mFormatCtx->pb);
01362 #else
01363 url_feof(&mFormatCtx->pb);
01364 #endif
01365
01366
01367
01368 bool readFrameFailed = false;
01369
01370 isValidFrame = false;
01371 isKeyFrame = false;
01372 int rc = 0;
01373 while (true)
01374 {
01375 int readFrameResult = av_read_frame(mFormatCtx, mPacket);
01376 readFrameFailed = (readFrameResult < 0);
01377 if (readFrameFailed)
01378 {
01379
01380
01381 ILOG_DEBUG("av_read_frame failed and returned: " << readFrameResult);
01382 }
01383
01384
01385
01386
01387 if (mPacket->stream_index == mVideoStreamIndex)
01388 {
01389 int frameDecoded = -1;
01390
01391
01392
01393
01394
01395
01396 const int bufSize = mPacket->size;
01397 uint8_t *buf = new uint8_t[bufSize + FF_INPUT_BUFFER_PADDING_SIZE];
01398 for (int i = 0; i < bufSize; i++)
01399 buf[i] = (mPacket->data)[i];
01400 for (int i = 0; i < FF_INPUT_BUFFER_PADDING_SIZE; i++)
01401 buf[bufSize + i] = 0;
01402 int len = avcodec_decode_video(mCodecCtx, mFrame, &frameDecoded,
01403 buf, bufSize);
01404 delete [] buf;
01405
01406 ILOG_DEBUG("mPacket->pts = " << mPacket->pts << " ; mPacket->dts = " << mPacket->dts);
01407 if (len < 0)
01408 ILOG_DEBUG(" avcodec_decode_video returned: " << len);
01409
01410 if (frameDecoded)
01411 {
01412 isValidFrame = true;
01413 isKeyFrame = (mFrame->pict_type==FF_I_TYPE && mFrame->key_frame==1);
01414 break;
01415 }
01416 else
01417 {
01418 #ifdef FFMPEG_52
01419 ILOG_DEBUG(
01420 " [DecodeNextFrame] Frame not valid; mPacket->size=" <<
01421 mPacket->size << "; mPacket->flags=" <<
01422 mPacket->flags << "; bp->pos=" << mFormatCtx->pb->pos);
01423 #else
01424 ILOG_DEBUG(
01425 " [DecodeNextFrame] Frame not valid; mPacket->size=" <<
01426 mPacket->size << "; mPacket->flags=" <<
01427 mPacket->flags << "; bp.pos=" << mFormatCtx->pb.pos);
01428 #endif
01429
01430
01431 if (atEndOfFile)
01432 {
01433 rc = -3;
01434 break;
01435 }
01436
01437
01438
01439 if (mPacket->flags == 0)
01440 break;
01441 }
01442 }
01443
01444 av_free_packet(mPacket);
01445
01446
01447
01448 nrOfReadFailures++;
01449 if ((atEndOfFile || readFrameFailed) && (nrOfReadFailures > MAX_READ_FAILURES))
01450 {
01451 ILOG_WARN("Max. nr of frame read failures reached (" <<
01452 MAX_READ_FAILURES << "); probably at end of file");
01453 rc = -1;
01454 break;
01455 }
01456 }
01457
01458 av_free_packet(mPacket);
01459 return rc;
01460 }
01461
01462
01463 void
01464 ConvertFrameToRgb()
01465 {
01466 const int result = sws_scale(mSwsContext,
01467 mFrame->data, mFrame->linesize,
01468 0, mFrameHeight,
01469 mFrameRGB->data, mFrameRGB->linesize);
01470 }
01471
01472
01473 int mVideoStreamIndex;
01474 AVStream* mVideoStream;
01475 AVFormatContext* mFormatCtx;
01476 AVCodecContext* mCodecCtx;
01477 struct SwsContext* mSwsContext;
01478 AVCodec* mCodec;
01479 AVFrame* mFrame;
01480 AVFrame* mFrameRGB;
01481 AVPacket* mPacket;
01482
01483 int mBufferedFrameNr;
01484 bool mValid;
01485 uint32_t mFrameCnt;
01486 uint32_t mFrameCountCalculated;
01487 IndexMode mMode;
01488 bool mFixIndexIfBroken;
01489 String mJumpMethod;
01490 int mJumpFlags;
01491 int mLastFixNr;
01492 int mFixCnt;
01493
01494 ILOG_VAR_DECL;
01495
01496 };
01497
01498 ILOG_VAR_INIT(RgbDataSrcLavc_old, Impala.Core.Stream);
01499
01500 }}}
01501
01502 #endif