[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r10041: More cleanups and refactorin
From: |
Bastiaan Jacques |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r10041: More cleanups and refactoring. Restore indexing broken by last commit. |
Date: |
Tue, 21 Oct 2008 22:20:52 +0200 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 10041
committer: Bastiaan Jacques <address@hidden>
branch nick: trunk
timestamp: Tue 2008-10-21 22:20:52 +0200
message:
More cleanups and refactoring. Restore indexing broken by last commit.
modified:
libmedia/FLVParser.cpp
libmedia/FLVParser.h
=== modified file 'libmedia/FLVParser.cpp'
--- a/libmedia/FLVParser.cpp 2008-10-21 15:24:43 +0000
+++ b/libmedia/FLVParser.cpp 2008-10-21 20:20:52 +0000
@@ -62,6 +62,9 @@
namespace gnash {
namespace media {
+
+const boost::uint16_t FLVParser::FLVAudioTag::flv_audio_rates [] = {5500,
11000, 22050, 44100};
+
FLVParser::FLVParser(std::auto_ptr<IOChannel> lt)
:
MediaParser(lt),
@@ -155,45 +158,38 @@
}
// would be called by parser thread
-bool
-FLVParser::indexTag(const boost::uint8_t* tag, boost::uint32_t timestamp,
boost::uint32_t thisTagPos)
-{
- if (tag[0] == FLV_AUDIO_TAG)
- {
- if ( ! _video) // if we have video we let that drive cue points
- {
- // we can theoretically seek anywhere, but
- // let's just keep 5 seconds of distance
- CuePointsMap::iterator it =
_cuePoints.lower_bound(timestamp);
- if ( it == _cuePoints.end() || it->first - timestamp >=
5000)
- {
- //log_debug("Added cue point at timestamp %d
and position %d (audio frame)", timestamp, thisTagPos);
- _cuePoints[timestamp] = thisTagPos;
- }
- }
- }
- else if (tag[0] == FLV_VIDEO_TAG)
- {
- // 1:keyframe, 2:interlacedFrame, 3:disposableInterlacedFrame
- int frameType = (tag[11] & 0xf0) >> 4;
-
- bool isKeyFrame = (frameType == 1);
- if ( isKeyFrame )
- {
- //log_debug("Added cue point at timestamp %d and
position %d (key video frame)", timestamp, thisTagPos);
- _cuePoints[timestamp] = thisTagPos;
- }
- }
- else
- {
- log_debug("FLVParser::indexNextTag: tag %d is neither audio nor
video", (int)tag[0]);
- }
-
- return true;
-}
+void
+FLVParser::indexAudioTag(const FLVTag& tag, boost::uint32_t thisTagPos)
+{
+ if ( _video) {
+ // if we have video we let that drive cue points
+ return;
+ }
+
+ // we can theoretically seek anywhere, but
+ // let's just keep 5 seconds of distance
+ CuePointsMap::iterator it = _cuePoints.lower_bound(tag.timestamp);
+ if ( it == _cuePoints.end() || it->first - tag.timestamp >= 5000)
+ {
+ //log_debug("Added cue point at timestamp %d and position %d
(audio frame)", timestamp, thisTagPos);
+ _cuePoints[tag.timestamp] = thisTagPos;
+ }
+}
+
+void
+FLVParser::indexVideoTag(const FLVTag& tag, const FLVVideoTag& videotag,
boost::uint32_t thisTagPos)
+{
+ if ( videotag.frametype != FLV_VIDEO_KEYFRAME ) {
+ return;
+ }
+
+ //log_debug("Added cue point at timestamp %d and position %d (key video
frame)", timestamp, thisTagPos);
+ _cuePoints[tag.timestamp] = thisTagPos;
+}
+
std::auto_ptr<EncodedAudioFrame>
-FLVParser::parseAudioTag(boost::uint32_t bodyLength, boost::uint32_t
timestamp, boost::uint32_t thisTagPos, const boost::uint8_t* tag)
+FLVParser::parseAudioTag(const FLVTag& flvtag, const FLVAudioTag& audiotag,
boost::uint32_t thisTagPos)
{
std::auto_ptr<EncodedAudioFrame> frame;
@@ -202,17 +198,16 @@
_audio = true; // TOCHECK: is this safe ?
}
- boost::uint8_t codec = (tag[11] & 0xf0) >> 4;
-
bool header = false;
+ boost::uint32_t bodyLength = flvtag.body_size;
- if (codec == AUDIO_CODEC_AAC) {
+ if (audiotag.codec == AUDIO_CODEC_AAC) {
boost::uint8_t packettype = _stream->read_byte();
header = (packettype == 0);
--bodyLength;
}
- frame = readAudioFrame(bodyLength-1, timestamp);
+ frame = readAudioFrame(bodyLength-1, flvtag.timestamp);
if ( ! frame.get() ) {
log_error("could not read audio frame?");
}
@@ -221,17 +216,7 @@
// audio format has been noted, so we do that now
if ( !_audioInfo.get() )
{
- 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.reset( new AudioInfo(codec, samplerate, samplesize,
(tag[11] & 0x01) >> 0, 0, FLASH) );
+ _audioInfo.reset( new AudioInfo(audiotag.codec,
audiotag.samplerate, audiotag.samplesize, audiotag.stereo, 0, FLASH) );
if (header) {
boost::uint8_t* newbuf = new
boost::uint8_t[frame->dataSize];
memcpy(newbuf, frame->data.get(), frame->dataSize);
@@ -250,51 +235,51 @@
}
std::auto_ptr<EncodedVideoFrame>
-FLVParser::parseVideoTag(boost::uint32_t bodyLength, boost::uint32_t
timestamp, boost::uint32_t thisTagPos, const boost::uint8_t* tag)
+FLVParser::parseVideoTag(const FLVTag& flvtag, const FLVVideoTag& videotag,
boost::uint32_t thisTagPos)
{
if ( ! _video ) {
log_error(_("Unexpected video tag found at offset %d of FLV
stream advertising no video in header. We'll warn only once per FLV, expecting
any further video tag."), thisTagPos);
_video = true; // TOCHECK: is this safe ?
}
- // 1:keyframe, 2:interlacedFrame, 3:disposableInterlacedFrame
- int frameType = (tag[11] & 0xf0) >> 4;
-
- boost::uint16_t codec = (tag[11] & 0x0f) >> 0;
-
- if (codec == VIDEO_CODEC_VP6 || codec == VIDEO_CODEC_VP6A)
- {
- _stream->read_byte();
- --bodyLength;
- }
bool header = false;
-
- if (codec == VIDEO_CODEC_H264) {
- boost::uint8_t packettype = _stream->read_byte();
- IF_VERBOSE_PARSE( log_debug(_("AVC packet type: %d"),
(unsigned)packettype) );
-
- header = (packettype == 0);
-
- // 24-bits value for composition time offset ignored for now.
- boost::uint8_t tmp[3];
- _stream->read(tmp, 3);
-
- bodyLength -= 4;
+ boost::uint32_t bodyLength = flvtag.body_size;
+
+ switch(videotag.codec) {
+ case VIDEO_CODEC_VP6:
+ case VIDEO_CODEC_VP6A:
+ {
+ _stream->read_byte();
+ --bodyLength;
+ break;
+ }
+ case VIDEO_CODEC_H264:
+ {
+ boost::uint8_t packettype = _stream->read_byte();
+ IF_VERBOSE_PARSE( log_debug(_("AVC packet type: %d"),
(unsigned)packettype) );
+
+ header = (packettype == 0);
+
+ // 24-bits value for composition time offset ignored
for now.
+ boost::uint8_t tmp[3];
+ _stream->read(tmp, 3);
+
+ bodyLength -= 4;
+ break;
+ }
+ default:
+ break;
}
- size_t dataPosition = _stream->tell();
-
- std::auto_ptr<EncodedVideoFrame> frame = readVideoFrame(bodyLength-1,
timestamp);
- if ( ! frame.get() )
- {
+ std::auto_ptr<EncodedVideoFrame> frame = readVideoFrame(bodyLength-1,
flvtag.timestamp);
+ if ( ! frame.get() ) {
log_error("could not read video frame?");
}
// If this is the first videoframe no info about the
// video format has been noted, so we do that now
- if ( ! _videoInfo.get() )
- {
- _videoInfo.reset( new VideoInfo(codec, 0 /* width */, 0 /*
height */, 0 /*frameRate*/, 0 /*duration*/, FLASH /*codec type*/) );
+ if ( ! _videoInfo.get() ) {
+ _videoInfo.reset( new VideoInfo(videotag.codec, 0 /* width */,
0 /* height */, 0 /*frameRate*/, 0 /*duration*/, FLASH /*codec type*/) );
if (header) {
boost::uint8_t* newbuf = new
boost::uint8_t[frame->dataSize()];
@@ -323,6 +308,7 @@
// won't mess with the parser on seek or on getBytesLoaded
boost::mutex::scoped_lock streamLock(_streamMutex);
+ if ( index_only && _indexingCompleted ) return false;
if ( _parsingComplete ) return false;
if ( _seekRequest )
@@ -331,35 +317,42 @@
_seekRequest = false;
}
- unsigned long thisTagPos = _lastParsedPosition;
+ uint64_t& position = index_only ? _nextPosToIndex : _lastParsedPosition;
+ bool& completed = index_only ? _indexingCompleted : _parsingComplete;
+
+ unsigned long thisTagPos = position;
// Seek to next frame and skip the tag size
//log_debug("FLVParser::parseNextTag seeking to %d", thisTagPos+4);
if ( _stream->seek(thisTagPos+4) )
{
log_error("FLVParser::parseNextTag: can't seek to %d",
thisTagPos+4);
- _parsingComplete=true;
+
+ completed = true;
return false;
}
//log_debug("FLVParser::parseNextTag seeked to %d", thisTagPos+4);
// Read the tag info
- boost::uint8_t tag[12];
- int actuallyRead = _stream->read(tag, 12);
+ boost::uint8_t chunk[12];
+ int actuallyRead = _stream->read(chunk, 12);
if ( actuallyRead < 12 )
{
if ( actuallyRead )
log_error("FLVParser::parseNextTag: can't read tag info
(needed 12 bytes, only got %d)", actuallyRead);
// else { assert(_stream->eof(); } ?
- _parsingComplete=true;
+
+ completed = true;
+
+ // update bytes loaded
+ boost::mutex::scoped_lock lock(_bytesLoadedMutex);
+ _bytesLoaded = _stream->tell();
return false;
}
- // Extract length and timestamp
- boost::uint32_t bodyLength = getUInt24(&tag[1]);
- boost::uint32_t timestamp = getUInt24(&tag[4]);
+ FLVTag flvtag(chunk);
- _lastParsedPosition += 15 + bodyLength;
+ position += 15 + flvtag.body_size;
bool doIndex = (_lastParsedPosition+4 > _nextPosToIndex) || index_only;
if ( doIndex )
@@ -368,25 +361,28 @@
_nextPosToIndex = _lastParsedPosition;
}
-
- if ( _lastParsedPosition > _bytesLoaded ) {
+
+ if ( position > _bytesLoaded ) {
boost::mutex::scoped_lock lock(_bytesLoadedMutex);
_bytesLoaded = _lastParsedPosition;
}
// check for empty tag
- if (bodyLength == 0) return true;
-
- if (doIndex) {
- indexTag(tag, timestamp, thisTagPos);
- if (index_only) {
- return true;
- }
- }
-
- if (tag[0] == FLV_AUDIO_TAG)
+ if (flvtag.body_size == 0) return true;
+
+ if (flvtag.type == FLV_AUDIO_TAG)
{
- std::auto_ptr<EncodedAudioFrame> frame =
parseAudioTag(bodyLength, timestamp, thisTagPos, tag);
+ FLVAudioTag audiotag(chunk[11]);
+
+ if (doIndex) {
+ indexAudioTag(flvtag, thisTagPos);
+ if (index_only) {
+ return true;
+ }
+ }
+
+
+ std::auto_ptr<EncodedAudioFrame> frame = parseAudioTag(flvtag,
audiotag, thisTagPos);
if (!frame.get()) {
return false;
}
@@ -398,9 +394,18 @@
streamLock.unlock();
pushEncodedAudioFrame(frame);
}
- else if (tag[0] == FLV_VIDEO_TAG)
+ else if (flvtag.type == FLV_VIDEO_TAG)
{
- std::auto_ptr<EncodedVideoFrame> frame =
parseVideoTag(bodyLength, timestamp, thisTagPos, tag);
+ FLVVideoTag videotag(chunk[11]);
+
+ if (doIndex) {
+ indexVideoTag(flvtag, videotag, thisTagPos);
+ if (index_only) {
+ return true;
+ }
+ }
+
+ std::auto_ptr<EncodedVideoFrame> frame = parseVideoTag(flvtag,
videotag, thisTagPos);
if (!frame.get()) {
return false;
}
@@ -413,31 +418,31 @@
pushEncodedVideoFrame(frame);
}
- else if (tag[0] == FLV_META_TAG)
+ else if (flvtag.type == FLV_META_TAG)
{
- if ( tag[11] != 2 )
+ if ( chunk[11] != 2 )
{
// ::processTags relies on the first AMF0 value being a
string...
log_unimpl(_("First byte of FLV_META_TAG is %d,
expected 0x02 (STRING AMF0 type)"),
- (int)tag[11]);
+ (int)chunk[11]);
}
// Extract information from the meta tag
- std::auto_ptr<SimpleBuffer> metaTag(new
SimpleBuffer(bodyLength-1));
- size_t actuallyRead = _stream->read(metaTag->data(),
bodyLength-1);
- if ( actuallyRead < bodyLength-1 )
+ std::auto_ptr<SimpleBuffer> metaTag(new
SimpleBuffer(flvtag.body_size-1));
+ size_t actuallyRead = _stream->read(metaTag->data(),
flvtag.body_size-1);
+ if ( actuallyRead < flvtag.body_size-1 )
{
log_error("FLVParser::parseNextTag: can't read metaTag
(%d) body (needed %d bytes, only got %d)",
- FLV_META_TAG, bodyLength, actuallyRead);
+ FLV_META_TAG, flvtag.body_size, actuallyRead);
return false;
}
metaTag->resize(actuallyRead);
boost::mutex::scoped_lock lock(_metaTagsMutex);
- _metaTags.push_back(new MetaTag(timestamp, metaTag));
+ _metaTags.push_back(new MetaTag(flvtag.timestamp, metaTag));
}
else
{
- log_error("FLVParser::parseNextTag: unknown FLV tag type %d",
(int)tag[0]);
+ log_error("FLVParser::parseNextTag: unknown FLV tag type %d",
(int)chunk[0]);
return false;
}
=== modified file 'libmedia/FLVParser.h'
--- a/libmedia/FLVParser.h 2008-10-21 15:15:10 +0000
+++ b/libmedia/FLVParser.h 2008-10-21 20:20:52 +0000
@@ -43,7 +43,6 @@
namespace media {
-
class ExtraVideoInfoFlv : public VideoInfo::ExtraInfo
{
public:
@@ -83,6 +82,60 @@
FLV_META_TAG = 0x12
};
+ struct FLVTag : public boost::noncopyable
+ {
+ FLVTag(boost::uint8_t* stream)
+ : type(stream[0]),
+ body_size(getUInt24(stream+1)),
+ timestamp(getUInt24(stream+4) | (stream[7] << 24) )
+ {}
+
+ /// Equals tagType
+ boost::uint8_t type;
+ boost::uint32_t body_size;
+ boost::uint32_t timestamp;
+ };
+
+ struct FLVAudioTag : public boost::noncopyable
+ {
+ FLVAudioTag(const boost::uint8_t& byte)
+ : codec( (byte & 0xf0) >> 4 ),
+ samplerate( flv_audio_rates[(byte & 0x0C) >> 2] ),
+ samplesize( 1 + ((byte & 0x02) >> 1)),
+ stereo( (byte & 0x01) )
+ {
+ }
+
+ /// Equals audioCodecType
+ boost::uint8_t codec;
+ boost::uint16_t samplerate;
+ boost::uint8_t samplesize;
+ bool stereo;
+ private:
+ static const boost::uint16_t flv_audio_rates[];
+ };
+
+ enum frameType
+ {
+ FLV_VIDEO_KEYFRAME = 1,
+ FLV_VIDEO_INTERLACED = 2,
+ FLV_VIDEO_DISPOSABLE = 3
+ };
+
+ struct FLVVideoTag : public boost::noncopyable
+ {
+ FLVVideoTag(const boost::uint8_t& byte)
+ : frametype( (byte & 0xf0) >> 4 ),
+ codec( byte & 0x0f )
+ {}
+
+ /// Equals frameType
+ boost::uint8_t frametype;
+ /// Equals videoCodecType
+ boost::uint8_t codec;
+ };
+
+
/// \brief
/// Create an FLV parser reading input from
@@ -123,12 +176,11 @@
///
bool parseNextTag(bool index_only);
- std::auto_ptr<EncodedAudioFrame> parseAudioTag(boost::uint32_t
bodyLength, boost::uint32_t timestamp, boost::uint32_t thisTagPos,
- const boost::uint8_t* tag);
- std::auto_ptr<EncodedVideoFrame> parseVideoTag(boost::uint32_t
bodyLength, boost::uint32_t timestamp, boost::uint32_t thisTagPos,
- const boost::uint8_t* tag);
+ std::auto_ptr<EncodedAudioFrame> parseAudioTag(const FLVTag& flvtag,
const FLVAudioTag& audiotag, boost::uint32_t thisTagPos);
+ std::auto_ptr<EncodedVideoFrame> parseVideoTag(const FLVTag& flvtag,
const FLVVideoTag& videotag, boost::uint32_t thisTagPos);
- bool indexTag(const boost::uint8_t* tag, boost::uint32_t timestamp,
boost::uint32_t thisTagPos);
+ void indexAudioTag(const FLVTag& tag, boost::uint32_t thisTagPos);
+ void indexVideoTag(const FLVTag& tag, const FLVVideoTag& videotag,
boost::uint32_t thisTagPos);
/// Parses the header of the file
bool parseHeader();
@@ -136,7 +188,7 @@
/// Reads three bytes in FLV (big endian) byte order.
/// @param in Pointer to read 3 bytes from.
/// @return 24-bit integer.
- inline boost::uint32_t getUInt24(boost::uint8_t* in);
+ static boost::uint32_t getUInt24(boost::uint8_t* in);
/// The position where the parsing should continue from.
/// Will be reset on seek, and will be protected by the _streamMutex
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r10041: More cleanups and refactoring. Restore indexing broken by last commit.,
Bastiaan Jacques <=