/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * tb_I420_codec.cc * */ #include "tb_I420_codec.h" #include #include #include tbI420Encoder::tbI420Encoder() : _inited(false), _encodedImage(), _encodedCompleteCallback(NULL) { // memset(&_functionCalls, 0, sizeof(_functionCalls)); } tbI420Encoder::~tbI420Encoder() { _inited = false; if (_encodedImage._buffer != NULL) { delete[] _encodedImage._buffer; _encodedImage._buffer = NULL; } } WebRtc_Word32 tbI420Encoder::VersionStatic(WebRtc_Word8* version, WebRtc_Word32 length) { const WebRtc_Word8* str = "I420 version 1.0.0\n"; WebRtc_Word32 verLen = (WebRtc_Word32) strlen(str); if (verLen > length) { return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; } strncpy(version, str, length); return verLen; } WebRtc_Word32 tbI420Encoder::Version(WebRtc_Word8 *version, WebRtc_Word32 length) const { return VersionStatic(version, length); } WebRtc_Word32 tbI420Encoder::Release() { _functionCalls.Release++; // should allocate an encoded frame and then release it here, for that we // actaully need an init flag if (_encodedImage._buffer != NULL) { delete[] _encodedImage._buffer; _encodedImage._buffer = NULL; } _inited = false; return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Encoder::Reset() { _functionCalls.Reset++; if (!_inited) { return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Encoder::InitEncode(const webrtc::VideoCodec* inst, WebRtc_Word32 /*numberOfCores*/, WebRtc_UWord32 /*maxPayloadSize */) { _functionCalls.InitEncode++; if (inst == NULL) { return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; } if (inst->width < 1 || inst->height < 1) { return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; } // allocating encoded memory if (_encodedImage._buffer != NULL) { delete[] _encodedImage._buffer; _encodedImage._buffer = NULL; _encodedImage._size = 0; } const WebRtc_UWord32 newSize = (3 * inst->width * inst->height) >> 1; WebRtc_UWord8* newBuffer = new WebRtc_UWord8[newSize]; if (newBuffer == NULL) { return WEBRTC_VIDEO_CODEC_MEMORY; } _encodedImage._size = newSize; _encodedImage._buffer = newBuffer; // if no memeory allocation, no point to init _inited = true; return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Encoder::Encode(const webrtc::RawImage& inputImage, const void* codecSpecificInfo /*= NULL*/, webrtc::VideoFrameType frameType /*= webrtc::kDeltaFrame*/) { _functionCalls.Encode++; if (!_inited) { return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } if (_encodedCompleteCallback == NULL) { return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } _encodedImage._frameType = webrtc::kKeyFrame; // no coding _encodedImage._timeStamp = inputImage._timeStamp; _encodedImage._encodedHeight = inputImage._height; _encodedImage._encodedWidth = inputImage._width; if (inputImage._length > _encodedImage._size) { // allocating encoded memory if (_encodedImage._buffer != NULL) { delete[] _encodedImage._buffer; _encodedImage._buffer = NULL; _encodedImage._size = 0; } const WebRtc_UWord32 newSize = (3 * _encodedImage._encodedWidth * _encodedImage._encodedHeight) >> 1; WebRtc_UWord8* newBuffer = new WebRtc_UWord8[newSize]; if (newBuffer == NULL) { return WEBRTC_VIDEO_CODEC_MEMORY; } _encodedImage._size = newSize; _encodedImage._buffer = newBuffer; } assert(_encodedImage._size >= inputImage._length); memcpy(_encodedImage._buffer, inputImage._buffer, inputImage._length); _encodedImage._length = inputImage._length; _encodedCompleteCallback->Encoded(_encodedImage); return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Encoder::RegisterEncodeCompleteCallback( webrtc::EncodedImageCallback* callback) { _functionCalls.RegisterEncodeCompleteCallback++; _encodedCompleteCallback = callback; return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Encoder::SetPacketLoss(WebRtc_UWord32 packetLoss) { _functionCalls.SetPacketLoss++; return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Encoder::SetRates(WebRtc_UWord32 newBitRate, WebRtc_UWord32 frameRate) { _functionCalls.SetRates++; return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Encoder::SetPeriodicKeyFrames(bool enable) { _functionCalls.SetPeriodicKeyFrames++; return WEBRTC_VIDEO_CODEC_ERROR; } WebRtc_Word32 tbI420Encoder::CodecConfigParameters(WebRtc_UWord8* /*buffer*/, WebRtc_Word32 /*size*/) { _functionCalls.CodecConfigParameters++; return WEBRTC_VIDEO_CODEC_ERROR; } tbI420Encoder::FunctionCalls tbI420Encoder::GetFunctionCalls() { return _functionCalls; } tbI420Decoder::tbI420Decoder(): _decodedImage(), _width(0), _height(0), _inited(false), _decodeCompleteCallback(NULL) { memset(&_functionCalls, 0, sizeof(_functionCalls)); } tbI420Decoder::~tbI420Decoder() { Release(); } WebRtc_Word32 tbI420Decoder::Reset() { _functionCalls.Reset++; return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Decoder::InitDecode(const webrtc::VideoCodec* inst, WebRtc_Word32 /*numberOfCores */) { _functionCalls.InitDecode++; if (inst == NULL) { return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; } else if (inst->width < 1 || inst->height < 1) { return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; } _width = inst->width; _height = inst->height; _inited = true; return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Decoder::Decode(const webrtc::EncodedImage& inputImage, bool /*missingFrames*/, const void* /*codecSpecificInfWord64o*/, WebRtc_Word64 /*renderTimeMs*/) { _functionCalls.Decode++; if (inputImage._buffer == NULL) { return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; } if (_decodeCompleteCallback == NULL) { return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } if (inputImage._length <= 0) { return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; } if (!_inited) { return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } // Allocate memory for decoded image if (_decodedImage._buffer != NULL) { delete[] _decodedImage._buffer; _decodedImage._buffer = NULL; _decodedImage._size = 0; } if (_decodedImage._buffer == NULL) { const WebRtc_UWord32 newSize = (3 * _width * _height) >> 1; WebRtc_UWord8* newBuffer = new WebRtc_UWord8[newSize]; if (newBuffer == NULL) { return WEBRTC_VIDEO_CODEC_MEMORY; } _decodedImage._size = newSize; _decodedImage._buffer = newBuffer; } // Set decoded image parameters _decodedImage._height = _height; _decodedImage._width = _width; _decodedImage._timeStamp = inputImage._timeStamp; assert(_decodedImage._size >= inputImage._length); memcpy(_decodedImage._buffer, inputImage._buffer, inputImage._length); _decodedImage._length = inputImage._length; //_decodedImage._buffer = inputImage._buffer; _decodeCompleteCallback->Decoded(_decodedImage); return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Decoder::RegisterDecodeCompleteCallback( webrtc::DecodedImageCallback* callback) { _functionCalls.RegisterDecodeCompleteCallback++; _decodeCompleteCallback = callback; return WEBRTC_VIDEO_CODEC_OK; } WebRtc_Word32 tbI420Decoder::Release() { _functionCalls.Release++; if (_decodedImage._buffer != NULL) { delete[] _decodedImage._buffer; _decodedImage._buffer = NULL; } _inited = false; return WEBRTC_VIDEO_CODEC_OK; } tbI420Decoder::FunctionCalls tbI420Decoder::GetFunctionCalls() { return _functionCalls; }