Home | History | Annotate | Download | only in video_coding
      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