[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash ChangeLog backend/sound_handler_gst.cpp l...,
Tomas Groth <=