Home | History | Annotate | Download | only in source
      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 
     17 namespace webrtc {
     18 
     19 VCMDecodedFrameCallback::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 
     31 VCMDecodedFrameCallback::~VCMDecodedFrameCallback()
     32 {
     33     delete _critSect;
     34 }
     35 
     36 void VCMDecodedFrameCallback::SetUserReceiveCallback(
     37     VCMReceiveCallback* receiveCallback)
     38 {
     39     CriticalSectionScoped cs(_critSect);
     40     _receiveCallback = receiveCallback;
     41 }
     42 
     43 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback()
     44 {
     45     CriticalSectionScoped cs(_critSect);
     46     return _receiveCallback;
     47 }
     48 
     49 int32_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 
     81 int32_t
     82 VCMDecodedFrameCallback::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 
     93 int32_t
     94 VCMDecodedFrameCallback::ReceivedDecodedFrame(const uint64_t pictureId)
     95 {
     96     _lastReceivedPictureID = pictureId;
     97     return 0;
     98 }
     99 
    100 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const
    101 {
    102     return _lastReceivedPictureID;
    103 }
    104 
    105 int32_t VCMDecodedFrameCallback::Map(uint32_t timestamp, VCMFrameInformation* frameInfo)
    106 {
    107     CriticalSectionScoped cs(_critSect);
    108     return _timestampMap.Add(timestamp, frameInfo);
    109 }
    110 
    111 int32_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 
    121 VCMGenericDecoder::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 
    133 VCMGenericDecoder::~VCMGenericDecoder()
    134 {
    135 }
    136 
    137 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings,
    138                                       int32_t numberOfCores)
    139 {
    140     _codecType = settings->codecType;
    141 
    142     return _decoder.InitDecode(settings, numberOfCores);
    143 }
    144 
    145 int32_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 
    175 int32_t
    176 VCMGenericDecoder::Release()
    177 {
    178     return _decoder.Release();
    179 }
    180 
    181 int32_t VCMGenericDecoder::Reset()
    182 {
    183     return _decoder.Reset();
    184 }
    185 
    186 int32_t VCMGenericDecoder::SetCodecConfigParameters(const uint8_t* buffer, int32_t size)
    187 {
    188     return _decoder.SetCodecConfigParameters(buffer, size);
    189 }
    190 
    191 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(VCMDecodedFrameCallback* callback)
    192 {
    193     _callback = callback;
    194     return _decoder.RegisterDecodeCompleteCallback(callback);
    195 }
    196 
    197 bool VCMGenericDecoder::External() const
    198 {
    199     return _isExternal;
    200 }
    201 
    202 }  // namespace
    203