[haiku-commits] r38545 - haiku/trunk/src/add-ons/media/plugins/ffmpeg

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 6 Sep 2010 20:45:05 +0200 (CEST)

Author: stippi
Date: 2010-09-06 20:45:05 +0200 (Mon, 06 Sep 2010)
New Revision: 38545
Changeset: http://dev.haiku-os.org/changeset/38545

Modified:
   haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp
Log:
 * Do not use an I/O buffer which is allocated with a StreamCookie
   object. Demuxers may actually resize the I/O context buffer,
   which would corrupt memory. This is certainly the case in FFmpeg
   0.6, don't know if it was a problem before.
 * Do not set the time to the packet PTS in Seek(), if it's the magic
   value for "no PTS".
 * Don't regard the AVInputFormat flags (generic index), we can detect
   this more reliably by the observed behavior: Don't trust the found
   keyframe if we are obvioulsy building the keyframe index on the fly.


Modified: haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp
===================================================================
--- haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp     
2010-09-06 18:13:58 UTC (rev 38544)
+++ haiku/trunk/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp     
2010-09-06 18:45:05 UTC (rev 38545)
@@ -45,10 +45,6 @@
 #define ERROR(a...) fprintf(stderr, a)
 
 
-static const size_t kIOBufferSize = 64 * 1024;
-       // TODO: This could depend on the BMediaFile creation flags, IIRC,
-       // they allow to specify a buffering mode.
-
 static const int64 kNoPTSValue = 0x8000000000000000LL;
        // NOTE: For some reasons, I have trouble with the avcodec.h define:
        // #define AV_NOPTS_VALUE          INT64_C(0x8000000000000000)
@@ -156,7 +152,6 @@
                        int32                           fVirtualIndex;
 
                        ByteIOContext           fIOContext;
-                       uint8                           
fIOBuffer[kIOBufferSize];
 
                        AVPacket                        fPacket;
                        bool                            fReusePacket;
@@ -183,7 +178,6 @@
 
        fStreamBuildsIndexWhileReading(false)
 {
-       memset(&fIOBuffer, 0, sizeof(fIOBuffer));
        memset(&fFormat, 0, sizeof(media_format));
        av_new_packet(&fPacket, 0);
 }
@@ -201,16 +195,17 @@
 {
        // Init probing data
        size_t probeSize = 2048;
+       uint8* probeBuffer = (uint8*)malloc(probeSize);
        AVProbeData probeData;
        probeData.filename = "";
-       probeData.buf = fIOBuffer;
+       probeData.buf = probeBuffer;
        probeData.buf_size = probeSize;
 
        // Read a bit of the input...
        // NOTE: Even if other streams have already read from the source,
        // it is ok to not seek first, since our fPosition is 0, so the 
necessary
        // seek will happen automatically in _Read().
-       if (_Read(this, fIOBuffer, probeSize) != (ssize_t)probeSize)
+       if (_Read(this, probeBuffer, probeSize) != (ssize_t)probeSize)
                return B_IO_ERROR;
        // ...and seek back to the beginning of the file. This is important
        // since libavformat will assume the stream to be at offset 0, the
@@ -250,7 +245,7 @@
 
        // Init I/O context with buffer and hook functions, pass ourself as
        // cookie.
-       if (init_put_byte(&fIOContext, fIOBuffer, kIOBufferSize, 0, this,
+       if (init_put_byte(&fIOContext, probeBuffer, probeSize, 0, this,
                        _Read, 0, _Seek) != 0) {
                TRACE("AVFormatReader::StreamCookie::Open() - "
                        "init_put_byte() failed!\n");
@@ -751,7 +746,7 @@
                bigtime_t startTime = 
_ConvertFromStreamTimeBase(fStream->start_time);
                TRACE("  start_time: %lld or %.5fs\n", startTime,
                        startTime / 1000000.0);
-               // TODO: Handle start time in FindKeyFrame()?!
+               // TODO: Handle start time in FindKeyFrame() and Seek()?!
        }
        #endif // TRACE_AVFORMAT_READER
 
@@ -840,7 +835,7 @@
        // based on frame.
        double frameRate = FrameRate();
        if ((flags & B_MEDIA_SEEK_TO_FRAME) != 0)
-               *time = (bigtime_t)(*frame * 1000000LL / frameRate + 0.5);
+               *time = (bigtime_t)(*frame * 1000000.0 / frameRate + 0.5);
 
 #if 0
        // This happens in ffplay.c:
@@ -860,7 +855,13 @@
        ret = av_seek_frame(fContext, Index(), pos, seekFlags);
 #endif
 
+#if 0
+       int streamIndex = -1;
+       int64_t timeStamp = *time / AV_TIME_BASE;
+#else
+       int streamIndex = Index();
        int64_t timeStamp = _ConvertToStreamTimeBase(*time);
+#endif
 
        TRACE_SEEK("  time: %.5fs -> %lld, current DTS: %lld (time_base: 
%d/%d)\n",
                *time / 1000000.0, timeStamp, fStream->cur_dts, 
fStream->time_base.num,
@@ -874,13 +875,13 @@
        bigtime_t oneSecond = 1000000;
        int64_t minTimeStamp = timeStamp - _ConvertToStreamTimeBase(oneSecond);
        int64_t maxTimeStamp = timeStamp + _ConvertToStreamTimeBase(oneSecond);
-       if (avformat_seek_file(fContext, Index(), minTimeStamp, timeStamp,
+       if (avformat_seek_file(fContext, streamIndex, minTimeStamp, timeStamp,
                maxTimeStamp, searchFlags) < 0) {
                TRACE_SEEK("  avformat_seek_file() failed.\n");
                return B_ERROR;
        }
 #else
-       if (av_seek_frame(fContext, Index(), timeStamp, searchFlags) < 0) {
+       if (av_seek_frame(fContext, streamIndex, timeStamp, searchFlags) < 0) {
                printf("  av_seek_frame() failed.\n");
                return B_ERROR;
        }
@@ -890,7 +891,8 @@
        // know where we really seeked.
        fReusePacket = false;
        if (_NextPacket(true) == B_OK) {
-               *time = _ConvertFromStreamTimeBase(fPacket.pts);
+               if (fPacket.pts != kNoPTSValue)
+                       *time = _ConvertFromStreamTimeBase(fPacket.pts);
                TRACE_SEEK("  seeked time: %.2fs\n", *time / 1000000.0);
                if ((flags & B_MEDIA_SEEK_TO_FRAME) != 0) {
                        *frame = *time * frameRate / 1000000LL + 0.5;
@@ -938,8 +940,17 @@
                // Best is to assume we can somehow seek to the time/frame
                // and leave them as they are.
        } else {
-               const AVIndexEntry& entry = fStream->index_entries[index];
-               timeStamp = entry.timestamp;
+               if (index > 0) {
+                       const AVIndexEntry& entry = 
fStream->index_entries[index];
+                       timeStamp = entry.timestamp;
+               } else {
+                       // Some demuxers use the first index entry to store some
+                       // other information, like the total playing time for 
example.
+                       // Assume the timeStamp of the first entry is alays 0.
+                       // TODO: Handle start-time offset?
+                       timeStamp = 0;
+               }
+                       
                bigtime_t foundTime = _ConvertFromStreamTimeBase(timeStamp);
                // It's really important that we can convert this back to the
                // same time-stamp (i.e. FindKeyFrame() with the time we return
@@ -949,7 +960,7 @@
                bigtime_t timeDiff = foundTime > *time
                        ? foundTime - *time : *time - foundTime;
        
-               if (fStreamBuildsIndexWhileReading && timeDiff > 1000000) {
+               if (timeDiff > 1000000 && index == fStream->nb_index_entries - 
1) {
                        // If the stream is building the index on the fly while 
parsing
                        // it, we only have entries in the index for positions 
already
                        // decoded, i.e. we cannot seek into the future. In 
that case,


Other related posts:

  • » [haiku-commits] r38545 - haiku/trunk/src/add-ons/media/plugins/ffmpeg - superstippi