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/modules/video_coding/main/interface/video_coding.h" 12#include "webrtc/modules/video_coding/main/source/generic_decoder.h" 13#include "webrtc/modules/video_coding/main/source/internal_defines.h" 14#include "webrtc/system_wrappers/interface/clock.h" 15#include "webrtc/system_wrappers/interface/logging.h" 16 17namespace webrtc { 18 19VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming& timing, 20 Clock* clock) 21: 22_critSect(CriticalSectionWrapper::CreateCriticalSection()), 23_clock(clock), 24_receiveCallback(NULL), 25_timing(timing), 26_timestampMap(kDecoderFrameMemoryLength), 27_lastReceivedPictureID(0) 28{ 29} 30 31VCMDecodedFrameCallback::~VCMDecodedFrameCallback() 32{ 33 delete _critSect; 34} 35 36void VCMDecodedFrameCallback::SetUserReceiveCallback( 37 VCMReceiveCallback* receiveCallback) 38{ 39 CriticalSectionScoped cs(_critSect); 40 _receiveCallback = receiveCallback; 41} 42 43VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() 44{ 45 CriticalSectionScoped cs(_critSect); 46 return _receiveCallback; 47} 48 49int32_t VCMDecodedFrameCallback::Decoded(I420VideoFrame& decodedImage) 50{ 51 // TODO(holmer): We should improve this so that we can handle multiple 52 // callbacks from one call to Decode(). 53 VCMFrameInformation* frameInfo; 54 VCMReceiveCallback* callback; 55 { 56 CriticalSectionScoped cs(_critSect); 57 frameInfo = static_cast<VCMFrameInformation*>( 58 _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 _timing.StopDecodeTimer( 69 decodedImage.timestamp(), 70 frameInfo->decodeStartTimeMs, 71 _clock->TimeInMilliseconds()); 72 73 if (callback != NULL) 74 { 75 decodedImage.set_render_time_ms(frameInfo->renderTimeMs); 76 callback->FrameToRender(decodedImage); 77 } 78 return WEBRTC_VIDEO_CODEC_OK; 79} 80 81int32_t 82VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame( 83 const uint64_t pictureId) 84{ 85 CriticalSectionScoped cs(_critSect); 86 if (_receiveCallback != NULL) 87 { 88 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId); 89 } 90 return -1; 91} 92 93int32_t 94VCMDecodedFrameCallback::ReceivedDecodedFrame(const uint64_t pictureId) 95{ 96 _lastReceivedPictureID = pictureId; 97 return 0; 98} 99 100uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const 101{ 102 return _lastReceivedPictureID; 103} 104 105int32_t VCMDecodedFrameCallback::Map(uint32_t timestamp, VCMFrameInformation* frameInfo) 106{ 107 CriticalSectionScoped cs(_critSect); 108 return _timestampMap.Add(timestamp, frameInfo); 109} 110 111int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) 112{ 113 CriticalSectionScoped cs(_critSect); 114 if (_timestampMap.Pop(timestamp) == NULL) 115 { 116 return VCM_GENERAL_ERROR; 117 } 118 return VCM_OK; 119} 120 121VCMGenericDecoder::VCMGenericDecoder(VideoDecoder& decoder, bool isExternal) 122: 123_callback(NULL), 124_frameInfos(), 125_nextFrameInfoIdx(0), 126_decoder(decoder), 127_codecType(kVideoCodecUnknown), 128_isExternal(isExternal), 129_keyFrameDecoded(false) 130{ 131} 132 133VCMGenericDecoder::~VCMGenericDecoder() 134{ 135} 136 137int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings, 138 int32_t numberOfCores) 139{ 140 _codecType = settings->codecType; 141 142 return _decoder.InitDecode(settings, numberOfCores); 143} 144 145int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, 146 int64_t nowMs) 147{ 148 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs; 149 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs(); 150 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]); 151 152 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength; 153 int32_t ret = _decoder.Decode(frame.EncodedImage(), 154 frame.MissingFrame(), 155 frame.FragmentationHeader(), 156 frame.CodecSpecific(), 157 frame.RenderTimeMs()); 158 159 if (ret < WEBRTC_VIDEO_CODEC_OK) 160 { 161 LOG(LS_WARNING) << "Failed to decode frame with timestamp " 162 << frame.TimeStamp() << ", error code: " << ret; 163 _callback->Pop(frame.TimeStamp()); 164 return ret; 165 } 166 else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT || 167 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) 168 { 169 // No output 170 _callback->Pop(frame.TimeStamp()); 171 } 172 return ret; 173} 174 175int32_t 176VCMGenericDecoder::Release() 177{ 178 return _decoder.Release(); 179} 180 181int32_t VCMGenericDecoder::Reset() 182{ 183 return _decoder.Reset(); 184} 185 186int32_t VCMGenericDecoder::SetCodecConfigParameters(const uint8_t* buffer, int32_t size) 187{ 188 return _decoder.SetCodecConfigParameters(buffer, size); 189} 190 191int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(VCMDecodedFrameCallback* callback) 192{ 193 _callback = callback; 194 return _decoder.RegisterDecodeCompleteCallback(callback); 195} 196 197bool VCMGenericDecoder::External() const 198{ 199 return _isExternal; 200} 201 202} // namespace 203