gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash ChangeLog libmedia/ffmpeg/MediaParserFfmp...


From: Sandro Santilli
Subject: [Gnash-commit] gnash ChangeLog libmedia/ffmpeg/MediaParserFfmp...
Date: Wed, 04 Jun 2008 14:06:58 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Sandro Santilli <strk>  08/06/04 14:06:57

Modified files:
        .              : ChangeLog 
        libmedia/ffmpeg: MediaParserFfmpeg.cpp MediaParserFfmpeg.h 
        server/asobj   : NetStreamFfmpeg.cpp 

Log message:
        * libmedia/ffmpeg/MediaParserFfmpeg.{cpp,h}: implement frame parsing.
        * server/asobj/NetStreamFfmpeg.cpp (refreshVideoFrame): don't do
          anything if video decoder wasn't initialized.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.6809&r2=1.6810
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/ffmpeg/MediaParserFfmpeg.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/ffmpeg/MediaParserFfmpeg.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.cpp?cvsroot=gnash&r1=1.141&r2=1.142

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.6809
retrieving revision 1.6810
diff -u -b -r1.6809 -r1.6810
--- ChangeLog   4 Jun 2008 14:02:01 -0000       1.6809
+++ ChangeLog   4 Jun 2008 14:06:56 -0000       1.6810
@@ -1,3 +1,9 @@
+2008-06-04 Sandro Santilli <address@hidden>
+
+       * libmedia/ffmpeg/MediaParserFfmpeg.{cpp,h}: implement frame parsing.
+       * server/asobj/NetStreamFfmpeg.cpp (refreshVideoFrame): don't do
+         anything if video decoder wasn't initialized.
+
 2008-06-04 Benjamin Wolsey <address@hidden>
 
        * server/movie_root.cpp: add metadata to Movie Properties tree.

Index: libmedia/ffmpeg/MediaParserFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/libmedia/ffmpeg/MediaParserFfmpeg.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libmedia/ffmpeg/MediaParserFfmpeg.cpp       4 Jun 2008 11:40:46 -0000       
1.2
+++ libmedia/ffmpeg/MediaParserFfmpeg.cpp       4 Jun 2008 14:06:57 -0000       
1.3
@@ -30,6 +30,16 @@
 namespace gnash {
 namespace media {
 
+namespace { // anonymous namespace
+
+       // Used to calculate a decimal value from a ffmpeg fraction
+       inline double as_double(AVRational time)
+       {
+               return time.num / (double) time.den;
+       }
+
+} // anonymous namespace
+
 
 int
 MediaParserFfmpeg::readPacketWrapper(void* opaque, boost::uint8_t* buf, int 
buf_size)
@@ -114,6 +124,7 @@
 VideoInfo*
 MediaParserFfmpeg::getVideoInfo()
 {
+        //VideoInfo(int codeci, boost::uint16_t widthi, boost::uint16_t 
heighti, boost::uint16_t frameRatei, boost::uint64_t durationi, codecType typei)
        LOG_ONCE( log_unimpl("%s", __PRETTY_FUNCTION__) );
        return 0;
 }
@@ -130,11 +141,11 @@
 {
        log_debug("MediaParserFfmpeg::seek(%d) TESTING", pos);
 
-       AVStream* videostream = _formatCtx->streams[_videoIndex];
+       AVStream* videostream = _formatCtx->streams[_videoStreamIndex];
        double timebase = static_cast<double>(videostream->time_base.num / 
videostream->time_base.den);
        long newpos = static_cast<long>(pos / timebase);
                
-       if (av_seek_frame(_formatCtx, _videoIndex, newpos, 0) < 0)
+       if (av_seek_frame(_formatCtx, _videoStreamIndex, newpos, 0) < 0)
        {
                log_error(_("%s: seeking failed"), __FUNCTION__);
                return 0;
@@ -153,21 +164,123 @@
                        return 0; // ??
                }
 
-               newtime = timebase * 
(double)_formatCtx->streams[_videoIndex]->cur_dts;
+               newtime = timebase * 
(double)_formatCtx->streams[_videoStreamIndex]->cur_dts;
        }
 
        //av_free_packet( &Packet );
-       av_seek_frame(_formatCtx, _videoIndex, newpos, 0);
+       av_seek_frame(_formatCtx, _videoStreamIndex, newpos, 0);
 
        newtime = static_cast<boost::int32_t>(newtime / 1000.0);
        return newtime;
 }
 
 bool
-MediaParserFfmpeg::parseNextChunk()
+MediaParserFfmpeg::parseVideoFrame(AVPacket& packet)
 {
-       LOG_ONCE( log_unimpl("%s", __PRETTY_FUNCTION__) );
+       assert(packet.stream_index == _videoStreamIndex);
+       assert(_videoStream);
+
+       // packet.dts is "decompression" timestamp
+       // packet.pts is "presentation" timestamp
+       // Dunno why we use dts, and don't understand the magic formula 
either...
+       boost::uint64_t timestamp = static_cast<boost::uint64_t>(packet.dts * 
as_double(_videoStream->time_base) * 1000.0); 
+
+       // flags, for keyframe
+       bool isKeyFrame = packet.flags&PKT_FLAG_KEY;
+
+       // Frame offset in input
+       boost::int64_t offset = packet.pos;
+       if ( offset < 0 )
+       {
+               log_error("Unknown offset of video frame, what to use here ?");
+               return false;
+       }
+
+       VideoFrameInfo* info = new VideoFrameInfo;
+       info->dataSize = packet.size;
+       info->isKeyFrame = isKeyFrame;
+       info->dataPosition = offset;
+       info->timestamp = timestamp;
+
+       _videoFrames.push_back(info); // takes ownership
+
+       return true;
+}
+
+bool
+MediaParserFfmpeg::parseAudioFrame(AVPacket& packet)
+{
+       assert(packet.stream_index == _audioStreamIndex);
+       assert(_audioStream);
+
+       // packet.dts is "decompression" timestamp
+       // packet.pts is "presentation" timestamp
+       // Dunno why we use dts, and don't understand the magic formula 
either...
+       boost::uint64_t timestamp = static_cast<boost::uint64_t>(packet.dts * 
as_double(_audioStream->time_base) * 1000.0); 
+
+       // Frame offset in input
+       boost::int64_t offset = packet.pos;
+       if ( offset < 0 )
+       {
+               log_error("Unknown offset of audio frame, what to use here ?");
        return false;
+       }
+
+       AudioFrameInfo* info = new AudioFrameInfo;
+       info->dataSize = packet.size;
+       info->dataPosition = offset;
+       info->timestamp = timestamp;
+
+       _audioFrames.push_back(info); // takes ownership
+
+       return true;
+}
+
+bool
+MediaParserFfmpeg::parseNextFrame()
+{
+       if ( _parsingComplete ) return false;
+
+       assert(_formatCtx);
+
+       AVPacket packet;
+
+       int rc = av_read_frame(_formatCtx, &packet);
+       if ( rc < 0 )
+       {
+               log_error(_("MediaParserFfmpeg::parseNextChunk: Problems 
parsing next frame"));
+               return false;
+       }
+
+       bool ret=false;
+
+       if ( packet.stream_index == _videoStreamIndex )
+       {
+               ret = parseVideoFrame(packet);
+       }
+       else if ( packet.stream_index == _audioStreamIndex )
+       {
+               ret = parseAudioFrame(packet);
+       }
+       else
+       {
+               ret = false; // redundant..
+               log_debug("MediaParserFfmpeg::parseNextFrame: unknown stream 
index %d", packet.stream_index);
+       }
+
+       av_free_packet(&packet);
+
+       return ret;
+
+}
+
+bool
+MediaParserFfmpeg::parseNextChunk()
+{
+       // parse 2 frames...
+       if ( ! parseNextFrame() ) return false;
+       if ( ! parseNextFrame() ) return false;
+       return true;
 }
 
 boost::uint64_t
@@ -182,9 +295,9 @@
        MediaParser(stream),
        _inputFmt(0),
        _formatCtx(0),
-       _videoIndex(-1),
+       _videoStreamIndex(-1),
        _videoStream(0),
-       _audioIndex(-1),
+       _audioStreamIndex(-1),
        _audioStream(0),
        _lastParsedPosition(0)
 {
@@ -229,17 +342,17 @@
                switch (enc->codec_type)
                {
                        case CODEC_TYPE_AUDIO:
-                               if (_audioIndex < 0)
+                               if (_audioStreamIndex < 0)
                                {
-                                       _audioIndex = i;
+                                       _audioStreamIndex = i;
                                        _audioStream = _formatCtx->streams[i];
                                }
                                break;
 
                        case CODEC_TYPE_VIDEO:
-                               if (_videoIndex < 0)
+                               if (_videoStreamIndex < 0)
                                {
-                                       _videoIndex = i;
+                                       _videoStreamIndex = i;
                                        _videoStream = _formatCtx->streams[i];
                                }
                                break;
@@ -247,17 +360,10 @@
                                break;
                }
        }
-
-       LOG_ONCE( log_unimpl("MediaParserFfmpeg") );
 }
 
 MediaParserFfmpeg::~MediaParserFfmpeg()
 {
-       if ( _inputFmt )
-       {
-               // TODO: check if this is correct (should we create RIIA 
classes for ffmpeg stuff?)
-               av_free(_inputFmt);
-       }
 
        if ( _formatCtx )
        {
@@ -265,6 +371,24 @@
                //av_close_input_file(_formatCtx); // NOTE: this one triggers a 
mismatched free/delete on _byteIOBuffer !
                av_free(_formatCtx);
        }
+
+       if ( _inputFmt )
+       {
+               // TODO: check if this is correct (should we create RIIA 
classes for ffmpeg stuff?)
+               //av_free(_inputFmt); // it seems this one blows up, could be 
due to av_free(_formatCtx) above
+       }
+
+       for (VideoFrames::iterator i=_videoFrames.begin(),
+               e=_videoFrames.end(); i!=e; ++i)
+       {
+               delete (*i);
+       }
+
+       for (AudioFrames::iterator i=_audioFrames.begin(),
+               e=_audioFrames.end(); i!=e; ++i)
+       {
+               delete (*i);
+       }
 }
 
 int 
@@ -280,6 +404,9 @@
        boost::uint64_t curPos = in.get_position();
        if ( curPos > _lastParsedPosition ) _lastParsedPosition = curPos;
 
+       // Check if EOF was reached
+       if ( in.get_eof() ) _parsingComplete=true;
+
        return ret;
 
 }

Index: libmedia/ffmpeg/MediaParserFfmpeg.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/ffmpeg/MediaParserFfmpeg.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libmedia/ffmpeg/MediaParserFfmpeg.h 4 Jun 2008 11:40:46 -0000       1.2
+++ libmedia/ffmpeg/MediaParserFfmpeg.h 4 Jun 2008 14:06:57 -0000       1.3
@@ -26,6 +26,7 @@
 
 #include "MediaParser.h" // for inheritance
 
+#include <vector>
 #include <boost/scoped_array.hpp>
 #include <memory>
 
@@ -87,6 +88,101 @@
 
 private:
 
+       /// Information about an FFMPEG Video Frame
+       class VideoFrameInfo
+       {
+       public:
+
+               VideoFrameInfo()
+                       :
+                       isKeyFrame(false),
+                       dataSize(0),
+                       dataPosition(0),
+                       timestamp(0)
+               {}
+
+               /// Type of this frame 
+               bool isKeyFrame;
+
+               /// Size of the frame in bytes (needed?)
+               boost::uint32_t dataSize;
+
+               /// Start of frame data in stream
+               boost::uint64_t dataPosition;
+
+               /// Timestamp in milliseconds 
+               boost::uint32_t timestamp;
+
+       };
+
+       /// Information about an FFMPEG Audio Frame
+       class AudioFrameInfo
+       {
+       public:
+
+               AudioFrameInfo()
+                       :
+                       dataSize(0),
+                       dataPosition(0),
+                       timestamp(0)
+               {}
+
+               /// Size of the frame in bytes (needed?)
+               boost::uint32_t dataSize;
+
+               /// Start of frame data in stream
+               boost::uint64_t dataPosition;
+
+               /// Timestamp in milliseconds 
+               boost::uint32_t timestamp;
+
+       };
+
+       // NOTE: VideoFrameInfo is a relatively small structure,
+       //       chances are keeping by value here would reduce
+       //       memory fragmentation with no big cost
+       typedef std::vector<VideoFrameInfo*> VideoFrames;
+
+       /// list of videoframes, does no contain the frame data.
+       //
+       /// Elements owned by this class.
+       ///
+       VideoFrames _videoFrames;
+
+       // NOTE: AudioFrameInfo is a relatively small structure,
+       //       chances are keeping by value here would reduce
+       //       memory fragmentation with no big cost
+       typedef std::vector<AudioFrameInfo*> AudioFrames;
+
+       /// list of audioframes, does no contain the frame data.
+       //
+       /// Elements owned by this class.
+       AudioFrames _audioFrames;
+
+       /// Parse next media frame
+       //
+       /// @return false on error or eof, true otherwise
+       ///
+       bool parseNextFrame();
+
+       /// Parse a video frame
+       //
+       /// Basically create a VideoFrameInfo out of the AVPacket and push
+       /// it on the container.
+       ///
+       /// @return false on error 
+       ///
+       bool parseVideoFrame(AVPacket& packet);
+
+       /// Parse an audio frame
+       //
+       /// Basically create a AudioFrameInfo out of the AVPacket and push
+       /// it on the container.
+       ///
+       /// @return false on error 
+       ///
+       bool parseAudioFrame(AVPacket& packet);
+
        /// Input chunk reader, to be called by ffmpeg parser
        int readPacket(boost::uint8_t* buf, int buf_size);
 
@@ -108,13 +204,13 @@
        AVFormatContext *_formatCtx;
 
        /// Index of the video stream in input
-       int _videoIndex;
+       int _videoStreamIndex;
 
        /// Video input stream
        AVStream* _videoStream;
 
        /// Index of the audio stream in input
-       int _audioIndex;
+       int _audioStreamIndex;
 
        // audio
        AVStream* _audioStream;

Index: server/asobj/NetStreamFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.cpp,v
retrieving revision 1.141
retrieving revision 1.142
diff -u -b -r1.141 -r1.142
--- server/asobj/NetStreamFfmpeg.cpp    3 Jun 2008 16:21:38 -0000       1.141
+++ server/asobj/NetStreamFfmpeg.cpp    4 Jun 2008 14:06:57 -0000       1.142
@@ -725,6 +725,9 @@
 {
        assert ( m_parser.get() );
 
+       // nothing to do if we don't have a video decoder
+       if ( ! _videoDecoder.get() ) return;
+
 #ifdef GNASH_DEBUG_DECODING
        // bufferLength() would lock the mutex (which we already hold),
        // so this is to avoid that.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]