1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/base/logging.h" 12 #include "webrtc/base/trace_event.h" 13 #include "webrtc/modules/video_coding/include/video_coding.h" 14 #include "webrtc/modules/video_coding/generic_decoder.h" 15 #include "webrtc/modules/video_coding/internal_defines.h" 16 #include "webrtc/system_wrappers/include/clock.h" 17 18 namespace webrtc { 19 20 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming* timing, 21 Clock* clock) 22 : _critSect(CriticalSectionWrapper::CreateCriticalSection()), 23 _clock(clock), 24 _receiveCallback(NULL), 25 _timing(timing), 26 _timestampMap(kDecoderFrameMemoryLength), 27 _lastReceivedPictureID(0) {} 28 29 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() { 30 delete _critSect; 31 } 32 33 void VCMDecodedFrameCallback::SetUserReceiveCallback( 34 VCMReceiveCallback* receiveCallback) { 35 CriticalSectionScoped cs(_critSect); 36 _receiveCallback = receiveCallback; 37 } 38 39 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() { 40 CriticalSectionScoped cs(_critSect); 41 return _receiveCallback; 42 } 43 44 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage) { 45 return Decoded(decodedImage, -1); 46 } 47 48 int32_t VCMDecodedFrameCallback::Decoded(VideoFrame& decodedImage, 49 int64_t decode_time_ms) { 50 TRACE_EVENT_INSTANT1("webrtc", "VCMDecodedFrameCallback::Decoded", 51 "timestamp", decodedImage.timestamp()); 52 // TODO(holmer): We should improve this so that we can handle multiple 53 // callbacks from one call to Decode(). 54 VCMFrameInformation* frameInfo; 55 VCMReceiveCallback* callback; 56 { 57 CriticalSectionScoped cs(_critSect); 58 frameInfo = _timestampMap.Pop(decodedImage.timestamp()); 59 callback = _receiveCallback; 60 } 61 62 if (frameInfo == NULL) { 63 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping " 64 "this one."; 65 return WEBRTC_VIDEO_CODEC_OK; 66 } 67 68 const int64_t now_ms = _clock->TimeInMilliseconds(); 69 if (decode_time_ms < 0) { 70 decode_time_ms = 71 static_cast<int32_t>(now_ms - frameInfo->decodeStartTimeMs); 72 } 73 _timing->StopDecodeTimer(decodedImage.timestamp(), decode_time_ms, now_ms, 74 frameInfo->renderTimeMs); 75 76 if (callback != NULL) { 77 decodedImage.set_render_time_ms(frameInfo->renderTimeMs); 78 decodedImage.set_rotation(frameInfo->rotation); 79 callback->FrameToRender(decodedImage); 80 } 81 return WEBRTC_VIDEO_CODEC_OK; 82 } 83 84 int32_t VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame( 85 const uint64_t pictureId) { 86 CriticalSectionScoped cs(_critSect); 87 if (_receiveCallback != NULL) { 88 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId); 89 } 90 return -1; 91 } 92 93 int32_t VCMDecodedFrameCallback::ReceivedDecodedFrame( 94 const uint64_t pictureId) { 95 _lastReceivedPictureID = pictureId; 96 return 0; 97 } 98 99 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const { 100 return _lastReceivedPictureID; 101 } 102 103 void VCMDecodedFrameCallback::OnDecoderImplementationName( 104 const char* implementation_name) { 105 CriticalSectionScoped cs(_critSect); 106 if (_receiveCallback) 107 _receiveCallback->OnDecoderImplementationName(implementation_name); 108 } 109 110 void VCMDecodedFrameCallback::Map(uint32_t timestamp, 111 VCMFrameInformation* frameInfo) { 112 CriticalSectionScoped cs(_critSect); 113 _timestampMap.Add(timestamp, frameInfo); 114 } 115 116 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) { 117 CriticalSectionScoped cs(_critSect); 118 if (_timestampMap.Pop(timestamp) == NULL) { 119 return VCM_GENERAL_ERROR; 120 } 121 return VCM_OK; 122 } 123 124 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder* decoder, bool isExternal) 125 : _callback(NULL), 126 _frameInfos(), 127 _nextFrameInfoIdx(0), 128 _decoder(decoder), 129 _codecType(kVideoCodecUnknown), 130 _isExternal(isExternal), 131 _keyFrameDecoded(false) {} 132 133 VCMGenericDecoder::~VCMGenericDecoder() {} 134 135 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings, 136 int32_t numberOfCores) { 137 TRACE_EVENT0("webrtc", "VCMGenericDecoder::InitDecode"); 138 _codecType = settings->codecType; 139 140 return _decoder->InitDecode(settings, numberOfCores); 141 } 142 143 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, int64_t nowMs) { 144 TRACE_EVENT1("webrtc", "VCMGenericDecoder::Decode", "timestamp", 145 frame.EncodedImage()._timeStamp); 146 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs; 147 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs(); 148 _frameInfos[_nextFrameInfoIdx].rotation = frame.rotation(); 149 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]); 150 151 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength; 152 int32_t ret = _decoder->Decode(frame.EncodedImage(), frame.MissingFrame(), 153 frame.FragmentationHeader(), 154 frame.CodecSpecific(), frame.RenderTimeMs()); 155 156 _callback->OnDecoderImplementationName(_decoder->ImplementationName()); 157 if (ret < WEBRTC_VIDEO_CODEC_OK) { 158 LOG(LS_WARNING) << "Failed to decode frame with timestamp " 159 << frame.TimeStamp() << ", error code: " << ret; 160 _callback->Pop(frame.TimeStamp()); 161 return ret; 162 } else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT || 163 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) { 164 // No output 165 _callback->Pop(frame.TimeStamp()); 166 } 167 return ret; 168 } 169 170 int32_t VCMGenericDecoder::Release() { 171 return _decoder->Release(); 172 } 173 174 int32_t VCMGenericDecoder::Reset() { 175 return _decoder->Reset(); 176 } 177 178 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback( 179 VCMDecodedFrameCallback* callback) { 180 _callback = callback; 181 return _decoder->RegisterDecodeCompleteCallback(callback); 182 } 183 184 bool VCMGenericDecoder::External() const { 185 return _isExternal; 186 } 187 188 bool VCMGenericDecoder::PrefersLateDecoding() const { 189 return _decoder->PrefersLateDecoding(); 190 } 191 192 } // namespace webrtc 193