aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules/video_coding/generic_decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/modules/video_coding/generic_decoder.cc')
-rw-r--r--webrtc/modules/video_coding/generic_decoder.cc192
1 files changed, 192 insertions, 0 deletions
diff --git a/webrtc/modules/video_coding/generic_decoder.cc b/webrtc/modules/video_coding/generic_decoder.cc
new file mode 100644
index 0000000000..5cbe0f5ba0
--- /dev/null
+++ b/webrtc/modules/video_coding/generic_decoder.cc
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#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"
+
+namespace webrtc {
+
+VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing,
+ Clock* clock)
+ : _critSect(CriticalSectionWrapper::CreateCriticalSection()),
+ _clock(clock),
+ _receiveCallback(NULL),
+ _timing(timing),
+ _timestampMap(kDecoderFrameMemoryLength),
+ _lastReceivedPictureID(0) {}
+
+VCMDecodedFrameCallback::~VCMDecodedFrameCallback() {
+ delete _critSect;
+}
+
+void VCMDecodedFrameCallback::SetUserReceiveCallback(
+ VCMReceiveCallback* receiveCallback) {
+ CriticalSectionScoped cs(_critSect);
+ _receiveCallback = receiveCallback;
+}
+
+VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() {
+ CriticalSectionScoped cs(_critSect);
+ return _receiveCallback;
+}
+
+int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) {
+ return Decoded(decodedImage, -1);
+}
+
+int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage,
+ int64_t decode_time_ms) {
+ 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;
+ VCMReceiveCallback* callback;
+ {
+ CriticalSectionScoped cs(_critSect);
+ frameInfo = _timestampMap.Pop(decodedImage.timestamp());
+ callback = _receiveCallback;
+ }
+
+ if (frameInfo == NULL) {
+ LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping "
+ "this one.";
+ return WEBRTC_VIDEO_CODEC_OK;
+ }
+
+ const int64_t now_ms = _clock->TimeInMilliseconds();
+ if (decode_time_ms < 0) {
+ decode_time_ms =
+ static_cast<int32_t>(now_ms - frameInfo->decodeStartTimeMs);
+ }
+ _timing->StopDecodeTimer(decodedImage.timestamp(), decode_time_ms, now_ms,
+ frameInfo->renderTimeMs);
+
+ if (callback != NULL) {
+ decodedImage.set_render_time_ms(frameInfo->renderTimeMs);
+ decodedImage.set_rotation(frameInfo->rotation);
+ callback->FrameToRender(decodedImage);
+ }
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame(
+ const uint64_t pictureId) {
+ CriticalSectionScoped cs(_critSect);
+ if (_receiveCallback != NULL) {
+ return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId);
+ }
+ return -1;
+}
+
+int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame(
+ const uint64_t pictureId) {
+ _lastReceivedPictureID = pictureId;
+ return 0;
+}
+
+uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const {
+ return _lastReceivedPictureID;
+}
+
+void VCMDecodedFrameCallback::OnDecoderImplementationName(
+ const char* implementation_name) {
+ CriticalSectionScoped cs(_critSect);
+ if (_receiveCallback)
+ _receiveCallback->OnDecoderImplementationName(implementation_name);
+}
+
+void VCMDecodedFrameCallback::Map(uint32_t timestamp,
+ VCMFrameInformation* frameInfo) {
+ CriticalSectionScoped cs(_critSect);
+ _timestampMap.Add(timestamp, frameInfo);
+}
+
+int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) {
+ CriticalSectionScoped cs(_critSect);
+ if (_timestampMap.Pop(timestamp) == NULL) {
+ return VCM_GENERAL_ERROR;
+ }
+ return VCM_OK;
+}
+
+VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal)
+ : _callback(NULL),
+ _frameInfos(),
+ _nextFrameInfoIdx(0),
+ _decoder(decoder),
+ _codecType(kVideoCodecUnknown),
+ _isExternal(isExternal),
+ _keyFrameDecoded(false) {}
+
+VCMGenericDecoder::~VCMGenericDecoder() {}
+
+int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
+ int32_t numberOfCores) {
+ TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode");
+ _codecType = settings->codecType;
+
+ 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;
+ int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(),
+ frame.FragmentationHeader(),
+ 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());
+ }
+ return ret;
+}
+
+int32_t VCMGenericDecoder::Release() {
+ return _decoder->Release();
+}
+
+int32_t VCMGenericDecoder::Reset() {
+ return _decoder->Reset();
+}
+
+int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(
+ VCMDecodedFrameCallback* callback) {
+ _callback = callback;
+ return _decoder->RegisterDecodeCompleteCallback(callback);
+}
+
+bool VCMGenericDecoder::External() const {
+ return _isExternal;
+}
+
+bool VCMGenericDecoder::PrefersLateDecoding() const {
+ return _decoder->PrefersLateDecoding();
+}
+
+} // namespace webrtc