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(); } }
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; }
// 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; }