Example #1
0
void
MediaParserGst::emitEncodedFrames()
{
    while (!_enc_audio_frames.empty()) {
        EncodedAudioFrame* frame = _enc_audio_frames.front();
        pushEncodedAudioFrame(std::auto_ptr<EncodedAudioFrame>(frame));
       _enc_audio_frames.pop_front();
    }
    
    while (!_enc_video_frames.empty()) {
        EncodedVideoFrame* frame = _enc_video_frames.front();
        pushEncodedVideoFrame(std::auto_ptr<EncodedVideoFrame>(frame));
       _enc_video_frames.pop_front();
    }
}
Example #2
0
bool
MediaParserGst::emitEncodedFrames()
{
    if (_enc_audio_frames.empty() && _enc_video_frames.empty()) {
        return false;
    }

    while (!_enc_audio_frames.empty()) {
        EncodedAudioFrame* frame = _enc_audio_frames.front();
        pushEncodedAudioFrame(std::auto_ptr<EncodedAudioFrame>(frame));
       _enc_audio_frames.pop_front();
    }
    
    while (!_enc_video_frames.empty()) {
        EncodedVideoFrame* frame = _enc_video_frames.front();
        pushEncodedVideoFrame(std::auto_ptr<EncodedVideoFrame>(frame));
       _enc_video_frames.pop_front();
    }

    return true;
}
Example #3
0
// would be called by parser thread
bool
FLVParser::parseNextTag(bool index_only)
{
	// lock the stream while reading from it, so actionscript
	// 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 )
	{
		clearBuffers();
		_seekRequest = false;
	}

	boost::uint64_t& position = index_only ? _nextPosToIndex : _lastParsedPosition;
	bool& completed = index_only ? _indexingCompleted : _parsingComplete;

	//log_debug("parseNextTag: _lastParsedPosition:%d, _nextPosToIndex:%d, index_only:%d", _lastParsedPosition, _nextPosToIndex, index_only);

	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);

		completed = true;
		return false;
	}
	//log_debug("FLVParser::parseNextTag seeked to %d", thisTagPos+4);

	// Read the tag info
	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(); } ?

		completed = true;

        // update bytes loaded
        boost::mutex::scoped_lock lock(_bytesLoadedMutex);
		_bytesLoaded = _stream->tell(); 
		return false;
	}

	FLVTag flvtag(chunk);

    // May be _lastParsedPosition OR _nextPosToIndex
    position += 15 + flvtag.body_size; 

	bool doIndex = (_lastParsedPosition+4 > _nextPosToIndex) || index_only;
	if ( _lastParsedPosition > _nextPosToIndex )
	{
		//log_debug("::parseNextTag setting _nextPosToIndex=%d", _lastParsedPosition+4);
		_nextPosToIndex = _lastParsedPosition;
	}

	if ( position > _bytesLoaded ) {
		boost::mutex::scoped_lock lock(_bytesLoadedMutex);
		_bytesLoaded = position;
	}

	// check for empty tag
	if (flvtag.body_size == 0) return true;

	if (flvtag.type == FLV_AUDIO_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;
		}
		// Release the stream lock 
		// *before* pushing the frame as that 
		// might block us waiting for buffers flush
		// the _qMutex...
		// We've done using the stream for this tag parsing anyway
		streamLock.unlock();
		pushEncodedAudioFrame(frame);
	}
	else if (flvtag.type == FLV_VIDEO_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;
		}

		// Release the stream lock 
		// *before* pushing the frame as that 
		// might block us waiting for buffers flush
		// the _qMutex...
		streamLock.unlock();
		pushEncodedVideoFrame(frame);

	}
	else if (flvtag.type == FLV_META_TAG)
	{
		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)"),
                    static_cast<int>(chunk[11]));
		}
		// Extract information from the meta tag
		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, flvtag.body_size, actuallyRead);
			return false;
		}
		metaTag->resize(actuallyRead);

		boost::uint32_t terminus = getUInt24(metaTag->data() +
                actuallyRead - 3);

        if (terminus != 9) {
			log_error(_("Corrupt FLV: Meta tag unterminated!"));
		}

		boost::mutex::scoped_lock lock(_metaTagsMutex);
		_metaTags.insert(std::make_pair(flvtag.timestamp, MetaTags::mapped_type(metaTag)));
	}
	else
	{
		log_error(_("FLVParser::parseNextTag: unknown FLV tag type %d"),
                (int)chunk[0]);
		return false;
	}

	_stream->read(chunk, 4);
	boost::uint32_t prevtagsize = chunk[0] << 24 | chunk[1] << 16 |
        chunk[2] << 8 | chunk[3];
	if (prevtagsize != flvtag.body_size + 11) {
		log_error(_("Corrupt FLV: previous tag size record (%1%) unexpected "
                    "(actual size: %2%)"), prevtagsize, flvtag.body_size + 11);
	}

	return true;
}