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