1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/interface/video_coding.h" 12a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/generic_decoder.h" 13a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/internal_defines.h" 141bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org#include "webrtc/system_wrappers/interface/clock.h" 158edcccef11eabb0dd98a061c9d640b2b7743609estefan@webrtc.org#include "webrtc/system_wrappers/interface/logging.h" 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming& timing, 201bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org Clock* clock) 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org: 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_critSect(CriticalSectionWrapper::CreateCriticalSection()), 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_clock(clock), 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_receiveCallback(NULL), 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_timing(timing), 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_timestampMap(kDecoderFrameMemoryLength), 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_lastReceivedPictureID(0) 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMDecodedFrameCallback::~VCMDecodedFrameCallback() 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _critSect; 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid VCMDecodedFrameCallback::SetUserReceiveCallback( 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VCMReceiveCallback* receiveCallback) 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_critSect); 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _receiveCallback = receiveCallback; 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 43d893b3fbd858898bd280f94a74854a86a6b91888wuchengli@chromium.orgVCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() 44d893b3fbd858898bd280f94a74854a86a6b91888wuchengli@chromium.org{ 45d893b3fbd858898bd280f94a74854a86a6b91888wuchengli@chromium.org CriticalSectionScoped cs(_critSect); 46d893b3fbd858898bd280f94a74854a86a6b91888wuchengli@chromium.org return _receiveCallback; 47d893b3fbd858898bd280f94a74854a86a6b91888wuchengli@chromium.org} 48d893b3fbd858898bd280f94a74854a86a6b91888wuchengli@chromium.org 49dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t VCMDecodedFrameCallback::Decoded(I420VideoFrame& decodedImage) 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(holmer): We should improve this so that we can handle multiple 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // callbacks from one call to Decode(). 533b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org VCMFrameInformation* frameInfo; 543b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org VCMReceiveCallback* callback; 553b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org { 563b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org CriticalSectionScoped cs(_critSect); 573b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org frameInfo = static_cast<VCMFrameInformation*>( 583b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org _timestampMap.Pop(decodedImage.timestamp())); 593b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org callback = _receiveCallback; 603b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org } 6107818d1134a8fc4272ca0dd108d8f35d1753f9c3stefan@webrtc.org 6207818d1134a8fc4272ca0dd108d8f35d1753f9c3stefan@webrtc.org if (frameInfo == NULL) { 6307818d1134a8fc4272ca0dd108d8f35d1753f9c3stefan@webrtc.org LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping " 6407818d1134a8fc4272ca0dd108d8f35d1753f9c3stefan@webrtc.org "this one."; 6507818d1134a8fc4272ca0dd108d8f35d1753f9c3stefan@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 6607818d1134a8fc4272ca0dd108d8f35d1753f9c3stefan@webrtc.org } 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _timing.StopDecodeTimer( 693bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org decodedImage.timestamp(), 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frameInfo->decodeStartTimeMs, 711bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org _clock->TimeInMilliseconds()); 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 733b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org if (callback != NULL) 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 753b35ec630eb4064c4e0333fa975e0607161f5814fischman@webrtc.org decodedImage.set_render_time_ms(frameInfo->renderTimeMs); 768edcccef11eabb0dd98a061c9d640b2b7743609estefan@webrtc.org callback->FrameToRender(decodedImage); 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return WEBRTC_VIDEO_CODEC_OK; 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 81dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMDecodedFrameCallback::ReceivedDecodedReferenceFrame( 83dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint64_t pictureId) 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_critSect); 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_receiveCallback != NULL) 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId); 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 93dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t 94dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMDecodedFrameCallback::ReceivedDecodedFrame(const uint64_t pictureId) 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastReceivedPictureID = pictureId; 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 100dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orguint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _lastReceivedPictureID; 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 105dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t VCMDecodedFrameCallback::Map(uint32_t timestamp, VCMFrameInformation* frameInfo) 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_critSect); 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _timestampMap.Add(timestamp, frameInfo); 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 111dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_critSect); 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_timestampMap.Pop(timestamp) == NULL) 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return VCM_GENERAL_ERROR; 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return VCM_OK; 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1218edcccef11eabb0dd98a061c9d640b2b7743609estefan@webrtc.orgVCMGenericDecoder::VCMGenericDecoder(VideoDecoder& decoder, bool isExternal) 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org: 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_callback(NULL), 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_frameInfos(), 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_nextFrameInfoIdx(0), 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_decoder(decoder), 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_codecType(kVideoCodecUnknown), 1288edcccef11eabb0dd98a061c9d640b2b7743609estefan@webrtc.org_isExternal(isExternal), 1298edcccef11eabb0dd98a061c9d640b2b7743609estefan@webrtc.org_keyFrameDecoded(false) 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMGenericDecoder::~VCMGenericDecoder() 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 137dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings, 138e2e033adc5f58b3ffe6c3c7e67b245ee66e1a607mikhal@webrtc.org int32_t numberOfCores) 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _codecType = settings->codecType; 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _decoder.InitDecode(settings, numberOfCores); 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 145dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int64_t nowMs) 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs; 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs(); 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]); 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength; 153dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org int32_t ret = _decoder.Decode(frame.EncodedImage(), 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame.MissingFrame(), 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame.FragmentationHeader(), 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame.CodecSpecific(), 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame.RenderTimeMs()); 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret < WEBRTC_VIDEO_CODEC_OK) 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1618edcccef11eabb0dd98a061c9d640b2b7743609estefan@webrtc.org LOG(LS_WARNING) << "Failed to decode frame with timestamp " 1628edcccef11eabb0dd98a061c9d640b2b7743609estefan@webrtc.org << frame.TimeStamp() << ", error code: " << ret; 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _callback->Pop(frame.TimeStamp()); 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ret; 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT || 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // No output 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _callback->Pop(frame.TimeStamp()); 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ret; 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 175dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMGenericDecoder::Release() 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _decoder.Release(); 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 181dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t VCMGenericDecoder::Reset() 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _decoder.Reset(); 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 186dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t VCMGenericDecoder::SetCodecConfigParameters(const uint8_t* buffer, int32_t size) 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _decoder.SetCodecConfigParameters(buffer, size); 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 191dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgint32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(VCMDecodedFrameCallback* callback) 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _callback = callback; 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _decoder.RegisterDecodeCompleteCallback(callback); 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMGenericDecoder::External() const 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _isExternal; 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2023b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org} // namespace 203