gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ChangeLog backend/sound_handler_gst.cpp l...


From: Tomas Groth
Subject: [Gnash-commit] gnash ChangeLog backend/sound_handler_gst.cpp l...
Date: Wed, 28 Mar 2007 16:12:08 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Tomas Groth <tgc>       07/03/28 16:12:08

Modified files:
        .              : ChangeLog 
        backend        : sound_handler_gst.cpp 
        libbase        : FLVParser.cpp FLVParser.h 
        server/asobj   : NetConnection.cpp NetStreamFfmpeg.cpp 
                         NetStreamGst.cpp NetStreamGst.h 

Log message:
                * backend/sound_handler_gst.cpp: Don't calculate the numbers of 
                  buffers to feed to the pipeline, since it makes loaded sound
                  streams stop to early.
                * libbase/FLVParser.{h,cpp}: Made it thread-safe. Fixed a lot of
                  bugs. Added support for extacting size of h.263 video.
                * server/asobj/NetConnection.cpp: Set _loader to NULL after 
deletion.
                * server/asobj/NetStreamFfmpeg.cpp: Corrected some error 
messages and
                  error handling.
                * server/asobj/NetStreamGst.{h,cpp}: Use our internal FLVParser
                  when FLV is being played.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2701&r2=1.2702
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_gst.cpp?cvsroot=gnash&r1=1.33&r2=1.34
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/FLVParser.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/FLVParser.h?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetConnection.cpp?cvsroot=gnash&r1=1.33&r2=1.34
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.cpp?cvsroot=gnash&r1=1.24&r2=1.25
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.cpp?cvsroot=gnash&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.h?cvsroot=gnash&r1=1.9&r2=1.10

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2701
retrieving revision 1.2702
diff -u -b -r1.2701 -r1.2702
--- ChangeLog   28 Mar 2007 15:22:24 -0000      1.2701
+++ ChangeLog   28 Mar 2007 16:12:08 -0000      1.2702
@@ -1,3 +1,16 @@
+2007-03-28 Tomas Groth Christensen <address@hidden>
+
+       * backend/sound_handler_gst.cpp: Don't calculate the numbers of 
+         buffers to feed to the pipeline, since it makes loaded sound
+         streams stop to early.
+       * libbase/FLVParser.{h,cpp}: Made it thread-safe. Fixed a lot of
+         bugs. Added support for extacting size of h.263 video.
+       * server/asobj/NetConnection.cpp: Set _loader to NULL after deletion.
+       * server/asobj/NetStreamFfmpeg.cpp: Corrected some error messages and
+         error handling.
+       * server/asobj/NetStreamGst.{h,cpp}: Use our internal FLVParser
+         when FLV is being played.
+
 2007-03-28 Sandro Santilli <address@hidden>
 
        * server/array.{cpp,h}: implement Array.splice(),

Index: backend/sound_handler_gst.cpp
===================================================================
RCS file: /sources/gnash/gnash/backend/sound_handler_gst.cpp,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -b -r1.33 -r1.34
--- backend/sound_handler_gst.cpp       22 Feb 2007 13:00:17 -0000      1.33
+++ backend/sound_handler_gst.cpp       28 Mar 2007 16:12:08 -0000      1.34
@@ -18,7 +18,7 @@
 // Based on sound_handler_sdl.cpp by Thatcher Ulrich http://tulrich.com 2003
 // which has been donated to the Public Domain.
 
-/* $Id: sound_handler_gst.cpp,v 1.33 2007/02/22 13:00:17 tgc Exp $ */
+/* $Id: sound_handler_gst.cpp,v 1.34 2007/03/28 16:12:08 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -343,18 +343,10 @@
                g_object_set (G_OBJECT (gst_element->capsfilter), "caps", caps, 
NULL);
                gst_caps_unref (caps);
 
-               // number of buffers to send
-               int numBuf = 
static_cast<int>(ceil(static_cast<float>(sounddata->data_size) / 
static_cast<float>(BUFFER_SIZE)));
-               if (loop_count == -1) {
-                       numBuf = -1;
-               } else if (loop_count > 0) {
-                       numBuf = numBuf * (loop_count+1) -1;
-               }
-
                // setup fake source
                g_object_set (G_OBJECT (gst_element->input),
                                        "sizetype", 2, "can-activate-pull", 
FALSE, "signal-handoffs", TRUE,
-                                       "sizemax", BUFFER_SIZE, "num-buffers", 
numBuf, NULL);
+                                       "sizemax", BUFFER_SIZE, NULL);
                // Setup the callback
                gst_element->handoff_signal_id = g_signal_connect 
(gst_element->input, "handoff", G_CALLBACK (callback_handoff), gst_element);
 

Index: libbase/FLVParser.cpp
===================================================================
RCS file: /sources/gnash/gnash/libbase/FLVParser.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- libbase/FLVParser.cpp       23 Mar 2007 00:30:10 -0000      1.1
+++ libbase/FLVParser.cpp       28 Mar 2007 16:12:08 -0000      1.2
@@ -16,7 +16,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-// $Id: FLVParser.cpp,v 1.1 2007/03/23 00:30:10 tgc Exp $
+// $Id: FLVParser.cpp,v 1.2 2007/03/28 16:12:08 tgc Exp $
 
 #include "FLVParser.h"
 #include "amf.h"
@@ -42,15 +42,45 @@
        _audioFrames.clear();
 }
 
+uint16_t FLVParser::videoFrameRate()
+{
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // Make sure that there are parsed some frames
+       while(_videoFrames.size() < 2 && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       if (_videoFrames.size() < 2) return 0;
+
+       uint32_t framedelay = _videoFrames[1]->timestamp - 
_videoFrames[0]->timestamp;
+       
+       return static_cast<int16_t>(1000 / framedelay);
+}
+
+
 uint32_t FLVParser::videoFrameDelay()
 {
-       if (!_video || _lastVideoFrame < 1) return 0;
+       boost::mutex::scoped_lock lock(_mutex);
+
+       // If there are no video in this FLV return 0
+       if (!_video && _lastParsedPosition > 0) return 0;
+
+       // Make sure that there are parsed some frames
+       while(_videoFrames.size() < 2 && !_parsingComplete) {
+               parseNextFrame();
+       }
+
+       // If there is no video data return 0
+       if (_videoFrames.size() == 0 || !_video || _lastVideoFrame < 1) return 
0;
 
        return _videoFrames[_lastVideoFrame]->timestamp - 
_videoFrames[_lastVideoFrame-1]->timestamp;
 }
 
 FLVFrame* FLVParser::nextMediaFrame()
 {
+       boost::mutex::scoped_lock lock(_mutex);
+
        uint32_t video_size = _videoFrames.size();
        uint32_t audio_size = _audioFrames.size();
        
@@ -108,6 +138,8 @@
 
 FLVFrame* FLVParser::nextAudioFrame()
 {
+       boost::mutex::scoped_lock lock(_mutex);
+
        // If there are no audio in this FLV return NULL
        if (!_audio && _lastParsedPosition > 0) return NULL;
 
@@ -117,7 +149,7 @@
        }
 
        // If the needed frame can't be parsed (EOF reached) return NULL
-       if (_audioFrames.size() < static_cast<uint32_t>(_lastAudioFrame+1)) 
return NULL;
+       if (_audioFrames.size() <= static_cast<uint32_t>(_lastAudioFrame+1) || 
_audioFrames.size() == 0) return NULL;
 
        _lastAudioFrame++;
 
@@ -134,6 +166,8 @@
 
 FLVFrame* FLVParser::nextVideoFrame()
 {
+       boost::mutex::scoped_lock lock(_mutex);
+
        // If there are no video in this FLV return NULL
        if (!_video && _lastParsedPosition > 0) return NULL;
 
@@ -143,7 +177,7 @@
        }
 
        // If the needed frame can't be parsed (EOF reached) return NULL
-       if (_videoFrames.size() < static_cast<uint32_t>(_lastVideoFrame+1)) 
return NULL;
+       if (_videoFrames.size() <= static_cast<uint32_t>(_lastVideoFrame+1) || 
_videoFrames.size() == 0) return NULL;
 
        _lastVideoFrame++;
 
@@ -161,6 +195,7 @@
 
 uint32_t FLVParser::seekAudio(uint32_t time)
 {
+
        // Make sure that there are parsed some frames
        while(_audioFrames.size() < 1 && !_parsingComplete) {
                parseNextFrame();
@@ -178,7 +213,7 @@
        // If there are no audio greater than the given time
        // the last audioframe is returned
        if (_audioFrames.back()->timestamp < time) {
-               _lastVideoFrame = _audioFrames.size() - 2;
+               _lastAudioFrame = _audioFrames.size() - 2;
                return _audioFrames.back()->timestamp;
        }
 
@@ -227,7 +262,7 @@
        // If there are no videoframe greater than the given time
        // the last key videoframe is returned
        FLVVideoFrame* lastFrame = _videoFrames.back();
-       uint32_t numFrames = _audioFrames.size();
+       uint32_t numFrames = _videoFrames.size();
        if (lastFrame->timestamp < time) {
                uint32_t lastFrameNum = numFrames -1;
                while (lastFrame->frameType != KEY_FRAME) {
@@ -246,14 +281,14 @@
 
        // Here we test if the guess was ok, and adjust if needed.
        uint32_t bestFrame = guess;
-       uint32_t diff = abs(_audioFrames[bestFrame]->timestamp - time);
+       uint32_t diff = abs(_videoFrames[bestFrame]->timestamp - time);
        while (true) {
-               if (bestFrame+1 < numFrames && 
static_cast<uint32_t>(abs(_audioFrames[bestFrame+1]->timestamp - time)) < diff) 
{
+               if (bestFrame+1 < numFrames && 
static_cast<uint32_t>(abs(_videoFrames[bestFrame+1]->timestamp - time)) < diff) 
{
                        bestFrame = bestFrame + 1;
-                       diff = abs(_audioFrames[bestFrame+1]->timestamp - time);
-               } else if (bestFrame-1 > 0 && 
static_cast<uint32_t>(abs(_audioFrames[bestFrame+1]->timestamp - time)) < diff) 
{
+                       diff = abs(_videoFrames[bestFrame+1]->timestamp - time);
+               } else if (bestFrame-1 > 0 && 
static_cast<uint32_t>(abs(_videoFrames[bestFrame+1]->timestamp - time)) < diff) 
{
                        bestFrame = bestFrame - 1;
-                       diff = abs(_audioFrames[bestFrame-1]->timestamp - time);
+                       diff = abs(_videoFrames[bestFrame-1]->timestamp - time);
                } else {
                        break;
                }
@@ -280,13 +315,15 @@
        else bestFrame = rewindKeyframe;
 
        _lastVideoFrame = bestFrame - 1;
-       return _audioFrames[bestFrame]->timestamp;
+       return _videoFrames[bestFrame]->timestamp;
 }
 
 
 
 FLVVideoInfo* FLVParser::getVideoInfo()
 {
+       boost::mutex::scoped_lock lock(_mutex);
+
        // If there are no video in this FLV return NULL
        if (!_video && _lastParsedPosition > 0) return NULL;
 
@@ -295,7 +332,7 @@
                parseNextFrame();
        }
 
-       // If there are no audio data return NULL
+       // If there are no video data return NULL
        if (_videoInfo == NULL) return NULL;
 
        FLVVideoInfo* info = new FLVVideoInfo(_videoInfo->codec, 
_videoInfo->width, _videoInfo->height, _videoInfo->frameRate, 
_videoInfo->duration);
@@ -305,6 +342,8 @@
 
 FLVAudioInfo* FLVParser::getAudioInfo()
 {
+       boost::mutex::scoped_lock lock(_mutex);
+
        // If there are no audio in this FLV return NULL
        if (!_audio && _lastParsedPosition > 0) return NULL;
 
@@ -323,6 +362,9 @@
 
 bool FLVParser::isTimeLoaded(uint32_t time)
 {
+
+       boost::mutex::scoped_lock lock(_mutex);
+
        // Parse frames until the need time is found, or EOF
        while (!_parsingComplete && (_videoFrames.size() > 0 && 
_videoFrames.back()->timestamp < time) && (_audioFrames.size() > 0 && 
_audioFrames.back()->timestamp < time)) {
                parseNextFrame();
@@ -341,6 +383,7 @@
 
 uint32_t FLVParser::seek(uint32_t time)
 {
+       boost::mutex::scoped_lock lock(_mutex);
 
        if (_video)     time = seekVideo(time);
        if (_audio)     time = seekAudio(time);
@@ -349,7 +392,6 @@
 
 bool FLVParser::parseNextFrame()
 {
-
        // Parse the header if not done already. If unsuccesfull return false.
        if (_lastParsedPosition == 0 && !parseHeader()) return false;
 
@@ -380,7 +422,17 @@
                // If this is the first audioframe no info about the
                // audio format has been noted, so we do that now
                if (_audioInfo == NULL) {
-                       _audioInfo = new FLVAudioInfo((tag[11] & 0xf0) >> 4, 
(tag[11] & 0x0C) >> 2, (tag[11] & 0x02) >> 1, (tag[11] & 0x01) >> 0, 0);
+                       int samplerate = (tag[11] & 0x0C) >> 2;
+                       if (samplerate == 0) samplerate = 5500;
+                       else if (samplerate == 1) samplerate = 11000;
+                       else if (samplerate == 2) samplerate = 22050;
+                       else if (samplerate == 3) samplerate = 44100;
+
+                       int samplesize = (tag[11] & 0x02) >> 1;
+                       if (samplesize == 0) samplesize = 1;
+                       else samplesize = 2;
+
+                       _audioInfo = new FLVAudioInfo((tag[11] & 0xf0) >> 4, 
samplerate, samplesize, (tag[11] & 0x01) >> 0, 0);
                }
                _lastParsedPosition += 15 + bodyLength;
 
@@ -395,9 +447,55 @@
                // If this is the first videoframe no info about the
                // video format has been noted, so we do that now
                if (_videoInfo == NULL) {
+                       uint16_t codec = (tag[11] & 0x0f) >> 0;
+                       // Set standard guessed size...
+                       uint16_t width = 320;
+                       uint16_t height = 240;
+
+                       // Extract the video size from the videodata header
+                       if (codec == VIDEO_CODEC_H263) {
+                               _lt->seek(frame->dataPosition);
+                               uint8_t videohead[12];
+                               _lt->read(videohead, 12);
+
+                               bool sizebit1 = (videohead[3] & 0x02);
+                               bool sizebit2 = (videohead[3] & 0x01);
+                               bool sizebit3 = (videohead[4] & 0x80);
+
+                               // First some predefined sizes
+                               if (!sizebit1 && sizebit2 && !sizebit3 ) {
+                                       width = 352;
+                                       height = 288;
+                               } else if (!sizebit1 && sizebit2 && sizebit3 ) {
+                                       width = 176;
+                                       height = 144;
+                               } else if (sizebit1 && !sizebit2 && !sizebit3 ) 
{
+                                       width = 128;
+                                       height = 96;
+                               } else if (sizebit1 && !sizebit2 && sizebit3 ) {
+                                       width = 320;
+                                       height = 240;
+                               } else if (sizebit1 && sizebit2 && !sizebit3 ) {
+                                       width = 160;
+                                       height = 120;
+
+                               // Then the custom sizes (1 byte - untested and 
ugly)
+                               } else if (!sizebit1 && !sizebit2 && !sizebit3 
) {
+                                       width = (videohead[4] & 0x40) | 
(videohead[4] & 0x20) | (videohead[4] & 0x20) | (videohead[4] & 0x08) | 
(videohead[4] & 0x04) | (videohead[4] & 0x02) | (videohead[4] & 0x01) | 
(videohead[5] & 0x80);
+
+                                       height = (videohead[5] & 0x40) | 
(videohead[5] & 0x20) | (videohead[5] & 0x20) | (videohead[5] & 0x08) | 
(videohead[5] & 0x04) | (videohead[5] & 0x02) | (videohead[5] & 0x01) | 
(videohead[6] & 0x80);
+
+                               // Then the custom sizes (2 byte - untested and 
ugly)
+                               } else if (!sizebit1 && !sizebit2 && sizebit3 ) 
{
+                                       width = (videohead[4] & 0x40) | 
(videohead[4] & 0x20) | (videohead[4] & 0x20) | (videohead[4] & 0x08) | 
(videohead[4] & 0x04) | (videohead[4] & 0x02) | (videohead[4] & 0x01) | 
(videohead[5] & 0x80) | (videohead[5] & 0x40) | (videohead[5] & 0x20) | 
(videohead[5] & 0x20) | (videohead[5] & 0x08) | (videohead[5] & 0x04) | 
(videohead[5] & 0x02) | (videohead[5] & 0x01) | (videohead[6] & 0x80);
+
+                                       height = (videohead[6] & 0x40) | 
(videohead[6] & 0x20) | (videohead[6] & 0x20) | (videohead[6] & 0x08) | 
(videohead[6] & 0x04) | (videohead[6] & 0x02) | (videohead[6] & 0x01) | 
(videohead[7] & 0x80) | (videohead[7] & 0x40) | (videohead[7] & 0x20) | 
(videohead[7] & 0x20) | (videohead[7] & 0x08) | (videohead[7] & 0x04) | 
(videohead[7] & 0x02) | (videohead[7] & 0x01) | (videohead[8] & 0x80);
+                               } 
+
+                       }
 
-                       // TODO: parse the video frame header to extract info 
about the width and height.
-                       _videoInfo = new FLVVideoInfo((tag[11] & 0x0f) >> 0, 0 
/*width*/, 0 /*height*/, 0 /*frameRate*/, 0 /*duration*/);
+                       // Create the videoinfo 
+                       _videoInfo = new FLVVideoInfo(codec, width, height, 0 
/*frameRate*/, 0 /*duration*/);
                }
                _lastParsedPosition += 15 + bodyLength;
 

Index: libbase/FLVParser.h
===================================================================
RCS file: /sources/gnash/gnash/libbase/FLVParser.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- libbase/FLVParser.h 23 Mar 2007 00:30:10 -0000      1.1
+++ libbase/FLVParser.h 28 Mar 2007 16:12:08 -0000      1.2
@@ -16,7 +16,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-// $Id: FLVParser.h,v 1.1 2007/03/23 00:30:10 tgc Exp $
+// $Id: FLVParser.h,v 1.2 2007/03/28 16:12:08 tgc Exp $
 
 // Information about the FLV format can be found at http://osflash.org/flv
 
@@ -25,6 +25,7 @@
 
 #include "LoadThread.h"
 #include <vector>
+#include <boost/thread/mutex.hpp>
 
 enum videoCodecType
 {
@@ -64,9 +65,9 @@
 class FLVFrame
 {
 public:
-       int dataSize;
+       uint32_t dataSize;
        uint8_t* data;
-       uint32_t timestamp;
+       uint64_t timestamp;
        uint8_t tag;
 };
 
@@ -78,7 +79,7 @@
 class FLVAudioInfo
 {
 public:
-       FLVAudioInfo(int codeci, int sampleRatei, int sampleSizei, bool 
stereoi, long durationi)
+       FLVAudioInfo(uint16_t codeci, uint16_t sampleRatei, uint16_t 
sampleSizei, bool stereoi, uint64_t durationi)
                : codec(codeci),
                sampleRate(sampleRatei),
                sampleSize(sampleSizei),
@@ -87,11 +88,11 @@
                {
                }
 
-       int codec;
-       int sampleRate;
-       int sampleSize;
+       uint16_t codec;
+       uint16_t sampleRate;
+       uint16_t sampleSize;
        bool stereo;
-       long duration;
+       uint64_t duration;
 };
 
 /// \brief
@@ -102,7 +103,7 @@
 class FLVVideoInfo
 {
 public:
-       FLVVideoInfo(int codeci, int widthi, int heighti, int frameRatei, long 
durationi)
+       FLVVideoInfo(uint16_t codeci, uint16_t widthi, uint16_t heighti, 
uint16_t frameRatei, uint64_t durationi)
                : codec(codeci),
                width(widthi),
                height(heighti),
@@ -115,7 +116,7 @@
        uint16_t width;
        uint16_t height;
        uint16_t frameRate;
-       long duration;
+       uint64_t duration;
 };
 
 
@@ -124,7 +125,7 @@
 public:
        uint16_t frameType;
        uint32_t dataSize;
-       long dataPosition;
+       uint64_t dataPosition;
        uint32_t timestamp;
        
 };
@@ -133,7 +134,7 @@
 {
 public:
        uint32_t dataSize;
-       long dataPosition;
+       uint64_t dataPosition;
        uint32_t timestamp;
        
 };
@@ -188,6 +189,9 @@
        /// videoframe in milliseconds. This is used for framerate.
        uint32_t videoFrameDelay();
 
+       /// Returns the framerate of the video
+       uint16_t videoFrameRate();
+
 private:
 
        /// seeks to the closest possible position the given position,
@@ -219,7 +223,7 @@
        std::vector<FLVAudioFrame*> _audioFrames;
 
        /// The position where the parsing should continue from.
-       long _lastParsedPosition;
+       uint64_t _lastParsedPosition;
 
        /// Whether the parsing is complete or not
        bool _parsingComplete;
@@ -231,16 +235,19 @@
        FLVAudioInfo* _audioInfo;
 
        /// Last audio frame returned
-       int _lastAudioFrame;
+       int32_t _lastAudioFrame;
 
        /// Last video frame returned
-       int _lastVideoFrame;
+       int32_t _lastVideoFrame;
 
        /// Audio stream is present
        bool _audio;
 
        /// Audio stream is present
        bool _video;
+
+       /// Mutex to avoid problems with threads using the parser
+       boost::mutex _mutex;
 };
 
 #endif // __FLVPARSER_H__

Index: server/asobj/NetConnection.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetConnection.cpp,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -b -r1.33 -r1.34
--- server/asobj/NetConnection.cpp      24 Mar 2007 14:36:47 -0000      1.33
+++ server/asobj/NetConnection.cpp      28 Mar 2007 16:12:08 -0000      1.34
@@ -14,7 +14,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: NetConnection.cpp,v 1.33 2007/03/24 14:36:47 tgc Exp $ */
+/* $Id: NetConnection.cpp,v 1.34 2007/03/28 16:12:08 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -61,7 +61,10 @@
 }
 
 NetConnection::~NetConnection() {
-       if (_loader) delete _loader;
+       if (_loader) {
+               delete _loader;
+               _loader = NULL;
+       }
 }
 
 /// Open a connection to stream FLV files.
@@ -101,6 +104,7 @@
        if 
(!_loader->setStream(std::auto_ptr<tu_file>(StreamProvider::getDefaultInstance().getStream(uri))))
 {
                log_warning("Gnash could not open this url:%s", _url.c_str());
                delete _loader;
+               _loader = NULL;
                return false;
        }
 

Index: server/asobj/NetStreamFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.cpp,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -b -r1.24 -r1.25
--- server/asobj/NetStreamFfmpeg.cpp    23 Mar 2007 07:52:07 -0000      1.24
+++ server/asobj/NetStreamFfmpeg.cpp    28 Mar 2007 16:12:08 -0000      1.25
@@ -14,7 +14,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: NetStreamFfmpeg.cpp,v 1.24 2007/03/23 07:52:07 tgc Exp $ */
+/* $Id: NetStreamFfmpeg.cpp,v 1.25 2007/03/28 16:12:08 tgc Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -263,7 +263,7 @@
        // Pass stuff from/to the NetConnection object.
        assert(ns);
        if ( !nc->openConnection(ns->url.c_str(), ns) ) {
-               log_warning("Gnash could not open movie url: %s", 
ns->url.c_str());
+               log_warning("Gnash could not open movie: %s", ns->url.c_str());
                ns->set_status("NetStream.Buffer.StreamNotFound");
                return;
        }
@@ -279,7 +279,12 @@
                ns->m_isFLV = true;
 
                ns->m_parser = new FLVParser();
-               nc->connectParser(ns->m_parser);
+               if (!nc->connectParser(ns->m_parser)) {
+                       ns->set_status("NetStream.Buffer.StreamNotFound");
+                       log_warning("Gnash could not open movie: %s", 
ns->url.c_str());
+                       delete ns->m_parser;
+                       return;
+               }
 
                // Init the avdecoder-decoder
                avcodec_init();

Index: server/asobj/NetStreamGst.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamGst.cpp,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- server/asobj/NetStreamGst.cpp       23 Mar 2007 00:30:10 -0000      1.15
+++ server/asobj/NetStreamGst.cpp       28 Mar 2007 16:12:08 -0000      1.16
@@ -62,7 +62,6 @@
        pipeline(NULL),
        audiosink(NULL),
        videosink(NULL),
-       source(NULL),
        decoder(NULL),
        volume(NULL),
        colorspace(NULL),
@@ -70,6 +69,15 @@
        videocaps(NULL),
        videoflip(NULL),
        audioconv(NULL),
+
+       audiosource(NULL),
+       videosource(NULL),
+       source(NULL),
+       videodecoder(NULL),
+       audiodecoder(NULL),
+       videoinputcaps(NULL),
+       audioinputcaps(NULL),
+
        m_go(false),
        m_imageframe(NULL),
        startThread(NULL),
@@ -261,6 +269,37 @@
 }
 
 
+// The callback function which refills the audio buffer with data
+void NetStreamGst::audio_callback_handoff (GstElement * /*c*/, GstBuffer 
*buffer, GstPad* /*pad*/, gpointer user_data)
+{
+       NetStreamGst* ns = static_cast<NetStreamGst*>(user_data);
+
+       FLVFrame* frame = ns->m_parser->nextAudioFrame();
+       if (!frame) return;
+
+//     if (GST_BUFFER_DATA(buffer)) delete [] GST_BUFFER_DATA(buffer);
+       GST_BUFFER_SIZE(buffer) = frame->dataSize;
+       GST_BUFFER_DATA(buffer) = frame->data;
+       GST_BUFFER_TIMESTAMP(buffer) = frame->timestamp * 1000000;
+       delete frame;
+       return;
+
+}
+
+void NetStreamGst::video_callback_handoff (GstElement * /*c*/, GstBuffer 
*buffer, GstPad* /*pad*/, gpointer user_data)
+{
+       NetStreamGst* ns = static_cast<NetStreamGst*>(user_data);
+
+       FLVFrame* frame = ns->m_parser->nextVideoFrame();
+       if (!frame) return;
+
+//     if (GST_BUFFER_DATA(buffer)) delete [] GST_BUFFER_DATA(buffer);
+       GST_BUFFER_SIZE(buffer) = frame->dataSize;
+       GST_BUFFER_DATA(buffer) = frame->data;
+       GST_BUFFER_TIMESTAMP(buffer) = frame->timestamp * 1000000;
+       delete frame;
+       return;
+}
 void
 NetStreamGst::startPlayback(NetStreamGst* ns)
 {
@@ -270,17 +309,32 @@
        // Pass stuff from/to the NetConnection object.
        assert(ns);
        if ( !nc->openConnection(ns->url.c_str(), ns) ) {
-               log_warning("Gnash could not open movie url: %s", 
ns->url.c_str());
+               ns->set_status("NetStream.Play.StreamNotFound");
+               log_warning("Gnash could not open movie: %s", ns->url.c_str());
                return;
        }
 
        ns->inputPos = 0;
 
+       uint8_t head[3];
+       if (nc->read(head,3) < 3) return;
+       nc->seek(0);
+       if (head[0] == 'F'|| head[1] == 'L' || head[2] == 'V') { 
+               ns->m_isFLV = true;
+               ns->m_parser = new FLVParser();
+               if (!nc->connectParser(ns->m_parser)) {
+                       ns->set_status("NetStream.Play.StreamNotFound");
+                       log_warning("Gnash could not open movie: %s", 
ns->url.c_str());
+                       return;
+                       
+               }
+       }
+
        // init GStreamer
        gst_init (NULL, NULL);
 
-       // setup the GnashNC plugin
-       _gst_plugin_register_static (&gnash_plugin_desc);
+       // setup the GnashNC plugin if we are not decoding FLV
+       if (!ns->m_isFLV) _gst_plugin_register_static (&gnash_plugin_desc);
 
        // setup the pipeline
        ns->pipeline = gst_pipeline_new (NULL);
@@ -324,33 +378,113 @@
                return;
        }
 
-       gst_bin_add_many (GST_BIN (ns->pipeline),ns->audiosink, ns->audioconv, 
NULL);
-
-       // setup gnashnc source (our homegrown source element)
+       // setup gnashnc source if we are not decoding FLV (our homegrown 
source element)
+       if (!ns->m_isFLV) {
        ns->source = gst_element_factory_make ("gnashsrc", NULL);
        gnashsrc_callback* gc = new gnashsrc_callback;
        gc->read = NetStreamGst::readPacket;
        gc->seek = NetStreamGst::seekMedia;
        g_object_set (G_OBJECT (ns->source), "data", ns, "callbacks", gc, NULL);
+       } else {
+
+               FLVVideoInfo* videoInfo = ns->m_parser->getVideoInfo();
+               FLVAudioInfo* audioInfo = ns->m_parser->getAudioInfo();
+
+               ns->audiosource = gst_element_factory_make ("fakesrc", NULL);
+               ns->videosource = gst_element_factory_make ("fakesrc", NULL);
+               
+               // setup fake sources
+               g_object_set (G_OBJECT (ns->audiosource),
+                                       "sizetype", 2, "can-activate-pull", 
FALSE, "signal-handoffs", TRUE, NULL);
+               g_object_set (G_OBJECT (ns->videosource),
+                                       "sizetype", 2, "can-activate-pull", 
FALSE, "signal-handoffs", TRUE, NULL);
+
+               // Setup the callbacks
+               g_signal_connect (ns->audiosource, "handoff", G_CALLBACK 
(NetStreamGst::audio_callback_handoff), ns);
+               g_signal_connect (ns->videosource, "handoff", G_CALLBACK 
(NetStreamGst::video_callback_handoff), ns);
+
+               // Setup the input capsfilter
+               ns->videoinputcaps = gst_element_factory_make ("capsfilter", 
NULL);
+               uint32_t fps = ns->m_parser->videoFrameRate(); 
+
+               GstCaps* videonincaps;
+               if (videoInfo->codec == VIDEO_CODEC_H263) {
+                       videonincaps = gst_caps_new_simple 
("video/x-flash-video",
+                               "width", G_TYPE_INT, videoInfo->width,
+                               "height", G_TYPE_INT, videoInfo->height,
+                               "framerate", GST_TYPE_FRACTION, fps, 1,
+                               "flvversion", G_TYPE_INT, 1,
+                               NULL);
+                       ns->videodecoder = gst_element_factory_make 
("ffdec_flv", NULL);
+               } else if (videoInfo->codec == VIDEO_CODEC_VP6) {
+                       videonincaps = gst_caps_new_simple ("video/x-vp6-flash",
+                               "width", G_TYPE_INT, 320, // We don't yet have 
a size extract for this codec, so we guess...
+                               "height", G_TYPE_INT, 240,
+                               "framerate", GST_TYPE_FRACTION, fps, 1,
+                               NULL);
+                       ns->videodecoder = gst_element_factory_make 
("ffdec_vp6f", NULL);
+               } else if (videoInfo->codec == VIDEO_CODEC_SCREENVIDEO) {
+                       videonincaps = gst_caps_new_simple 
("video/x-flash-screen",
+                               "width", G_TYPE_INT, 320, // We don't yet have 
a size extract for this codec, so we guess...
+                               "height", G_TYPE_INT, 240,
+                               "framerate", GST_TYPE_FRACTION, fps, 1,
+                               NULL);
+                       ns->videodecoder = gst_element_factory_make 
("ffdec_flashsv", NULL);
+               } else {
+                       assert(0);
+               }
 
+               g_object_set (G_OBJECT (ns->videoinputcaps), "caps", 
videonincaps, NULL);
+               gst_caps_unref (videonincaps);
 
-       // setup the decoder with callback
+               if (audioInfo->codec == AUDIO_CODEC_MP3) { 
+
+                       ns->audiodecoder = gst_element_factory_make ("mad", 
NULL);
+                       if (ns->audiodecoder == NULL) {
+                               ns->audiodecoder = gst_element_factory_make 
("flump3dec", NULL);
+                               if (ns->audiodecoder != NULL && 
!gst_default_registry_check_feature_version("flump3dec", 0, 10, 4)) {
+                                       log_warning("This version of fluendos 
mp3 plugin does not support flash streaming sounds, please upgrade to version 
0.10.4 or higher.");
+                               }
+                       }
+                       // Check if the element was correctly created
+                       if (!ns->audiodecoder) {
+                               log_error("A gstreamer mp3-decoder element 
could not be created! You probably need to install a mp3-decoder plugin like 
gstreamer0.10-mad or gstreamer0.10-fluendo-mp3.");
+                               return;
+                       }
+
+                       // Set the info about the stream so that gstreamer 
knows what it is.
+                       ns->audioinputcaps = gst_element_factory_make 
("capsfilter", NULL);
+                       GstCaps* audioincaps = gst_caps_new_simple 
("audio/mpeg",
+                               "mpegversion", G_TYPE_INT, 1,
+                               "layer", G_TYPE_INT, 3,
+                               "rate", G_TYPE_INT, audioInfo->sampleRate,
+                               "channels", G_TYPE_INT, audioInfo->stereo ? 2 : 
1, NULL);
+                       g_object_set (G_OBJECT (ns->audioinputcaps), "caps", 
audioincaps, NULL);
+                       gst_caps_unref (audioincaps);
+               } else {
+                       assert(0);
+               }
+       }
+
+       // setup the decoder with callback, but only if we are not decoding a 
FLV
+       if (!ns->m_isFLV) {
        ns->decoder = gst_element_factory_make ("decodebin", NULL);
        g_signal_connect (ns->decoder, "new-decoded-pad", G_CALLBACK 
(NetStreamGst::callback_newpad), ns);
+       }
 
        // setup the video colorspaceconverter converter
        ns->colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
 
        // Setup the capsfilter which demands either YUV or RGB videoframe 
format
        ns->videocaps = gst_element_factory_make ("capsfilter", NULL);
-       GstCaps* caps;
+       GstCaps* videooutcaps;
        if (gnash::render::videoFrameFormat() == render::YUV) {
-               caps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
+               videooutcaps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
        } else {
-               caps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
+               videooutcaps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
        }
-       g_object_set (G_OBJECT (ns->videocaps), "caps", caps, NULL);
-       gst_caps_unref (caps);
+       g_object_set (G_OBJECT (ns->videocaps), "caps", videooutcaps, NULL);
+       gst_caps_unref (videooutcaps);
 
        // Setup the videorate element which makes sure the frames are 
delivered on time.
        ns->videorate = gst_element_factory_make ("videorate", NULL);
@@ -360,23 +494,39 @@
        g_object_set (G_OBJECT (ns->videosink), "signal-handoffs", TRUE, 
"sync", TRUE, NULL);
        g_signal_connect (ns->videosink, "handoff", G_CALLBACK 
(NetStreamGst::callback_output), ns);
 
-       if (!ns->source || !ns->decoder || !ns->colorspace || !ns->videocaps || 
!ns->videorate || !ns->videosink) {
+       if (!ns->colorspace || !ns->videocaps || !ns->videorate || 
!ns->videosink) {
                gnash::log_error("Gstreamer element(s) for video movie handling 
could not be created\n");
                return;
        }
 
-       // put it all in the pipeline
-       gst_bin_add_many (GST_BIN (ns->pipeline), ns->source, ns->decoder, 
ns->colorspace, ns->videosink, ns->videorate, ns->videocaps, ns->volume, NULL);
+       // put it all in the pipeline and link the elements
+       if (!ns->m_isFLV) { 
+               gst_bin_add_many (GST_BIN (ns->pipeline),ns->audiosink, 
ns->audioconv, NULL);
+               gst_bin_add_many (GST_BIN (ns->pipeline), ns->source, 
ns->decoder, ns->colorspace, 
+                       ns->videosink, ns->videorate, ns->videocaps, 
ns->volume, NULL);
 
-       // link the elements
        gst_element_link(ns->source, ns->decoder);
        gst_element_link_many(ns->colorspace, ns->videocaps, ns->videorate, 
ns->videosink, NULL);
-
        gst_element_link_many(ns->audioconv, ns->volume, ns->audiosink, NULL);
        
+       } else {
+               gst_bin_add_many (GST_BIN (ns->pipeline), ns->videosource, 
ns->videoinputcaps, ns->videodecoder, ns->colorspace, ns->videocaps, 
ns->videorate, ns->videosink, NULL);
+               gst_bin_add_many (GST_BIN (ns->pipeline), ns->audiosource, 
ns->audioinputcaps, ns->audiodecoder, ns->audioconv, ns->volume, ns->audiosink, 
NULL);
+
+               gst_element_link_many(ns->audiosource, ns->audioinputcaps, 
ns->audiodecoder, ns->audioconv, ns->volume, ns->audiosink, NULL);
+               gst_element_link_many(ns->videosource, ns->videoinputcaps, 
ns->videodecoder, ns->colorspace, ns->videocaps, ns->videorate, ns->videosink, 
NULL);
+
+       }
+
        // start playing        
-       gst_element_set_state (ns->pipeline, GST_STATE_PLAYING);
+       if (!ns->m_isFLV) {
+               gst_element_set_state (GST_ELEMENT (ns->pipeline), 
GST_STATE_PLAYING);
+       } else {
+               gst_element_set_state (GST_ELEMENT (ns->pipeline), 
GST_STATE_PAUSED);
+               ns->m_pause = true;
+       }
 
+       ns->set_status("NetStream.Play.Start");
        return;
 }
 
@@ -388,12 +538,26 @@
 void
 NetStreamGst::seek(double pos)
 {
+
+       if (m_isFLV) {
+               uint32_t newpos = 
m_parser->seek(static_cast<uint32_t>(pos*1000))/1000;
+               /*if (!gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, 
GST_SEEK_FLAG_FLUSH,
+                       GST_SEEK_TYPE_SET, GST_SECOND * 
static_cast<long>(newpos),
+                       GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
+                       log_warning("Seek failed");
+                       set_status("NetStream.Seek.InvalidTime");
+                       return;
+               }*/
+       } else {
        if (!gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, 
GST_SEEK_FLAG_FLUSH,
                GST_SEEK_TYPE_SET, GST_SECOND * static_cast<long>(pos),
                GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
                log_warning("Seek failed");
+                       set_status("NetStream.Seek.InvalidTime");
+                       return;
        }
-
+       }
+       set_status("NetStream.Seek.Notify");
 }
 
 void
@@ -406,11 +570,12 @@
 void
 NetStreamGst::advance()
 {
-/*     if (m_go && m_pause && !m_imageframe && m_parser && 
m_parser->isTimeLoaded(m_bufferTime)) {
+       if (m_isFLV && m_pause && m_go && !m_imageframe && m_parser && 
m_parser->isTimeLoaded(m_bufferTime)) {
                set_status("NetStream.Buffer.Full");
                m_pause = false;
+               gst_element_set_state (GST_ELEMENT (pipeline), 
GST_STATE_PLAYING);
        }
-*/
+
        if (m_statusChanged) {
 /*             fn_call dummy(NULL, NULL, 0, 0);
                as_value info_asv(infoobject_new(dummy));

Index: server/asobj/NetStreamGst.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamGst.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- server/asobj/NetStreamGst.h 23 Mar 2007 00:30:10 -0000      1.9
+++ server/asobj/NetStreamGst.h 28 Mar 2007 16:12:08 -0000      1.10
@@ -33,6 +33,7 @@
 #include <gst/gst.h>
 #include "image.h"
 #include "NetStream.h" // for inheritance
+#include "FLVParser.h"
 
 namespace gnash {
   
@@ -69,6 +70,9 @@
        static void startPlayback(NetStreamGst* ns);
        static void callback_output (GstElement* /*c*/, GstBuffer *buffer, 
GstPad* /*pad*/, gpointer user_data);
        static void callback_newpad (GstElement *decodebin, GstPad *pad, 
gboolean last, gpointer data);
+       static void video_callback_handoff (GstElement* /*c*/, GstBuffer 
*buffer, GstPad* /*pad*/, gpointer user_data);
+       static void audio_callback_handoff (GstElement* /*c*/, GstBuffer 
*buffer, GstPad* /*pad*/, gpointer user_data);
+
 private:
 
        bool _bufferLength;
@@ -83,7 +87,6 @@
        GstElement *pipeline;
        GstElement *audiosink;
        GstElement *videosink;
-       GstElement *source;
        GstElement *decoder;
        GstElement *volume;
        GstElement *colorspace;
@@ -92,6 +95,15 @@
        GstElement *videoflip;
        GstElement *audioconv;
 
+       // used only for FLV
+       GstElement *audiosource;
+       GstElement *videosource;
+       GstElement *source;
+       GstElement *videodecoder;
+       GstElement *audiodecoder;
+       GstElement *videoinputcaps;
+       GstElement *audioinputcaps;
+
        // Are the playing loop running or not
        volatile bool m_go;
 
@@ -122,6 +134,11 @@
        // The handler which is invoked on status change
        boost::intrusive_ptr<as_function> m_statusHandler;
 
+       // Are we decoding a FLV?
+       bool m_isFLV;
+
+       // The parser for FLV
+       FLVParser* m_parser;
 };
 
 } // gnash namespace




reply via email to

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