[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog libmedia/FLVParser.cpp libmedia...
From: |
Tomas Groth |
Subject: |
[Gnash-commit] gnash ChangeLog libmedia/FLVParser.cpp libmedia... |
Date: |
Fri, 30 Nov 2007 00:13:03 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Tomas Groth <tgc> 07/11/30 00:13:02
Modified files:
. : ChangeLog
libmedia : FLVParser.cpp FLVParser.h Makefile.am
MediaBuffer.h MediaDecoder.h MediaParser.h
sound_handler.h
libmedia/gst : VideoDecoderGst.cpp VideoDecoderGst.h
sound_handler_gst.cpp sound_handler_gst.h
libmedia/sdl : AudioDecoderFfmpeg.cpp MediaDecoderSdl.cpp
MediaDecoderSdl.h MediaParserFfmpeg.cpp
MediaParserFfmpeg.h sound_handler_sdl.h
Added files:
libmedia/gst : AudioDecoderGst.cpp AudioDecoderGst.h
MediaDecoderGst.cpp MediaDecoderGst.h
Log message:
* libmedia/Makefile.am: Added new files.
* libmedia/FLVParser.{h,cpp}: Use a shared pointer for the
tu_file stream.
* libmedia/MediaBuffer.h: Changed from using a combined
audio-video
container, to seperate containers.
* libmedia/MediaDecoder.{cpp,h}: Split into a header and source
file. Move
shared code to MediaDecoder.cpp.
* libmedia/MediaParser.h: Use a shared pointer for the tu_file
stream.
* libmedia/sound_handler.h: Removed duplicate code.
* libmedia/gst/VideoDecoderGst.{cpp,h}: Updated to changed API.
* libmedia/gst/sound_handler_gst.{h,cpp}: Initial code for
callbacks.
* libmedia/sdl/AudioDecoderFfmpeg.cpp: Free at the right
point(?)
* libmedia/sdl/MediaDecoderSdl.{cpp,h}: Moved shared code to
MediaDecoder.cpp.
* libmedia/sdl/MediaParserFfmpeg.{h,cpp}: Use a shared pointer
for the tu_file stream.
* libmedia/sdl/sound_handler_sdl.h: Updated some comments.
* libmedia/gst/AudioDecoderGst.{cpp,h}: Added. Implements the
audiodecoder
used by GST when playing FLVs.
* libmedia/gst/MediaDecoderGst.{cpp,h}: Added. Implements the
MediaDecoder
used when playing movies and sounds. Doesn't work. Should not
be far from
playing FLVs.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5021&r2=1.5022
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/FLVParser.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/FLVParser.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/Makefile.am?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/MediaBuffer.h?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/MediaDecoder.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/MediaParser.h?cvsroot=gnash&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sound_handler.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/VideoDecoderGst.cpp?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/VideoDecoderGst.h?cvsroot=gnash&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/sound_handler_gst.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/sound_handler_gst.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/AudioDecoderGst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/AudioDecoderGst.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/MediaDecoderGst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/MediaDecoderGst.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/AudioDecoderFfmpeg.cpp?cvsroot=gnash&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/MediaDecoderSdl.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/MediaDecoderSdl.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/MediaParserFfmpeg.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/MediaParserFfmpeg.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sdl/sound_handler_sdl.h?cvsroot=gnash&r1=1.4&r2=1.5
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.5021
retrieving revision 1.5022
diff -u -b -r1.5021 -r1.5022
--- ChangeLog 29 Nov 2007 23:48:33 -0000 1.5021
+++ ChangeLog 30 Nov 2007 00:13:00 -0000 1.5022
@@ -1,3 +1,25 @@
+2007-11-29 Tomas Groth Christensen <address@hidden>
+
+ * libmedia/Makefile.am: Added new files.
+ * libmedia/FLVParser.{h,cpp}: Use a shared pointer for the tu_file
stream.
+ * libmedia/MediaBuffer.h: Changed from using a combined audio-video
+ container, to seperate containers.
+ * libmedia/MediaDecoder.{cpp,h}: Split into a header and source file.
Move
+ shared code to MediaDecoder.cpp.
+ * libmedia/MediaParser.h: Use a shared pointer for the tu_file stream.
+ * libmedia/sound_handler.h: Removed duplicate code.
+ * libmedia/gst/VideoDecoderGst.{cpp,h}: Updated to changed API.
+ * libmedia/gst/sound_handler_gst.{h,cpp}: Initial code for callbacks.
+ * libmedia/sdl/AudioDecoderFfmpeg.cpp: Free at the right point(?)
+ * libmedia/sdl/MediaDecoderSdl.{cpp,h}: Moved shared code to
MediaDecoder.cpp.
+ * libmedia/sdl/MediaParserFfmpeg.{h,cpp}: Use a shared pointer for the
tu_file stream.
+ * libmedia/sdl/sound_handler_sdl.h: Updated some comments.
+ * libmedia/gst/AudioDecoderGst.{cpp,h}: Added. Implements the
audiodecoder
+ used by GST when playing FLVs.
+ * libmedia/gst/MediaDecoderGst.{cpp,h}: Added. Implements the
MediaDecoder
+ used when playing movies and sounds. Doesn't work. Should not be far
from
+ playing FLVs.
+
2007-11-29 Bastiaan Jacques <address@hidden>
* backend/render_handler_ogl.cpp: Remove line styles from masks.
Index: libmedia/FLVParser.cpp
===================================================================
RCS file: /sources/gnash/gnash/libmedia/FLVParser.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libmedia/FLVParser.cpp 24 Nov 2007 17:21:42 -0000 1.2
+++ libmedia/FLVParser.cpp 30 Nov 2007 00:13:00 -0000 1.3
@@ -17,11 +17,12 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-// $Id: FLVParser.cpp,v 1.2 2007/11/24 17:21:42 strk Exp $
+// $Id: FLVParser.cpp,v 1.3 2007/11/30 00:13:00 tgc Exp $
#include "FLVParser.h"
#include "amf.h"
#include "log.h"
+#include "BitsReader.h"
#define PADDING_BYTES 8
@@ -31,7 +32,7 @@
namespace gnash {
namespace media {
-FLVParser::FLVParser(tu_file* stream)
+FLVParser::FLVParser(boost::shared_ptr<tu_file> stream)
:
MediaParser(stream),
_lastParsedPosition(0),
@@ -171,9 +172,9 @@
frame->dataSize = _audioFrames[_nextAudioFrame]->dataSize;
frame->timestamp = _audioFrames[_nextAudioFrame]->timestamp;
-
_stream->set_position(_audioFrames[_nextAudioFrame]->dataPosition);
//_lt.seek(_audioFrames[_nextAudioFrame]->dataPosition);
+
_stream->set_position(_audioFrames[_nextAudioFrame]->dataPosition);
frame->data = new uint8_t[frame->dataSize + PADDING_BYTES];
- size_t bytesread = _stream->read_bytes(frame->data,
frame->dataSize); //_lt.read(frame->data, frame->dataSize);
+ size_t bytesread = _stream->read_bytes(frame->data,
frame->dataSize);
memset(frame->data + bytesread, 0, PADDING_BYTES);
frame->tag = 8;
@@ -186,9 +187,9 @@
frame->dataSize = _videoFrames[_nextVideoFrame]->dataSize;
frame->timestamp = _videoFrames[_nextVideoFrame]->timestamp;
-
_stream->set_position(_videoFrames[_nextVideoFrame]->dataPosition);
//_lt.seek(_videoFrames[_nextVideoFrame]->dataPosition);
+
_stream->set_position(_videoFrames[_nextVideoFrame]->dataPosition);
frame->data = new uint8_t[frame->dataSize + PADDING_BYTES];
- size_t bytesread = _stream->read_bytes(frame->data,
frame->dataSize); //_lt.read(frame->data, frame->dataSize);
+ size_t bytesread = _stream->read_bytes(frame->data,
frame->dataSize);
memset(frame->data + bytesread, 0, PADDING_BYTES);
frame->tag = 9;
@@ -218,10 +219,10 @@
frame->timestamp = _audioFrames[_nextAudioFrame]->timestamp;
frame->tag = 8;
- _stream->set_position(_audioFrames[_nextAudioFrame]->dataPosition);
//_lt.seek(_audioFrames[_nextAudioFrame]->dataPosition);
+ _stream->set_position(_audioFrames[_nextAudioFrame]->dataPosition);
frame->data = new uint8_t[_audioFrames[_nextAudioFrame]->dataSize +
PADDING_BYTES];
- size_t bytesread = _stream->read_bytes(frame->data,
_audioFrames[_nextAudioFrame]->dataSize); //_lt.read(frame->data,
_audioFrames[_nextAudioFrame]->dataSize);
+ size_t bytesread = _stream->read_bytes(frame->data,
_audioFrames[_nextAudioFrame]->dataSize);
memset(frame->data + bytesread, 0, PADDING_BYTES);
_nextAudioFrame++;
@@ -259,10 +260,10 @@
frame->timestamp = _videoFrames[_nextVideoFrame]->timestamp;
frame->tag = 9;
- _stream->set_position(_videoFrames[_nextVideoFrame]->dataPosition);
//_lt.seek(_videoFrames[_nextVideoFrame]->dataPosition);
+ _stream->set_position(_videoFrames[_nextVideoFrame]->dataPosition);
frame->data = new uint8_t[_videoFrames[_nextVideoFrame]->dataSize +
PADDING_BYTES];
- size_t bytesread = _stream->read_bytes(frame->data,
_videoFrames[_nextVideoFrame]->dataSize); //_lt.read(frame->data,
_videoFrames[_nextVideoFrame]->dataSize);
+ size_t bytesread = _stream->read_bytes(frame->data,
_videoFrames[_nextVideoFrame]->dataSize);
memset(frame->data + bytesread, 0, PADDING_BYTES);
_nextVideoFrame++;
@@ -520,36 +521,29 @@
return time;
}
+#define HEADER_SKIP 15
+
bool FLVParser::parseNextFrame()
{
// Parse the header if not done already. If unsuccesfull return false.
if (_lastParsedPosition == 0 && !parseHeader()) return false;
- // Check if there is enough data to parse the header of the frame
- //if (!_lt.isPositionConfirmed(_lastParsedPosition+14)) return false;
-
// Seek to next frame and skip the size of the last tag,
// return false on error
if (_stream->set_position(_lastParsedPosition+4) != 0) return false;
- //_lt.seek(_lastParsedPosition+4);
// Read the tag info
uint8_t tag[12];
_stream->read_bytes(tag, 12);
- //_lt.read(tag, 12);
// Extract length and timestamp
uint32_t bodyLength = getUInt24(&tag[1]);
uint32_t timestamp = getUInt24(&tag[4]);
- // Check if there is enough data to parse the body of the frame
- //if (!_lt.isPositionConfirmed(_lastParsedPosition+15+bodyLength))
return false;
- /*if (_stream->set_position(_lastParsedPosition+15+bodyLength) != 0)
return false;*/
- //_stream->set_position(_lastParsedPosition + HEADER_SKIP + bodyLength);
+ _lastParsedPosition += HEADER_SKIP + bodyLength;
// check for empty tag
if (bodyLength == 0) {
- _lastParsedPosition += HEADER_SKIP + bodyLength;
return true;
}
@@ -557,9 +551,8 @@
FLVAudioFrame* frame = new FLVAudioFrame;
frame->dataSize = bodyLength - 1;
frame->timestamp = timestamp;
- frame->dataPosition = _lastParsedPosition + HEADER_SKIP + 1; //
_stream->get_position(); //_lt.tell();
+ frame->dataPosition = _stream->get_position();
_audioFrames.push_back(frame);
-//log_debug("audio tag, timestamp: %d", timestamp);
// If this is the first audioframe no info about the
// audio format has been noted, so we do that now
@@ -576,17 +569,15 @@
_audioInfo.reset(new
AudioInfo(static_cast<audioCodecType>((tag[11] & 0xf0) >> 4), samplerate,
samplesize, (tag[11] & 0x01) >> 0, 0, FLASH));
}
- _lastParsedPosition += HEADER_SKIP + bodyLength;
} else if (tag[0] == VIDEO_TAG) {
FLVVideoFrame* frame = new FLVVideoFrame;
frame->dataSize = bodyLength - 1;
frame->timestamp = timestamp;
- frame->dataPosition = _lastParsedPosition + HEADER_SKIP + 1;
//_stream->get_position(); //_lt.tell();
+ frame->dataPosition = _stream->get_position();
frame->frameType = (tag[11] & 0xf0) >> 4;
_videoFrames.push_back(frame);
-//log_debug("video tag, timestamp: %d", timestamp);
// If this is the first videoframe no info about the
// video format has been noted, so we do that now
@@ -597,11 +588,11 @@
uint16_t height = 240;
// Extract the video size from the videodata header
- if (codec == VIDEO_CODEC_H263) {
- _stream->set_position(frame->dataPosition);
//_lt.seek(frame->dataPosition);
+ _stream->set_position(frame->dataPosition);
uint8_t videohead[12];
- _stream->read_bytes(videohead, 12);
//_lt.read(videohead, 12);
+ _stream->read_bytes(videohead, 12);
+ if (codec == VIDEO_CODEC_H263) {
bool sizebit1 = (videohead[3] & 0x02);
bool sizebit2 = (videohead[3] & 0x01);
bool sizebit3 = (videohead[4] & 0x80);
@@ -623,37 +614,58 @@
width = 160;
height = 120;
- // Then the custom sizes (1 byte - untested and
ugly)
+ // Then the custom sizes (1 byte)
} 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);
+ BitsReader* br = new
BitsReader(&videohead[4], 8);
+ br->read_bit();
+ width = br->read_uint(8);
+ height = br->read_uint(8);
+ delete br;
- 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)
+ // Then the custom sizes (2 byte)
} 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);
- }
+ BitsReader* br = new
BitsReader(&videohead[4], 8);
+ br->read_bit();
+ width = br->read_uint(16);
+ height = br->read_uint(16);
+ delete br;
+ }
+ } else if (codec == VIDEO_CODEC_VP6) {
+ if (!(videohead[0] & 0x80)) {
+ uint32_t index = 0;
+ if ((videohead[index] & 1) ||
!(videohead[index+1] & 0x06)) {
+ index += 2;
+ }
+ index += 2;
+ width = videohead[index++] * 16;
+ height = videohead[index] * 16;
+
+ }
+ } else if (codec == VIDEO_CODEC_SCREENVIDEO) {
+ BitsReader* br = new BitsReader(&videohead[0],
12);
+ br->read_uint(4);
+ width = br->read_uint(12);
+ br->read_uint(4);
+ height = br->read_uint(12);
+ delete br;
}
+
// Create the videoinfo
_videoInfo.reset(new VideoInfo(codec, width, height, 0
/*frameRate*/, 0 /*duration*/, FLASH));
}
- _lastParsedPosition += HEADER_SKIP + bodyLength;
} else if (tag[0] == META_TAG) {
-//log_debug("meta tag");
+ //log_debug("meta tag");
// Extract information from the meta tag
/*_lt.seek(_lastParsedPosition+16);
char* metaTag = new char[bodyLength];
_lt.read(metaTag, bodyLength);
amf::AMF* amfParser = new amf::AMF();
amfParser->parseAMF(metaTag);*/
- _lastParsedPosition += HEADER_SKIP + bodyLength;
} else {
-log_debug("no tag - the end?");
+ //log_debug("no tag - the end?");
// We can't be sure that the parsing is really complete,
// maybe it's a corrupt FLV.
_parsingComplete = true;
Index: libmedia/FLVParser.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/FLVParser.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- libmedia/FLVParser.h 24 Nov 2007 17:21:42 -0000 1.3
+++ libmedia/FLVParser.h 30 Nov 2007 00:13:01 -0000 1.4
@@ -17,7 +17,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-// $Id: FLVParser.h,v 1.3 2007/11/24 17:21:42 strk Exp $
+// $Id: FLVParser.h,v 1.4 2007/11/30 00:13:01 tgc Exp $
// Information about the FLV format can be found at http://osflash.org/flv
@@ -29,8 +29,6 @@
#include <boost/thread/mutex.hpp>
#include "MediaParser.h"
-#define HEADER_SKIP 15
-
namespace gnash {
namespace media {
@@ -91,7 +89,7 @@
/// tu_file to use for input.
/// Ownership left to the caller.
///
- FLVParser(tu_file* stream);
+ FLVParser(boost::shared_ptr<tu_file> stream);
/// Kills the parser...
~FLVParser();
Index: libmedia/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/libmedia/Makefile.am,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- libmedia/Makefile.am 29 Nov 2007 20:45:01 -0000 1.5
+++ libmedia/Makefile.am 30 Nov 2007 00:13:01 -0000 1.6
@@ -77,6 +77,7 @@
FLVParser.cpp \
AudioDecoderNellymoser.cpp \
AudioDecoderSimple.cpp \
+ MediaDecoder.cpp \
$(NULL)
noinst_HEADERS = \
@@ -94,9 +95,9 @@
if USE_SOUND_GST
-#libgnashmedia_la_SOURCES += gst/gstgnashsrc.c gst/VideoDecoderGst.cpp
gst/gstappbuffer.c gst/gstappsink.c gst/gstappsrc.c gst/sound_handler_gst.cpp
+#libgnashmedia_la_SOURCES += gst/gstgnashsrc.c gst/VideoDecoderGst.cpp
gst/AudioDecoderGst.cpp gst/gstappbuffer.c gst/gstappsink.c gst/gstappsrc.c
gst/sound_handler_gst.cpp
libgnashmedia_la_SOURCES += gst/VideoDecoderGst.cpp gst/sound_handler_gst.cpp
gst/gstgnashsrc.c
-#noinst_HEADERS += gst/gstgnashsrc.h gst/gstappbuffer.h gst/VideoDecoderGst.h
gst/gstappsink.h gst/gstappsrc.h gst/sound_handler_gst.h
+#noinst_HEADERS += gst/gstgnashsrc.h gst/gstappbuffer.h gst/AudioDecoderGst.h
gst/VideoDecoderGst.h gst/gstappsink.h gst/gstappsrc.h gst/sound_handler_gst.h
noinst_HEADERS += gst/VideoDecoderGst.h gst/sound_handler_gst.h
gst/gstgnashsrc.h
libgnashmedia_la_CPPFLAGS += $(GSTREAMER_CFLAGS)
libgnashmedia_la_LIBADD += $(GSTREAMER_LIBS) -lgstbase-0.10
Index: libmedia/MediaBuffer.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/MediaBuffer.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- libmedia/MediaBuffer.h 29 Nov 2007 20:45:01 -0000 1.5
+++ libmedia/MediaBuffer.h 30 Nov 2007 00:13:01 -0000 1.6
@@ -16,25 +16,25 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-// $Id: MediaBuffer.h,v 1.5 2007/11/29 20:45:01 bwy Exp $
+// $Id: MediaBuffer.h,v 1.6 2007/11/30 00:13:01 tgc Exp $
#ifndef __MEDIABUFFER_H__
#define __MEDIABUFFER_H__
#include <boost/thread/mutex.hpp>
#include <queue>
+#include "image.h"
namespace gnash {
namespace media {
-/// This class is used to store decoded video or audio data
+/// This class is used to store decoded audio data
/// while it is in the MediaBuffer.
-class raw_mediadata_t
+class raw_audiodata_t
{
public:
- raw_mediadata_t():
- //m_stream_index(-1),
+ raw_audiodata_t():
m_size(0),
m_data(NULL),
m_ptr(NULL),
@@ -42,7 +42,7 @@
{
}
- ~raw_mediadata_t()
+ ~raw_audiodata_t()
{
if (m_data) delete [] m_data;
}
@@ -63,6 +63,28 @@
uint32_t m_pts;
};
+/// This class is used to store decoded video data
+/// while it is in the MediaBuffer.
+class raw_videodata_t
+{
+public:
+ raw_videodata_t():
+ image(NULL),
+ timestamp(0)
+ {
+ }
+
+ ~raw_videodata_t()
+ {
+ }
+
+ /// Pointer to the data. The data is owned by this class.
+ std::auto_ptr<image::image_base> image;
+
+ /// Timestamp in millisec
+ uint32_t timestamp;
+};
+
/// Threadsafe elements-owning queue
//
/// This class is a threadsafe queue, using std:queue and locking.
@@ -106,7 +128,7 @@
/// @param member
/// The element to be pushed unto the audio queue.
///
- void pushAudio(raw_mediadata_t* member) {
+ void pushAudio(raw_audiodata_t* member) {
boost::mutex::scoped_lock lock(_mutex);
audioQueue.push(member);
}
@@ -116,7 +138,7 @@
/// @param member
/// The element to be pushed unto the video queue.
///
- void pushVideo(raw_mediadata_t* member) {
+ void pushVideo(raw_videodata_t* member) {
boost::mutex::scoped_lock lock(_mutex);
videoQueue.push(member);
}
@@ -127,7 +149,7 @@
///
/// @return a pointer to the first element on the audio queue, NULL if
queue is empty.
///
- raw_mediadata_t* audioFront() {
+ raw_audiodata_t* audioFront() {
boost::mutex::scoped_lock lock(_mutex);
if (audioQueue.empty()) return NULL;
return audioQueue.front();
@@ -139,7 +161,7 @@
///
/// @return a pointer to the first element on the video queue, NULL if
queue is empty.
///
- raw_mediadata_t* videoFront() {
+ raw_videodata_t* videoFront() {
boost::mutex::scoped_lock lock(_mutex);
if (videoQueue.empty()) return NULL;
return videoQueue.front();
@@ -201,12 +223,11 @@
/// Gets the real size of the buffer in milliseconds. The size of
/// the audio and video buffer is compared and the biggest is returned.
Locks.
//
- /// @return the real size of the buffer in milliseconds.
+ /// @return the current size of the buffer in milliseconds.
///
uint32_t getBufferTime() {
boost::mutex::scoped_lock lock(_mutex);
- bool ret = calcBufferTime();
- return ret;
+ return calcBufferTime();
}
/// Checks if the contents of the buffer span a timeframe larger than
@@ -238,7 +259,7 @@
// Get the size of video buffer, and use that if it is bigger
than
// the vaule from the audio buffer.
if (!videoQueue.empty()) {
- uint32_t vSize = videoQueue.back()->m_pts -
videoQueue.front()->m_pts;
+ uint32_t vSize = videoQueue.back()->timestamp -
videoQueue.front()->timestamp;
if (vSize > size) size = vSize;
}
return size;
@@ -249,8 +270,8 @@
boost::mutex _mutex;
/// The queues of audio and video data.
- std::queue <raw_mediadata_t*> audioQueue;
- std::queue <raw_mediadata_t*> videoQueue;
+ std::queue <raw_audiodata_t*> audioQueue;
+ std::queue <raw_videodata_t*> videoQueue;
/// The requested size of the buffer in milliseconds
uint32_t _bufferTime;
Index: libmedia/MediaDecoder.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/MediaDecoder.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libmedia/MediaDecoder.h 24 Nov 2007 17:21:42 -0000 1.4
+++ libmedia/MediaDecoder.h 30 Nov 2007 00:13:01 -0000 1.5
@@ -16,7 +16,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: MediaDecoder.h,v 1.4 2007/11/24 17:21:42 strk Exp $
+// $Id: MediaDecoder.h,v 1.5 2007/11/30 00:13:01 tgc Exp $
#ifndef __MEDIADECODER_H__
#define __MEDIADECODER_H__
@@ -25,11 +25,14 @@
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
+#include <boost/shared_ptr.hpp>
#include <vector>
#include "MediaBuffer.h"
#include "MediaParser.h"
#include "FLVParser.h"
+#include "AudioDecoder.h"
+#include "VideoDecoder.h"
#include "log.h"
#ifdef HAVE_CONFIG_H
@@ -39,23 +42,8 @@
namespace gnash {
namespace media {
-
-/// \brief
-/// The MediaDecoder class decodes media data and puts it on a given buffer.
-///
-/// We need to be able to handle event stuff, so we store the events that
-/// need to be handled, and then NetStream can ask for it on ::advance()
-/// or whenever it is appropriate. Eventhandling is different from AS2 to AS3,
-/// but in this first draft only AS2 will be supported.
-///
-class MediaDecoder
-{
-
-public:
- /// Status codes used for NetStream onStatus notifications
- // Copied from NetSteam.h, so it should be updated it the orginal
- // is changed.
- enum StatusCode {
+/// Status codes used for NetStream onStatus notifications
+enum StatusCode {
// Internal status, not a valid ActionScript value
invalidStatus,
@@ -83,8 +71,20 @@
/// NetStream.Seek.InvalidTime (level: error)
invalidTime
- };
+};
+/// \brief
+/// The MediaDecoder class decodes media data and puts it on a given buffer.
+///
+/// We need to be able to handle event stuff, so we store the events that
+/// need to be handled, and then NetStream can ask for it on ::advance()
+/// or whenever it is appropriate. Eventhandling is different from AS2 to AS3,
+/// but in this first draft only AS2 will be supported.
+///
+class MediaDecoder
+{
+
+public:
/// This is copied from the render and should be changed if the
original is.
enum videoOutputFormat
{
@@ -121,7 +121,7 @@
/// The buffer we will use.
/// Ownership left to the caller.
///
- MediaDecoder(tu_file* stream, MediaBuffer* buffer, uint16_t swfVersion,
int format)
+ MediaDecoder(boost::shared_ptr<tu_file> stream, MediaBuffer* buffer,
uint16_t swfVersion, int format)
:
_buffer(buffer),
_stream(stream),
@@ -133,20 +133,19 @@
_error(noError),
_isFLV(true),
_inputPos(0),
- _audio(true),
- _video(true)
+ _audio(false),
+ _video(false),
+ _running(true),
+ _audioDecoder(NULL),
+ _videoDecoder(NULL),
+ _decodeThread(NULL)
{
}
/// Destroys the Decoder
- ~MediaDecoder() {}
-
- /// Pause decoding (needed ?)
- virtual void pause() {}
-
- /// Resume/start decoding (needed ?)
- virtual void decode() {}
-
+#if !defined(sgi) || defined(__GNUC__)
+ virtual ~MediaDecoder() {}
+#endif
/// Seeks to pos, returns the new position
virtual uint32_t seek(uint32_t /*pos*/) { return 0;}
@@ -164,13 +163,7 @@
}
/// Returns a vector with the waiting onStatus events (AS2)
- std::vector<StatusCode> getOnStatusEvents() {
- boost::mutex::scoped_lock lock(_onStatusMutex);
-
- const std::vector<StatusCode> statusQueue(_onStatusQueue);
- _onStatusQueue.clear();
- return statusQueue;
- }
+ std::vector<StatusCode> getOnStatusEvents();
/// Returns whether we got audio
bool gotAudio() {
@@ -182,18 +175,46 @@
return _video;
}
+ /// Used to wake up the decoder when it is needed
+ void wakeUp()
+ {
+ boost::mutex::scoped_lock lock(_monitor);
+ _nothingToDo.notify_all();
+ }
+
protected:
+
+ /// Decodes data with the decoders that has been setup and pushes the
data
+ /// unto the buffer. Returns when decoding stops.
+ void decodingLoop();
+
+ /// Decodes a frame and push it unto the buffer
+ bool decodeAndBufferFrame();
+
+ // Used to decode a video frame and push it on the videoqueue
+ void decodeVideo(MediaFrame* packet);
+
+ // Used to decode a audio frame and push it on the audioqueue
+ void decodeAudio(MediaFrame* packet);
+
/// Push an event to the onStatus event queue (AS2)
void pushOnStatus(StatusCode code) {
boost::mutex::scoped_lock lock(_onStatusMutex);
_onStatusQueue.push_back(code);
}
+ /// used to wait for something to do
+ void relax()
+ {
+ boost::mutex::scoped_lock lock(_monitor);
+ _nothingToDo.wait(lock);
+ }
+
/// The media buffer
MediaBuffer* _buffer;
/// The stream we decode
- tu_file* _stream;
+ boost::shared_ptr<tu_file> _stream;
/// Version of the SWF playing
uint16_t _swfVersion;
@@ -231,6 +252,21 @@
/// Do we have video ?
bool _video;
+ /// Used to wait when there is nothing to do
+ boost::condition _nothingToDo;
+ boost::mutex _monitor;
+
+ // Should the decode loop run or not
+ volatile bool _running;
+
+ // An audio decoder
+ std::auto_ptr<AudioDecoder> _audioDecoder;
+
+ // A video decoder
+ std::auto_ptr<VideoDecoder> _videoDecoder;
+
+ // The decoding thread
+ boost::thread* _decodeThread;
};
Index: libmedia/MediaParser.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/MediaParser.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- libmedia/MediaParser.h 24 Nov 2007 17:21:42 -0000 1.8
+++ libmedia/MediaParser.h 30 Nov 2007 00:13:01 -0000 1.9
@@ -16,7 +16,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: MediaParser.h,v 1.8 2007/11/24 17:21:42 strk Exp $
+// $Id: MediaParser.h,v 1.9 2007/11/30 00:13:01 tgc Exp $
#ifndef __MEDIAPARSER_H__
#define __MEDIAPARSER_H__
@@ -25,6 +25,7 @@
#include "config.h"
#endif
+#include <boost/shared_ptr.hpp>
#include "tu_file.h"
#ifdef USE_FFMPEG
@@ -192,7 +193,7 @@
class MediaParser
{
public:
- MediaParser(tu_file* stream)
+ MediaParser(boost::shared_ptr<tu_file> stream)
:
_isAudioMp3(false),
_isAudioNellymoser(false),
@@ -271,7 +272,7 @@
bool _isAudioNellymoser;
/// The stream used to access the file
- tu_file* _stream;
+ boost::shared_ptr<tu_file> _stream;
};
Index: libmedia/sound_handler.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/sound_handler.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- libmedia/sound_handler.h 24 Nov 2007 17:21:42 -0000 1.3
+++ libmedia/sound_handler.h 30 Nov 2007 00:13:01 -0000 1.4
@@ -18,7 +18,7 @@
//
//
-/* $Id: sound_handler.h,v 1.3 2007/11/24 17:21:42 strk Exp $ */
+/* $Id: sound_handler.h,v 1.4 2007/11/30 00:13:01 tgc Exp $ */
/// \page sound_handler_intro Sound handler introduction
///
@@ -429,103 +429,9 @@
size_t _soundsStopped;
};
-/*
-///
-/// Class containing information about a sound. Is created by the parser while
-/// parsing, and ownership is then transfered to sound_data. When the parser is
-/// parsing streams, it will ask the soundhandler for this to know what
properties
-/// the stream has.
-///
-class SoundInfo {
-public:
- /// Constructor
- //
- /// @param format
- /// The format of the sound. Can be MP3, ADPCM, uncompressed or
Nellymoser
- ///
- /// @param stero
- /// Defines whether the sound is in stereo.
- ///
- /// @param sampleRate
- /// The sample rate of the sound.
- ///
- /// @param sampleCount
- /// The sample count in the sound. In soundstreams this is an average
for each frame.
- ///
- /// @param is16bit
- /// Defines whether the sound is in stereo.
- /// Defines whether the sound is in 16bit format (samplesize == 2)?
else it
- /// is 8bit (samplesize == 1). Used for streams when decoding adpcm.
- ///
- SoundInfo(sound_handler::format_type format, sound_handler::format_type
orgFormat, bool stereo, uint32_t sampleRate, uint32_t sampleCount, bool is16bit)
- : _format(format),
- _orgFormat(orgFormat),
- _stereo(stereo),
- _sampleRate(sampleRate),
- _sampleCount(sampleCount),
- _is16bit(is16bit)
- {
- }
-
- /// Returns the current format of the sound
- ///
- /// @return the current format of the sound
- sound_handler::format_type getFormat() { return _format; }
-
- /// Returns the original format of the sound
- ///
- /// @return the original format of the sound
- sound_handler::format_type getOrgFormat() { return _orgFormat; }
-
- /// Returns the stereo status of the sound
- ///
- /// @return the stereo status of the sound
- bool isStereo() { return _stereo; }
-
- /// Returns the samplerate of the sound
- ///
- /// @return the samplerate of the sound
- unsigned long getSampleRate() { return _sampleRate; }
-
- /// Returns the samplecount of the sound
- ///
- /// @return the samplecount of the sound
- unsigned long getSampleCount() { return _sampleCount; }
-
- /// Returns the 16bit status of the sound
- ///
- /// @return the 16bit status of the sound
- bool is16bit() { return _is16bit; }
-
-private:
- /// Current format of the sound (MP3, raw, etc).
- sound_handler::format_type _format;
-
- /// Original format of the sound (ADPCM, etc).
- sound_handler::format_type _orgFormat;
-
- /// The size of the undecoded data
- unsigned long _dataSize;
-
- /// Stereo or not
- bool _stereo;
-
- /// Sample rate, one of 5512, 11025, 22050, 44100
- uint32_t _sampleRate;
-
- /// Number of samples
- uint32_t _sampleCount;
-
- /// Is the audio in 16bit format (samplesize == 2)? else it
- /// is 8bit (samplesize == 1). Used for streams when decoding adpcm.
- bool _is16bit;
-};*/
-
// TODO: move to appropriate specific sound handlers
DSOEXPORT sound_handler* create_sound_handler_sdl();
DSOEXPORT sound_handler* create_sound_handler_gst();
-DSOEXPORT sound_handler* create_sound_handler_test();
-
} // gnash.media namespace
Index: libmedia/gst/VideoDecoderGst.cpp
===================================================================
RCS file: /sources/gnash/gnash/libmedia/gst/VideoDecoderGst.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- libmedia/gst/VideoDecoderGst.cpp 24 Nov 2007 17:21:42 -0000 1.5
+++ libmedia/gst/VideoDecoderGst.cpp 30 Nov 2007 00:13:02 -0000 1.6
@@ -16,7 +16,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: VideoDecoderGst.cpp,v 1.5 2007/11/24 17:21:42 strk Exp $
+// $Id: VideoDecoderGst.cpp,v 1.6 2007/11/30 00:13:02 tgc Exp $
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -54,6 +54,11 @@
}
}
+bool VideoDecoderGst::setup(VideoInfo* info)
+{
+ return setup(info->width, info->height, 0, true,
(videoCodecType)info->codec, 0);
+}
+
bool
VideoDecoderGst::setup(int widthi, int heighti, int deblockingi, bool
smoothingi, videoCodecType formati, int outputFormati)
{
@@ -209,7 +214,7 @@
frame = data;
frameSize = size;
-
+//printf("datasize: %d\n", size);
delete input_lock;
output_lock = new boost::mutex::scoped_lock(output_mutex);
@@ -226,37 +231,6 @@
return ret_image;
}
-// gnash calls this when it wants you to decode the given videoframe
-/*uint8_t*
-VideoDecoderGst::decode(uint8_t* data, uint32_t size, uint32_t& outputSize)
-{
- // If there is nothing to decode in the new frame
- // we just return the lastest.
- if (data == NULL || size == 0 || !decoder)
- {
- outputSize = 0;
- return NULL;
- }
-
- frame = data;
- frameSize = size;
-
- delete input_lock;
-
- output_lock = new boost::mutex::scoped_lock(output_mutex);
-
- // If we never decoded any frame return a NULL
- // auto pointer ..
- if ( ! decodedFrame.get() )
- {
- outputSize = 0;
- return NULL;
- }
-
- outputSize = width * height * 3;
- return decodedFrame->data();
-}*/
-
// The callback function which refills the buffer with data
void
VideoDecoderGst::callback_handoff (GstElement * /*c*/, GstBuffer *buffer,
GstPad* /*pad*/, gpointer user_data)
@@ -277,7 +251,7 @@
VideoDecoderGst::callback_output (GstElement * /*c*/, GstBuffer *buffer,
GstPad* /*pad*/, gpointer user_data)
{
VideoDecoderGst* decoder = static_cast<VideoDecoderGst*>(user_data);
-
+//printf("datadecoded\n");
if (decoder->stop) return;
if (decoder->decodedFrame.get())
Index: libmedia/gst/VideoDecoderGst.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/gst/VideoDecoderGst.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- libmedia/gst/VideoDecoderGst.h 24 Nov 2007 17:21:42 -0000 1.7
+++ libmedia/gst/VideoDecoderGst.h 30 Nov 2007 00:13:02 -0000 1.8
@@ -16,7 +16,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: VideoDecoderGst.h,v 1.7 2007/11/24 17:21:42 strk Exp $
+// $Id: VideoDecoderGst.h,v 1.8 2007/11/30 00:13:02 tgc Exp $
#ifndef __VIDEODECODERGST_H__
#define __VIDEODECODERGST_H__
@@ -44,6 +44,8 @@
VideoDecoderGst();
~VideoDecoderGst();
+ bool setup(VideoInfo* info);
+
bool setup(
int /*width*/,
int /*height*/,
Index: libmedia/gst/sound_handler_gst.cpp
===================================================================
RCS file: /sources/gnash/gnash/libmedia/gst/sound_handler_gst.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libmedia/gst/sound_handler_gst.cpp 24 Nov 2007 17:21:42 -0000 1.2
+++ libmedia/gst/sound_handler_gst.cpp 30 Nov 2007 00:13:02 -0000 1.3
@@ -20,7 +20,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.2 2007/11/24 17:21:42 strk Exp $ */
+/* $Id: sound_handler_gst.cpp,v 1.3 2007/11/30 00:13:02 tgc Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -609,14 +609,199 @@
return muted;
}
-void GST_sound_handler::attach_aux_streamer(aux_streamer_ptr /*ptr*/, void*
/*owner*/)
+
+
+// The callback function which refills the buffer with data
+void GST_sound_handler::callback_as_handoff (GstElement * /*c*/, GstBuffer
*buffer, GstPad* /*pad*/, gpointer user_data)
{
- log_unimpl(__PRETTY_FUNCTION__);
+ gst_elements *gstelements = static_cast<gst_elements*>(user_data);
+
+ try_mutex::scoped_try_lock lock(gstelements->handler->_mutex);
+
+ // If we couldn't obtain a lock return to avoid a deadlock
+ if (!lock.locked()) {
+
+ // We return nothing in this case to avoid noise being decoded
and played
+ if (GST_BUFFER_SIZE(buffer) != 0 && GST_BUFFER_DATA(buffer)) {
+ GST_BUFFER_DATA(buffer) = 0;
+ GST_BUFFER_SIZE(buffer) = 0;
+ }
+ return;
+ }
+
+ // First callback or after a couldn't-get-lock-return
+ if (GST_BUFFER_SIZE(buffer) == 0) {
+ if (gstelements->data_size > BUFFER_SIZE) {
+ GST_BUFFER_SIZE(buffer) = BUFFER_SIZE;
+ } else {
+ GST_BUFFER_SIZE(buffer) = gstelements->data_size;
+ }
+
+ // Reallocate the required memory.
+ guint8* tmp_buf = new guint8[GST_BUFFER_SIZE(buffer)];
+ memcpy(tmp_buf, GST_BUFFER_DATA(buffer), sizeof(buffer));
+
+ delete [] GST_BUFFER_DATA(buffer);
+ GST_BUFFER_DATA(buffer) = tmp_buf;
+ }
+
+ /*GST_sound_handler::*/aux_streamer_ptr aux_streamer =
gstelements->handler->m_aux_streamer[gstelements->owner];
+
+ // If false is returned the sound doesn't want to be attached anymore
+ bool ret = (aux_streamer)(gstelements->owner, GST_BUFFER_DATA(buffer),
GST_BUFFER_SIZE(buffer));
+/* if (!ret) {
+ handler->m_aux_streamer.erase(it++);
+ handler->soundsPlaying--;
+
+ // All the data has been given to the pipeline, so now we need
to stop
+ // the pipeline. g_idle_add() makes sure sound_killer is called
soon.
+ if (gstelements->position > gstelements->data_size) {
+ g_idle_add(sound_killer, user_data);
+ GST_BUFFER_SIZE(buffer) = 0;
+ GST_BUFFER_DATA(buffer) = 0;
+ return;
+ }
+ }*/
+
+}
+
+void GST_sound_handler::attach_aux_streamer(aux_streamer_ptr ptr, void* owner)
+{
+ try_mutex::scoped_lock lock(_mutex);
+ assert(owner);
+ assert(ptr);
+
+ aux_streamer_ptr p;
+ if (m_aux_streamer.get(owner, &p))
+ {
+ // Already in the hash.
+ return;
+ }
+ m_aux_streamer[owner] = ptr;
+
+ // Make a pipeline that can play the raw data
+
+ // Make a "gst_elements" for this sound which is latter placed on the
vector of instances of this sound being played
+ gst_elements* gst_element = new gst_elements;
+ if (gst_element == NULL) {
+ log_error (_("Could not allocate memory for gst_element"));
+ return;
+ }
+
+ // Set the handler
+ gst_element->handler = this;
+
+ // create main pipeline
+ gst_element->pipeline = gst_pipeline_new (NULL);
+
+ // create an audio sink - use oss, alsa or...? make a commandline
option?
+ // we first try atudetect, then alsa, then oss, then esd, then...?
+#if !defined(__NetBSD__)
+ gst_element->audiosink = gst_element_factory_make ("autoaudiosink",
NULL);
+ if (!gst_element->audiosink) gst_element->audiosink =
gst_element_factory_make ("alsasink", NULL);
+ if (!gst_element->audiosink) gst_element->audiosink =
gst_element_factory_make ("osssink", NULL);
+#endif
+ if (!gst_element->audiosink) gst_element->audiosink =
gst_element_factory_make ("esdsink", NULL);
+
+ // Check if the creation of the gstreamer pipeline, adder and audiosink
was a succes
+ if (!gst_element->pipeline) {
+ log_error(_("The gstreamer pipeline element could not be
created"));
+ }
+ if (!gst_element->audiosink) {
+ log_error(_("The gstreamer audiosink element could not be
created"));
+ }
+
+ // link adder and output to bin
+ gst_bin_add (GST_BIN (gst_element->pipeline), gst_element->audiosink);
+
+ gst_element->bin = gst_bin_new(NULL);
+ gst_element->input = gst_element_factory_make ("fakesrc", NULL);
+ gst_element->capsfilter = gst_element_factory_make ("capsfilter", NULL);
+ gst_element->audioconvert = gst_element_factory_make ("audioconvert",
NULL);
+ gst_element->audioresample = gst_element_factory_make ("audioresample",
NULL);
+ gst_element->volume = gst_element_factory_make ("volume", NULL);
+
+ // Put the gstreamer elements in the pipeline
+ gst_bin_add_many (GST_BIN (gst_element->bin), gst_element->input,
+ gst_element->capsfilter,
+ gst_element->audioconvert,
+ gst_element->audioresample,
+ gst_element->volume, NULL);
+
+ // Test if the fakesrc, typefind and audio* elements was correctly
created
+ if (!gst_element->input
+ || !gst_element->capsfilter
+ || !gst_element->audioconvert
+ || !gst_element->audioresample) {
+
+ log_error(_("Gstreamer element for audio handling could not be
created"));
+ return;
+ }
+
+ // Create a gstreamer decoder for the chosen sound.
+
+ // Set the info about the stream so that gstreamer knows what it is.
+ // We know what the pre-decoded data format is.
+ GstCaps *caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, 44100,
+ "channels", G_TYPE_INT, 2,
+ "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+ "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16,
+ //"signed", G_TYPE_INT, 1,
+ NULL);
+ g_object_set (G_OBJECT (gst_element->capsfilter), "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ // setup fake source
+ g_object_set (G_OBJECT (gst_element->input),
+ "sizetype", 2, "can-activate-pull", FALSE,
"signal-handoffs", TRUE,
+ "sizemax", BUFFER_SIZE, NULL);
+ // Setup the callback
+ gst_element->handoff_signal_id = g_signal_connect (gst_element->input,
"handoff", G_CALLBACK (callback_as_handoff), gst_element);
+
+ // we receive raw native sound-data, output directly
+ gst_element_link_many (gst_element->input,
+ gst_element->capsfilter,
+ gst_element->audioconvert,
+ gst_element->audioresample,
+ gst_element->volume, NULL);
+
+ // Add ghostpad
+ GstPad *pad = gst_element_get_pad (gst_element->volume, "src");
+ gst_element_add_pad (gst_element->bin, gst_ghost_pad_new ("src", pad));
+ gst_object_unref (GST_OBJECT (pad));
+
+ // Add the bin to the main pipeline
+ gst_bin_add(GST_BIN (gst_element->pipeline), gst_element->bin);
+ // Link to the adder sink pad
+ GstPad *sinkpad = gst_element_get_pad (gst_element->audiosink, "sink");
+ GstPad *srcpad = gst_element_get_pad (gst_element->bin, "src");
+ gst_pad_link (srcpad, sinkpad);
+ gst_object_unref (GST_OBJECT (srcpad));
+ gst_object_unref (GST_OBJECT (sinkpad));
+
+ gst_element->owner = owner;
+
+ // Put the gst_element on the vector
+ m_aux_streamer_gstelements[owner] = gst_element;
+
+ // If not already playing, start doing it
+ gst_element_set_state (GST_ELEMENT (gst_element->pipeline),
GST_STATE_PLAYING);
+printf("pipeline stated playing\n");
}
-void GST_sound_handler::detach_aux_streamer(void* /*owner*/)
+void GST_sound_handler::detach_aux_streamer(void* owner)
{
- log_unimpl(__PRETTY_FUNCTION__);
+ try_mutex::scoped_lock lock(_mutex);
+ aux_streamer_ptr p;
+ if (m_aux_streamer.get(owner, &p))
+ {
+ m_aux_streamer.erase(owner);
+ delete m_aux_streamer_gstelements[owner];
+ m_aux_streamer_gstelements.erase(owner);
+ }
+
}
unsigned int GST_sound_handler::get_duration(int sound_handle)
Index: libmedia/gst/sound_handler_gst.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/gst/sound_handler_gst.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libmedia/gst/sound_handler_gst.h 24 Nov 2007 17:21:43 -0000 1.4
+++ libmedia/gst/sound_handler_gst.h 30 Nov 2007 00:13:02 -0000 1.5
@@ -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: sound_handler_gst.h,v 1.4 2007/11/24 17:21:43 strk Exp $
+// $Id: sound_handler_gst.h,v 1.5 2007/11/30 00:13:02 tgc Exp $
#ifndef SOUND_HANDLER_GST_H
#define SOUND_HANDLER_GST_H
@@ -28,6 +28,7 @@
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
+#include "hash_wrapper.h"
#define BUFFER_SIZE 5000
@@ -78,6 +79,10 @@
/// Set the undecoded data pointer
void set_data(const uint8_t*);
+ /// The owner of the audio data this element will get data from.
+ /// Only used when getting data from NetStream or Sound.
+ void* owner;
+
private:
// The (un)compressed data
const guint8* data;
@@ -131,6 +136,11 @@
class GST_sound_handler : public sound_handler
{
private:
+ /// AS classes (NetStream, Sound) audio callbacks
+ hash_wrapper< void* /* owner */, aux_streamer_ptr /* callback */>
m_aux_streamer;
+
+ hash_wrapper< void* /* owner */, gst_elements*>
m_aux_streamer_gstelements;
+
/// Vector containing all the sounds
std::vector<sound_data*> m_sound_data;
@@ -148,6 +158,9 @@
/// Gstreamer callback function
static void callback_handoff (GstElement * /*c*/, GstBuffer *buffer,
GstPad* /*pad*/, gpointer user_data);
+ /// Gstreamer callback function when using ActionScript audio source
(NetStream, Sound)
+ static void callback_as_handoff (GstElement * /*c*/, GstBuffer *buffer,
GstPad* /*pad*/, gpointer user_data);
+
GST_sound_handler();
virtual ~GST_sound_handler();
@@ -196,8 +209,8 @@
/// Gets the playhead position in milliseconds of an event sound
connected to an AS Soound obejct.
virtual unsigned int get_position(int sound_handle);
- virtual void attach_aux_streamer(aux_streamer_ptr ptr, void* owner);
//vv
- virtual void detach_aux_streamer(void* owner); //vv
+ virtual void attach_aux_streamer(aux_streamer_ptr ptr, void* owner);
+ virtual void detach_aux_streamer(void* owner);
};
Index: libmedia/sdl/AudioDecoderFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/libmedia/sdl/AudioDecoderFfmpeg.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- libmedia/sdl/AudioDecoderFfmpeg.cpp 24 Nov 2007 17:21:43 -0000 1.6
+++ libmedia/sdl/AudioDecoderFfmpeg.cpp 30 Nov 2007 00:13:02 -0000 1.7
@@ -17,7 +17,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-// $Id: AudioDecoderFfmpeg.cpp,v 1.6 2007/11/24 17:21:43 strk Exp $
+// $Id: AudioDecoderFfmpeg.cpp,v 1.7 2007/11/30 00:13:02 tgc Exp $
#include "AudioDecoderFfmpeg.h"
@@ -221,10 +221,10 @@
// Error handling
if (bufsize < 1) {
+ log_error(_("Error while decoding audio data."));
+ delete [] output;
decodedBytes = 0;
outputSize = 0;
- delete [] output;
- log_error(_("Error while decoding audio data."));
return NULL;
}
Index: libmedia/sdl/MediaDecoderSdl.cpp
===================================================================
RCS file: /sources/gnash/gnash/libmedia/sdl/MediaDecoderSdl.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libmedia/sdl/MediaDecoderSdl.cpp 24 Nov 2007 17:21:43 -0000 1.4
+++ libmedia/sdl/MediaDecoderSdl.cpp 30 Nov 2007 00:13:02 -0000 1.5
@@ -16,10 +16,11 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-// $Id: MediaDecoderSdl.cpp,v 1.4 2007/11/24 17:21:43 strk Exp $
+// $Id: MediaDecoderSdl.cpp,v 1.5 2007/11/30 00:13:02 tgc Exp $
#include "MediaDecoderSdl.h"
#include "AudioDecoderNellymoser.h"
+#include "AudioDecoderSimple.h"
#ifdef USE_FFMPEG
#include "AudioDecoderFfmpeg.h"
@@ -33,95 +34,33 @@
#include "log.h"
-#include <boost/scoped_array.hpp>
-
-#if defined(_WIN32) || defined(WIN32)
-# include <windows.h> // for sleep()
-# define usleep(x) Sleep(x/1000)
-#else
-# include "unistd.h" // for usleep()
-#endif
+#include "gnash.h"
namespace gnash {
namespace media {
-MediaDecoderSdl::MediaDecoderSdl(tu_file* stream, MediaBuffer* buffer,
uint16_t swfVersion, int format)
+MediaDecoderSdl::MediaDecoderSdl(boost::shared_ptr<tu_file> stream,
MediaBuffer* buffer, uint16_t swfVersion, int format)
:
- MediaDecoder(stream, buffer, swfVersion, format),
-
- _decodeThread(NULL),
-
- _running(true),
- _audioDecoder(NULL),
- _videoDecoder(NULL)
+ MediaDecoder(stream, buffer, swfVersion, format)
{
- // Buffer a bit to make sure the stream is accessable
- if (_stream->set_position(512) != 0) {
- _error = streamError;
- pushOnStatus(streamNotFound);
- return;
- }
- _lastConfirmedPosition = 512;
- _streamSize = _stream->get_size();
-
- // Check if the file is a FLV, in which case we use our own parser
- char head[4] = {0, 0, 0, 0};
- _stream->set_position(0);
- _stream->read_bytes(head, 3);
- _stream->set_position(0);
-
- // Setup the decoding and parser
- bool ret = false;
- if (std::string(head) == "FLV") {
- _parser.reset(new FLVParser(_stream));
-#ifdef USE_FFMPEG
- } else {
- _parser.reset(new MediaParserFfmpeg(_stream));
-#endif
- }
-
- ret = _parser->setupParser();
-
- if (ret) {
- ret = setupDecoding();
- } else {
- log_error("Setup of media parser failed");
- return;
- }
-
- // If the setup failed, there is no reason to start the decoding thread
- if (ret) {
// Start the decoding thread which will also setup the decoder
and parser
_decodeThread = new
boost::thread(boost::bind(MediaDecoderSdl::decodeThread, this));
- } else {
- log_error("Setup of media decoder failed");
- }
}
MediaDecoderSdl::~MediaDecoderSdl()
{
_running = false;
-printf("waiting for thread to stop\n");
- _decodeThread->join();
-printf("thread stopped\n");
+ if (_decodeThread) {
+ wakeUp();
+ _decodeThread->join();
delete _decodeThread;
- printf("MediaDecoderSdl deleted!");
-}
-
-void MediaDecoderSdl::pause()
-{
-}
-
-void MediaDecoderSdl::decode()
-{
+ _decodeThread = NULL;
+ }
}
bool MediaDecoderSdl::setupDecoding()
{
- bool video = false;
- bool audio = false;
-
std::auto_ptr<VideoInfo> vInfo = _parser->getVideoInfo();
if (vInfo.get() != NULL) {
#ifdef USE_FFMPEG
@@ -132,14 +71,14 @@
_videoDecoder.reset(NULL); // Delete the
videoDecoder if it is of no use
log_error("No video decoder could be created,
since no decoder for this format is available.");
}
- video = true;
+ _video = true;
} else {
log_error("No video decoder could be created, since no
decoder is enabled.");
}
}
std::auto_ptr<AudioInfo> aInfo = _parser->getAudioInfo();
- if (aInfo.get() != NULL) {
+ if (get_sound_handler() && aInfo.get() != NULL) {
#ifdef USE_MAD
if (_parser->isAudioMp3()) {
_audioDecoder.reset(new AudioDecoderMad());
@@ -157,16 +96,44 @@
_audioDecoder.reset(NULL); // Delete the
audioDecoder if it is of no use
log_error("No audio decoder could be created,
since no decoder for this format is available.");
}
- audio = true;
+ _audio = true;
} else {
log_error("No audio decoder could be created, since no
decoder is enabled.");
}
}
// We don't need both audio and video to be happy :)
- return (audio || video);
+ return (_audio || _video);
}
+bool MediaDecoderSdl::setupParser()
+{
+ // Buffer a bit to make sure the stream is accessable
+ if (_stream->set_position(512) != 0) {
+ _error = streamError;
+ pushOnStatus(streamNotFound);
+ return false;
+ }
+
+ _lastConfirmedPosition = 512;
+ _streamSize = _stream->get_size();
+
+ // Check if the file is a FLV, in which case we use our own parser
+ char head[4] = {0, 0, 0, 0};
+ _stream->set_position(0);
+ _stream->read_bytes(head, 3);
+ _stream->set_position(0);
+
+ // Setup the decoding and parser
+ if (std::string(head) == "FLV") {
+ _parser.reset(new FLVParser(_stream));
+#ifdef USE_FFMPEG
+ } else {
+ _parser.reset(new MediaParserFfmpeg(_stream));
+#endif
+ }
+ return _parser->setupParser();
+}
uint32_t MediaDecoderSdl::seek(uint32_t pos)
{
@@ -183,117 +150,31 @@
void MediaDecoderSdl::decodeThread(MediaDecoderSdl* decoder)
{
printf("\t in the decode thread\n");
- // The decode loop
- while (decoder->_running) {
- // If the buffer is not full, put something into it!
- if (!decoder->_buffer->isFull()) {
- decoder->decodeAndBufferFrame();
- //log_debug("decoded a frame");
-
- // "Warm up" the data.
- } else if (decoder->_streamSize >
decoder->_lastConfirmedPosition) {
- if
(decoder->_stream->set_position(decoder->_lastConfirmedPosition+10000) != 0) {
- // We assume we're done now
- // TODO: check for errors
- decoder->_lastConfirmedPosition =
decoder->_streamSize;
- } else {
- decoder->_lastConfirmedPosition += 10000;
- }
- //log_debug("warming up the file");
+ // If the destructor has been called at this point, exit the thread
+ if (!decoder->_running) return;
- }
- usleep(1); // task switch, to avoid 100% CPU
- }
- log_debug("Left the decoding loop");
-}
+ // Setup the decoder and parser
-
-void MediaDecoderSdl::decodeAndBufferFrame()
-{
-
- MediaFrame* frame = _parser->parseMediaFrame();
- uint32_t parserPosition = _parser->getLastParsedPos();
- if (parserPosition > _lastConfirmedPosition) _lastConfirmedPosition =
parserPosition;
-
- if (frame == NULL) {
- if (_lastConfirmedPosition+1 >= _streamSize)
- {
-#ifdef GNASH_DEBUG_THREADS
- log_debug("decodeFLVFrame: load completed, stopping");
-#endif
- // Stop!
- //m_go = false;
- } else {
- log_error("FLV parsing problems! stopping buffering.");
- _running = false;
- }
-//log_error("FLV parsing problems!");
+ if (decoder->setupParser()) {
+ if (!decoder->setupDecoding()) {
+ decoder->pushOnStatus(streamNotFound);
+ log_error("Setup of media decoder failed");
return;
}
-
- if (frame->tag == 9) {
- decodeVideo(frame);
} else {
- decodeAudio(frame);
- }
-
-}
-
-void MediaDecoderSdl::decodeAudio(MediaFrame* packet)
-{
- // We don't handle audio
- if (!_audioDecoder.get()) return;
-
- uint32_t datasize;
- uint32_t bufsize;
-
- uint8_t* ptr = _audioDecoder->decode(packet->data, packet->dataSize,
bufsize, datasize, false);
-
- if (bufsize > 0 && ptr != NULL)
- {
- raw_mediadata_t* raw = new raw_mediadata_t();
-
- raw->m_data = ptr;
- raw->m_ptr = raw->m_data;
- raw->m_size = bufsize;
- raw->m_pts = packet->timestamp;
- _buffer->pushAudio(raw);
+ decoder->pushOnStatus(streamNotFound);
+ log_error("Setup of media parser failed");
return;
}
- log_debug(_("Problems decoding audio frame."));
- /*_running = false;
- _error = decodingError;
- pushOnStatus(playStop);*/
-}
-void MediaDecoderSdl::decodeVideo(MediaFrame* packet)
-{
- // We don't handle video decoding today
- if (!_videoDecoder.get()) return;
-
- uint32_t bufsize;
+ // Everything is setup, so let's play!
- uint8_t* ptr = _videoDecoder->decode(packet->data, packet->dataSize,
bufsize);
+ decoder->pushOnStatus(playStart);
- if (bufsize > 0 && ptr != NULL)
- {
- raw_mediadata_t* raw = new raw_mediadata_t();
-
- raw->m_data = ptr;
- raw->m_ptr = raw->m_data;
- raw->m_size = bufsize;
- raw->m_pts = packet->timestamp;
- _buffer->pushVideo(raw);
- return;
- }
- log_debug(_("Problems decoding video frame."));
-/* _running = false;
- _error = decodingError;
- pushOnStatus(playStop);*/
+ decoder->decodingLoop();
}
-
std::pair<uint32_t, uint32_t>
MediaDecoderSdl::getWidthAndHeight()
{
@@ -307,3 +188,4 @@
} // gnash.media namespace
} // namespace gnash
+
Index: libmedia/sdl/MediaDecoderSdl.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/sdl/MediaDecoderSdl.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libmedia/sdl/MediaDecoderSdl.h 24 Nov 2007 17:21:43 -0000 1.4
+++ libmedia/sdl/MediaDecoderSdl.h 30 Nov 2007 00:13:02 -0000 1.5
@@ -16,10 +16,10 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-// $Id: MediaDecoderSdl.h,v 1.4 2007/11/24 17:21:43 strk Exp $
+// $Id: MediaDecoderSdl.h,v 1.5 2007/11/30 00:13:02 tgc Exp $
-#ifndef __MEDIADECODERFFMPEG_H__
-#define __MEDIADECODERFFMPEG_H__
+#ifndef __MEDIADECODERSDL_H__
+#define __MEDIADECODERSDL_H__
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -42,118 +42,26 @@
/// Media decoding using libs, used with sdl soundhandler.
class MediaDecoderSdl: public MediaDecoder {
public:
- MediaDecoderSdl(tu_file* stream, MediaBuffer* buffer, uint16_t
swfVersion, int format);
+ MediaDecoderSdl(boost::shared_ptr<tu_file> stream, MediaBuffer* buffer,
uint16_t swfVersion, int format);
~MediaDecoderSdl();
- /// Pause decoding (needed ?)
- void pause();
-
- /// Resume/start decoding (needed ?)
- void decode();
-
/// Seeks to pos
uint32_t seek(uint32_t pos);
std::pair<uint32_t, uint32_t> getWidthAndHeight();
-/* // Used for ffmpeg data read and seek callbacks with non-FLV
- static int readPacket(void* opaque, uint8_t* buf, int buf_size);
-
- // Used for ffmpeg data read and seek callbacks with non-FLV
- static offset_t seekMedia(void *opaque, offset_t offset, int whence);*/
-
private:
+ /// Sets up the parser
+ bool setupParser();
+
/// The decoding thread. Sets up the decoder, and decodes.
static void decodeThread(MediaDecoderSdl* decoder);
- /// Decodes a frame and push it unto the buffer
- void decodeAndBufferFrame();
-
- // Used to decode a video frame and push it on the videoqueue
- void decodeVideo(MediaFrame* packet);
-
- // Used to decode a audio frame and push it on the audioqueue
- void decodeAudio(MediaFrame* packet);
-
- /// Sets up the decoder and parser
+ /// Sets up the decoder
bool setupDecoding();
-
-#if 0
- /// Sets up the decoder and parser for FLVs
- bool setupFLVdecoding();
-
- // Used to decode and push the next available (non-FLV) frame to the
audio or video queue
- void decodeMediaFrame();
-
- /// Used to decode push the next available FLV frame to the audio or
video queue
- //
- /// Called by ::av_streamer to buffer more a/v frames when possible.
- ///
- /// This is a non-blocking call, if data isn't available in the parser
no
- /// new frame is decoded and this method returns false. Note that this
doesn't
- /// necessarely means the FLV stream is ended, rather it is possible
the loader
- /// thread is starving.
- ///
- /// TODO: return a more informative value to distinguish between EOF
and starving
- /// conditions ?
- ///
- void decodeFLVFrame();
-
- // Used to decode a video frame and push it on the videoqueue
- void decodeVideo(AVPacket* packet);
-
- // Used to decode a audio frame and push it on the audioqueue
- void decodeAudio(AVPacket* packet);
-
- // Used to calculate a decimal value from a ffmpeg fraction
- inline double as_double(AVRational time)
- {
- return time.num / (double) time.den;
- }
-
- int _videoIndex;
- int _audioIndex;
-
- // video
- AVCodecContext* _videoCodecCtx;
- AVStream* _videoStream;
-
- // audio
- AVCodecContext* _audioCodecCtx;
- AVStream* _audioStream;
-
- // the format (mp3, avi, etc.)
- AVFormatContext *_formatCtx;
-
- // A ffmpeg frame
- AVFrame* _frame;
-#endif
- // The decoding thread
- boost::thread* _decodeThread;
-
- // The timestamp of the last decoded video frame, in seconds.
- volatile uint32_t _lastVideoTimestamp;
-
- // The timestamp of the last decoded audio frame, in seconds.
- volatile uint32_t _lastAudioTimestamp;
-
- // The time we started playing in seconds (since VM start ?)
- volatile uint64_t _startClock;
-
- // A ffmpeg thingy
- //ByteIOContext _byteIOCxt;
-
- // Should the decode loop run or not
- volatile bool _running;
-
- // An audio decoder, either using ffmpeg or mad
- std::auto_ptr<AudioDecoder> _audioDecoder;
-
- // A video decoder, using ffmpeg
- std::auto_ptr<VideoDecoder> _videoDecoder;
};
} // gnash.media namespace
} // namespace gnash
-#endif // __MEDIADECODERFFMPEG_H__
+#endif // __MEDIADECODERSDL_H__
Index: libmedia/sdl/MediaParserFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/libmedia/sdl/MediaParserFfmpeg.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libmedia/sdl/MediaParserFfmpeg.cpp 24 Nov 2007 17:21:43 -0000 1.4
+++ libmedia/sdl/MediaParserFfmpeg.cpp 30 Nov 2007 00:13:02 -0000 1.5
@@ -16,7 +16,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: MediaParserFfmpeg.cpp,v 1.4 2007/11/24 17:21:43 strk Exp $
+// $Id: MediaParserFfmpeg.cpp,v 1.5 2007/11/30 00:13:02 tgc Exp $
#include "MediaParserFfmpeg.h"
#include "log.h"
@@ -25,7 +25,7 @@
namespace gnash {
namespace media {
-MediaParserFfmpeg::MediaParserFfmpeg(tu_file* stream)
+MediaParserFfmpeg::MediaParserFfmpeg(boost::shared_ptr<tu_file> stream)
:
MediaParser(stream),
_videoIndex(-1),
@@ -86,7 +86,7 @@
// XXX should we call avcodec_init() first?
av_register_all();
- AVInputFormat* inputFmt = probeStream(_stream);
+ AVInputFormat* inputFmt = probeStream(_stream.get());
if (!inputFmt) {
log_error(_("Couldn't determine stream input format"));
//pushOnStatus(streamNotFound);
Index: libmedia/sdl/MediaParserFfmpeg.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/sdl/MediaParserFfmpeg.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libmedia/sdl/MediaParserFfmpeg.h 24 Nov 2007 17:21:43 -0000 1.4
+++ libmedia/sdl/MediaParserFfmpeg.h 30 Nov 2007 00:13:02 -0000 1.5
@@ -16,7 +16,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: MediaParserFfmpeg.h,v 1.4 2007/11/24 17:21:43 strk Exp $
+// $Id: MediaParserFfmpeg.h,v 1.5 2007/11/30 00:13:02 tgc Exp $
#ifndef __MEDIAPARSERFFMPEG_H__
#define __MEDIAPARSERFFMPEG_H__
@@ -47,7 +47,7 @@
class MediaParserFfmpeg : public MediaParser
{
public:
- MediaParserFfmpeg(tu_file* stream);
+ MediaParserFfmpeg(boost::shared_ptr<tu_file> stream);
~MediaParserFfmpeg();
/// Setup the parser
Index: libmedia/sdl/sound_handler_sdl.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/sdl/sound_handler_sdl.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libmedia/sdl/sound_handler_sdl.h 24 Nov 2007 17:21:43 -0000 1.4
+++ libmedia/sdl/sound_handler_sdl.h 30 Nov 2007 00:13:02 -0000 1.5
@@ -16,7 +16,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: sound_handler_sdl.h,v 1.4 2007/11/24 17:21:43 strk Exp $
+// $Id: sound_handler_sdl.h,v 1.5 2007/11/30 00:13:02 tgc Exp $
#ifndef SOUND_HANDLER_SDL_H
#define SOUND_HANDLER_SDL_H
@@ -284,8 +284,8 @@
class SDL_sound_handler : public sound_handler
{
private:
- /// NetStream audio callbacks
- hash_wrapper< void* /* owner */, aux_streamer_ptr /* callback */>
m_aux_streamer; //vv
+ /// AS classes (NetStream, Sound) audio callbacks
+ hash_wrapper< void* /* owner */, aux_streamer_ptr /* callback */>
m_aux_streamer;
/// Vector containing all sounds.
//
Index: libmedia/gst/AudioDecoderGst.cpp
===================================================================
RCS file: libmedia/gst/AudioDecoderGst.cpp
diff -N libmedia/gst/AudioDecoderGst.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/AudioDecoderGst.cpp 30 Nov 2007 00:13:01 -0000 1.1
@@ -0,0 +1,206 @@
+// AudioDecoderGst.cpp: Audio decoding using Gstreamer.
+//
+// Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// $Id: AudioDecoderGst.cpp,v 1.1 2007/11/30 00:13:01 tgc Exp $
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef SOUND_GST
+
+#include "AudioDecoderGst.h"
+
+namespace gnash {
+namespace media {
+
+AudioDecoderGst::AudioDecoderGst() :
+ _pipeline(NULL),
+ _input(NULL),
+ _inputcaps(NULL),
+ _outputcaps(NULL),
+ _output(NULL),
+ _decoder(NULL),
+ _resampler(NULL),
+ _converter(NULL),
+ _stop(false),
+ _undecodedDataSize(0),
+ _undecodedData(NULL),
+ _decodedDataSize(0),
+ _decodedData(0)
+{
+}
+
+AudioDecoderGst::~AudioDecoderGst()
+{
+
+ if (_pipeline) {
+ _stop = true;
+ delete input_lock;
+ gst_element_set_state (GST_ELEMENT (_pipeline), GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (_pipeline));
+ }
+}
+
+bool AudioDecoderGst::setup(AudioInfo* info)
+{
+ if (info->type != FLASH || info->codec != AUDIO_CODEC_MP3) return false;
+
+ // init GStreamer
+ gst_init (NULL, NULL);
+
+ // setup the pipeline
+ _pipeline = gst_pipeline_new (NULL);
+
+ // Setup the pipeline elements
+
+ // setup fake source
+ _input = gst_element_factory_make ("fakesrc", NULL);
+ g_object_set (G_OBJECT (_input), "sizetype", 3,
/*"can-activate-pull", FALSE,*/ "signal-handoffs", TRUE, NULL);
+
+ // Setup the callback
+ g_signal_connect (_input, "handoff", G_CALLBACK
(AudioDecoderGst::callback_handoff), this);
+
+ _decoder = gst_element_factory_make ("mad", NULL);
+ if (_decoder == NULL) {
+ _decoder = gst_element_factory_make ("flump3dec", NULL);
+ if (_decoder != NULL &&
!gst_default_registry_check_feature_version("flump3dec", 0, 10, 4))
+ {
+ static bool warned=false;
+ if ( ! warned )
+ {
+ // I keep getting these messages even if I hear
sound... too much paranoia ?
+ log_debug(_("This version of fluendos mp3
plugin does not support flash streaming sounds, please upgrade to version
0.10.4 or higher"));
+ warned=true;
+ }
+ }
+ }
+ // Check if the element was correctly created
+ if (!_decoder) {
+ 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 false;
+ }
+
+ GstCaps *caps = NULL;
+
+ // Set the info about the stream so that gstreamer knows what it is.
+ _inputcaps = gst_element_factory_make ("capsfilter", NULL);
+ caps = gst_caps_new_simple ("audio/mpeg",
+ "mpegversion", G_TYPE_INT, 1,
+ "layer", G_TYPE_INT, 3,
+ "rate", G_TYPE_INT, _sampleRate,
+ "channels", G_TYPE_INT, _stereo ? 2 : 1, NULL);
+ g_object_set (G_OBJECT (_inputcaps), "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ // Set the info about the stream so that gstreamer knows what the
output should be.
+ _outputcaps = gst_element_factory_make ("capsfilter", NULL);
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, 44100,
+ "channels", G_TYPE_INT, 2,
+ "width", G_TYPE_INT, 16,
+ //"depth", G_TYPE_INT, 16,
+ //"signed", G_TYPE_INT, ?,
+ NULL);
+ g_object_set (G_OBJECT (_outputcaps), "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ // setup the audiosink with callback
+ _output = gst_element_factory_make ("fakesink", NULL);
+ g_object_set (G_OBJECT (_output), "signal-handoffs", TRUE, NULL);
+ g_signal_connect (_output, "handoff", G_CALLBACK
(AudioDecoderGst::callback_output), this);
+
+
+ // Put the elemets in the pipeline and link them
+ gst_bin_add_many (GST_BIN (_pipeline), _input, _inputcaps, _decoder,
_resampler, _converter, _outputcaps, _output, NULL);
+
+ // link the elements
+ gst_element_link_many(_input, _inputcaps, _decoder, _resampler,
_converter, _outputcaps, _output, NULL);
+
+ // This make callback_handoff wait for data
+ input_lock = new boost::mutex::scoped_lock(input_mutex);
+
+ // This make decodeFrame wait for data
+ output_lock = new boost::mutex::scoped_lock(output_mutex);
+
+ // Start "playing"
+ gst_element_set_state (GST_ELEMENT (_pipeline), GST_STATE_PLAYING);
+
+ return true;
+
+}
+
+uint8_t* AudioDecoderGst::decode(uint8_t* input, uint32_t inputSize, uint32_t&
outputSize, uint32_t& decodedData, bool /*parse*/)
+{
+ // If there is nothing to decode in the new data we return NULL
+ if (input == NULL || inputSize == 0 || !_decoder)
+ {
+ outputSize = 0;
+ decodedData = 0;
+ return NULL;
+ }
+
+ _undecodedData = input;
+ _undecodedDataSize = inputSize;
+
+ delete input_lock;
+printf("waiting for decoded data\n");
+ output_lock = new boost::mutex::scoped_lock(output_mutex);
+printf("decoded data arrived\n");
+
+ decodedData = inputSize;
+ outputSize = _decodedDataSize;
+ return _decodedData;
+}
+
+// The callback function which refills the buffer with data
+void
+AudioDecoderGst::callback_handoff (GstElement * /*c*/, GstBuffer *buffer,
GstPad* /*pad*/, gpointer user_data)
+{
+ AudioDecoderGst* decoder = static_cast<AudioDecoderGst*>(user_data);
+
+ if (decoder->_stop) return;
+
+ decoder->input_lock = new
boost::mutex::scoped_lock(decoder->input_mutex);
+
+ GST_BUFFER_SIZE(buffer) = decoder->_undecodedDataSize;
+
+ GST_BUFFER_DATA(buffer) = decoder->_undecodedData;
+}
+
+// The callback function which passes the decoded audio data
+void
+AudioDecoderGst::callback_output (GstElement * /*c*/, GstBuffer *buffer,
GstPad* /*pad*/, gpointer user_data)
+{
+ AudioDecoderGst* decoder = static_cast<AudioDecoderGst*>(user_data);
+
+ if (decoder->_stop) return;
+
+ decoder->_decodedDataSize = GST_BUFFER_SIZE(buffer);
+
+ decoder->_decodedData = GST_BUFFER_DATA(buffer);
+
+ delete decoder->output_lock;
+
+}
+
+} // end of media namespace
+} // end of gnash namespace
+
+#endif // SOUND_GST
+
Index: libmedia/gst/AudioDecoderGst.h
===================================================================
RCS file: libmedia/gst/AudioDecoderGst.h
diff -N libmedia/gst/AudioDecoderGst.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/AudioDecoderGst.h 30 Nov 2007 00:13:01 -0000 1.1
@@ -0,0 +1,95 @@
+// AudioDecoderGst.h: Audio decoding using Gstreamer.
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// $Id: AudioDecoderGst.h,v 1.1 2007/11/30 00:13:01 tgc Exp $
+
+#ifndef __AUDIODECODERGST_H__
+#define __AUDIODECODERGST_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "log.h"
+#include "AudioDecoder.h"
+
+#include <gst/gst.h>
+#include "image.h"
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+#include <boost/thread/mutex.hpp>
+
+namespace gnash {
+namespace media {
+
+/// Video decoding using Gstreamer.
+class AudioDecoderGst : public AudioDecoder {
+
+public:
+ AudioDecoderGst();
+ ~AudioDecoderGst();
+
+ bool setup(AudioInfo* info);
+
+ uint8_t* decode(uint8_t* /*input*/, uint32_t /*inputSize*/, uint32_t&
/*outputSize*/, uint32_t& /*decodedData*/, bool /*parse*/);
+
+ static void callback_handoff (GstElement * /*c*/, GstBuffer *buffer,
GstPad* /*pad*/, gpointer user_data);
+ static void callback_output (GstElement * /*c*/, GstBuffer *buffer,
GstPad* /*pad*/, gpointer user_data);
+private:
+
+ // gstreamer pipeline objects
+
+ /// the main bin containing the elements
+ GstElement* _pipeline;
+
+ /// Gstreamer objects
+ GstElement* _input;
+ GstElement* _inputcaps;
+ GstElement* _outputcaps;
+ GstElement* _output;
+ GstElement* _decoder;
+ GstElement* _resampler;
+ GstElement* _converter;
+
+ /// mutexes and locks used to handle input and output.
+ boost::mutex input_mutex;
+ boost::mutex output_mutex;
+ boost::mutex::scoped_lock* input_lock;
+ boost::mutex::scoped_lock* output_lock;
+
+ /// Info from the video tag header. Might be usefull...
+ bool _stereo;
+ uint32_t _sampleRate;
+ audioCodecType _format;
+
+ /// If we should stop this will be true
+ volatile bool _stop;
+
+ uint32_t _undecodedDataSize;
+ uint8_t* _undecodedData;
+
+ uint32_t _decodedDataSize;
+ uint8_t* _decodedData;
+
+};
+
+} // media namespace
+} // gnash namespace
+
+#endif // __AUDIODECODERGST_H__
+
Index: libmedia/gst/MediaDecoderGst.cpp
===================================================================
RCS file: libmedia/gst/MediaDecoderGst.cpp
diff -N libmedia/gst/MediaDecoderGst.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/MediaDecoderGst.cpp 30 Nov 2007 00:13:01 -0000 1.1
@@ -0,0 +1,183 @@
+// MediaDecoderGst.cpp: Media decoding using Gstreamer
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// $Id: MediaDecoderGst.cpp,v 1.1 2007/11/30 00:13:01 tgc Exp $
+
+#include "MediaDecoderGst.h"
+#include "AudioDecoderNellymoser.h"
+#include "AudioDecoderSimple.h"
+
+#include "AudioDecoderGst.h"
+#include "VideoDecoderGst.h"
+
+#include "log.h"
+
+#include "gnash.h"
+
+namespace gnash {
+namespace media {
+
+MediaDecoderGst::MediaDecoderGst(boost::shared_ptr<tu_file> stream,
MediaBuffer* buffer, uint16_t swfVersion, int format)
+ :
+ MediaDecoder(stream, buffer, swfVersion, format)
+{
+ // Start the decoding thread which will also setup the decoder and
parser
+ _decodeThread = new
boost::thread(boost::bind(MediaDecoderGst::decodeThread, this));
+}
+
+MediaDecoderGst::~MediaDecoderGst()
+{
+ _running = false;
+
+ if (_decodeThread) {
+ wakeUp();
+ _decodeThread->join();
+ delete _decodeThread;
+ _decodeThread = NULL;
+ }
+}
+
+bool MediaDecoderGst::setupParser()
+{
+ // Buffer a bit to make sure the stream is accessable
+ if (_stream->set_position(512) != 0) {
+ _error = streamError;
+ pushOnStatus(streamNotFound);
+ return false;
+ }
+
+ _lastConfirmedPosition = 512;
+ _streamSize = _stream->get_size();
+
+ // Check if the file is a FLV, in which case we use our own parser
+ char head[4] = {0, 0, 0, 0};
+ _stream->set_position(0);
+ _stream->read_bytes(head, 3);
+ _stream->set_position(0);
+
+ // Setup the decoding and parser
+ if (std::string(head) == "FLV") {
+ _parser.reset(new FLVParser(_stream));
+ return _parser->setupParser();
+ } else {
+ return false;
+ }
+}
+
+bool MediaDecoderGst::setupDecoding()
+{
+ std::auto_ptr<VideoInfo> vInfo = _parser->getVideoInfo();
+ if (vInfo.get() != NULL) {
+
+ _videoDecoder.reset(new VideoDecoderGst());
+
+ if (_videoDecoder.get() != NULL) {
+ if (!_videoDecoder->setup(vInfo.get())) {
+ _videoDecoder.reset(NULL); // Delete the
videoDecoder if it is of no use
+ log_error("No video decoder could be created,
since no decoder for this format is available.");
+ }
+ _video = true;
+ } else {
+ log_error("No video decoder could be created, since no
decoder is enabled.");
+ }
+ }
+
+ std::auto_ptr<AudioInfo> aInfo = _parser->getAudioInfo();
+ if (get_sound_handler() && aInfo.get() != NULL) {
+
+ if (_parser->isAudioNellymoser()) {
+ _audioDecoder.reset(new AudioDecoderNellymoser());
+ }
+
+ if (_audioDecoder.get() == NULL) _audioDecoder.reset(new
AudioDecoderGst());
+
+ if (_audioDecoder.get() != NULL) {
+ if (!_audioDecoder->setup(aInfo.get())) {
+ _audioDecoder.reset(NULL); // Delete the
audioDecoder if it is of no use
+ log_error("No audio decoder could be created,
since no decoder for this format is available.");
+ }
+ _audio = true;
+ } else {
+ log_error("No audio decoder could be created, since no
decoder is enabled.");
+ }
+ }
+
+ // We don't need both audio and video to be happy :)
+ return (_audio || _video);
+}
+
+
+uint32_t MediaDecoderGst::seek(uint32_t pos)
+{
+ uint32_t ret = 0;
+ if (_parser.get()) ret = _parser->seek(pos);
+ else ret = 0;
+
+ // Flush the buffer
+ _buffer->flush();
+
+ return ret;
+}
+
+void MediaDecoderGst::decodeThread(MediaDecoderGst* decoder)
+{
+printf("\t in the decode thread\n");
+
+ // If the destructor has been called at this point, exit the thread
+ if (!decoder->_running) return;
+
+ // Setup the decoder and parser
+
+ if (decoder->setupParser()) {
+ if (!decoder->setupDecoding()) {
+ decoder->pushOnStatus(streamNotFound);
+ log_error("Setup of media decoder failed");
+ return;
+ }
+
+ // If the parser setup failed, it is perhaps because it is not a FLV
file,
+ // so we set up an gstreamer pipeline instead.
+ } else {
+/* if (!decoder->setupGstPipeline()) {
+ decoder->pushOnStatus(streamNotFound);*/
+ log_error("Setup of media parser failed");
+ return;
+// }
+ }
+
+ // Everything is setup, so let's play!
+
+ decoder->pushOnStatus(playStart);
+
+ decoder->decodingLoop();
+}
+
+std::pair<uint32_t, uint32_t>
+MediaDecoderGst::getWidthAndHeight()
+{
+ if (_parser.get()) {
+ std::auto_ptr<VideoInfo> vInfo = _parser->getVideoInfo();
+ if (vInfo.get()) return std::pair<uint32_t,
uint32_t>(vInfo->width, vInfo->height);
+ }
+ return std::pair<uint32_t, uint32_t>(0,0);
+}
+
+
+} // namespace media
+
+} // namespace gnash
Index: libmedia/gst/MediaDecoderGst.h
===================================================================
RCS file: libmedia/gst/MediaDecoderGst.h
diff -N libmedia/gst/MediaDecoderGst.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/MediaDecoderGst.h 30 Nov 2007 00:13:01 -0000 1.1
@@ -0,0 +1,62 @@
+// MediaDecoderGst.h: Media decoding using Gstreamer
+//
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// $Id: MediaDecoderGst.h,v 1.1 2007/11/30 00:13:01 tgc Exp $
+
+#ifndef __MEDIADECODERGST_H__
+#define __MEDIADECODERGST_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "MediaDecoder.h"
+#include "MediaParser.h"
+#include "AudioDecoder.h"
+#include "VideoDecoder.h"
+
+#include "image.h"
+
+namespace gnash {
+namespace media {
+
+/// Media decoding using Gstreamer
+class MediaDecoderGst: public MediaDecoder {
+public:
+ MediaDecoderGst(boost::shared_ptr<tu_file> stream, MediaBuffer* buffer,
uint16_t swfVersion, int format);
+ ~MediaDecoderGst();
+
+ /// Seeks to pos
+ uint32_t seek(uint32_t pos);
+
+ std::pair<uint32_t, uint32_t> getWidthAndHeight();
+
+private:
+ /// Sets up the parser
+ bool setupParser();
+
+ /// The decoding thread. Sets up the decoder, and decodes.
+ static void decodeThread(MediaDecoderGst* decoder);
+
+ /// Sets up the decoder and parser
+ bool setupDecoding();
+};
+
+} // namespace media
+} // namespace gnash
+#endif // __MEDIADECODERGST_H__
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash ChangeLog libmedia/FLVParser.cpp libmedia...,
Tomas Groth <=