Chromium Code Reviews| Index: webrtc/modules/video_coding/generic_decoder.cc |
| diff --git a/webrtc/modules/video_coding/generic_decoder.cc b/webrtc/modules/video_coding/generic_decoder.cc |
| index 2121ab63067acdafe71e7f1cb7ceaf90c3b1196d..3dcacdd75d520e2be81236ad03ca8048f609915e 100644 |
| --- a/webrtc/modules/video_coding/generic_decoder.cc |
| +++ b/webrtc/modules/video_coding/generic_decoder.cc |
| @@ -8,11 +8,12 @@ |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| +#include "webrtc/modules/video_coding/generic_decoder.h" |
| + |
| #include "webrtc/base/checks.h" |
| #include "webrtc/base/logging.h" |
| #include "webrtc/base/trace_event.h" |
| #include "webrtc/modules/video_coding/include/video_coding.h" |
| -#include "webrtc/modules/video_coding/generic_decoder.h" |
| #include "webrtc/modules/video_coding/internal_defines.h" |
| #include "webrtc/system_wrappers/include/clock.h" |
| @@ -23,9 +24,12 @@ VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing, |
| : _clock(clock), |
| _timing(timing), |
| _timestampMap(kDecoderFrameMemoryLength), |
| - _lastReceivedPictureID(0) {} |
| + _lastReceivedPictureID(0) { |
| + decoder_thread_.DetachFromThread(); |
| +} |
| VCMDecodedFrameCallback::~VCMDecodedFrameCallback() { |
| + RTC_DCHECK(construction_thread_.CalledOnValidThread()); |
| } |
| void VCMDecodedFrameCallback::SetUserReceiveCallback( |
| @@ -37,6 +41,7 @@ void VCMDecodedFrameCallback::SetUserReceiveCallback( |
| } |
| VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| // Called on the decode thread via VCMCodecDataBase::GetDecoder. |
| // The callback must always have been set before this happens. |
| RTC_DCHECK(_receiveCallback); |
| @@ -59,16 +64,14 @@ int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, |
| void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, |
| rtc::Optional<int32_t> decode_time_ms, |
| rtc::Optional<uint8_t> qp) { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| RTC_DCHECK(_receiveCallback) << "Callback must not be null at this point"; |
| + |
| TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded", |
| "timestamp", decodedImage.timestamp()); |
| // TODO(holmer): We should improve this so that we can handle multiple |
| // callbacks from one call to Decode(). |
| - VCMFrameInformation* frameInfo; |
| - { |
| - rtc::CritScope cs(&lock_); |
| - frameInfo = _timestampMap.Pop(decodedImage.timestamp()); |
| - } |
| + VCMFrameInformation* frameInfo = _timestampMap.Pop(decodedImage.timestamp()); |
| if (frameInfo == NULL) { |
| LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping " |
| @@ -92,101 +95,117 @@ void VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, |
| int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame( |
| const uint64_t pictureId) { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId); |
| } |
| int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame( |
| const uint64_t pictureId) { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| _lastReceivedPictureID = pictureId; |
| return 0; |
| } |
| uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| return _lastReceivedPictureID; |
| } |
| void VCMDecodedFrameCallback::OnDecoderImplementationName( |
| const char* implementation_name) { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| _receiveCallback->OnDecoderImplementationName(implementation_name); |
| } |
| void VCMDecodedFrameCallback::Map(uint32_t timestamp, |
| VCMFrameInformation* frameInfo) { |
| - rtc::CritScope cs(&lock_); |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| _timestampMap.Add(timestamp, frameInfo); |
| } |
| int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) { |
| - rtc::CritScope cs(&lock_); |
| - if (_timestampMap.Pop(timestamp) == NULL) { |
| - return VCM_GENERAL_ERROR; |
| - } |
| - return VCM_OK; |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| + return _timestampMap.Pop(timestamp) == nullptr ? VCM_GENERAL_ERROR : VCM_OK; |
| } |
| VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal) |
| : _callback(NULL), |
| _frameInfos(), |
| _nextFrameInfoIdx(0), |
| - _decoder(decoder), |
| + decoder_(decoder), |
| _codecType(kVideoCodecUnknown), |
| - _isExternal(isExternal), |
| - _keyFrameDecoded(false) {} |
| + _isExternal(isExternal) {} |
| -VCMGenericDecoder::~VCMGenericDecoder() {} |
| +VCMGenericDecoder::~VCMGenericDecoder() { |
| + decoder_->Release(); |
| + if (_isExternal) |
| + decoder_.release(); |
|
stefan-webrtc
2017/03/31 13:42:07
Nice improvement. :)
tommi
2017/04/04 10:13:52
:D
|
| + |
| + RTC_DCHECK(_isExternal || !decoder_); |
| +} |
| int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings, |
| int32_t numberOfCores) { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode"); |
| _codecType = settings->codecType; |
| - return _decoder->InitDecode(settings, numberOfCores); |
| + return decoder_->InitDecode(settings, numberOfCores); |
| } |
| int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) { |
| - TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp", |
| - frame.EncodedImage()._timeStamp); |
| - _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs; |
| - _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs(); |
| - _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation(); |
| - _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]); |
| - |
| - _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength; |
| - const RTPFragmentationHeader dummy_header; |
| - int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(), |
| - &dummy_header, |
| - frame.CodecSpecific(), frame.RenderTimeMs()); |
| - |
| - _callback->OnDecoderImplementationName(_decoder->ImplementationName()); |
| - if (ret < WEBRTC_VIDEO_CODEC_OK) { |
| - LOG(LS_WARNING) << "Failed to decode frame with timestamp " |
| - << frame.TimeStamp() << ", error code: " << ret; |
| - _callback->Pop(frame.TimeStamp()); |
| - return ret; |
| - } else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT || |
| - ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) { |
| - // No output |
| - _callback->Pop(frame.TimeStamp()); |
| - } |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| + TRACE_EVENT2("webrtc", "VCMGenericDecoder::Decode", "timestamp", |
| + frame.EncodedImage()._timeStamp, "decoder", |
| + decoder_->ImplementationName()); |
| + _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs; |
| + _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs(); |
| + _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation(); |
| + _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]); |
| + |
| + _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength; |
| + const RTPFragmentationHeader dummy_header; |
| + int32_t ret = decoder_->Decode(frame.EncodedImage(), frame.MissingFrame(), |
| + &dummy_header, frame.CodecSpecific(), |
| + frame.RenderTimeMs()); |
| + |
| + // TODO(tommi): Necessary every time? |
| + // Maybe this should be the first thing the function does, and only the first |
| + // time around? |
|
stefan-webrtc
2017/03/31 13:42:07
Yes, but I think it can change on each call if it
tommi
2017/04/04 10:13:52
I'll leave it as is for now. Depending on the call
|
| + _callback->OnDecoderImplementationName(decoder_->ImplementationName()); |
| + if (ret < WEBRTC_VIDEO_CODEC_OK) { |
|
mflodman
2017/03/31 09:30:01
If it gets simpler, we can remove the return in th
tommi
2017/03/31 10:27:19
Done.
|
| + LOG(LS_WARNING) << "Failed to decode frame with timestamp " |
| + << frame.TimeStamp() << ", error code: " << ret; |
| + _callback->Pop(frame.TimeStamp()); |
| return ret; |
| -} |
| + } |
| -int32_t VCMGenericDecoder::Release() { |
| - return _decoder->Release(); |
| + if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT || |
| + ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) { |
| + // No output |
| + _callback->Pop(frame.TimeStamp()); |
| + } |
| + |
| + return ret; |
| } |
| int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback( |
| VCMDecodedFrameCallback* callback) { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| _callback = callback; |
| - return _decoder->RegisterDecodeCompleteCallback(callback); |
| + return decoder_->RegisterDecodeCompleteCallback(callback); |
| } |
| -bool VCMGenericDecoder::External() const { |
| - return _isExternal; |
| +bool VCMGenericDecoder::PrefersLateDecoding() const { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| + return decoder_->PrefersLateDecoding(); |
| } |
| -bool VCMGenericDecoder::PrefersLateDecoding() const { |
| - return _decoder->PrefersLateDecoding(); |
| +#if defined(WEBRTC_ANDROID) |
| +void VCMGenericDecoder::PollDecodedFrames() { |
| + RTC_DCHECK_RUN_ON(&decoder_thread_); |
| + decoder_->PollDecodedFrames(); |
| } |
| +#endif |
| } // namespace webrtc |