2011-07-07 08:21:25 +00:00
|
|
|
/*
|
2012-02-02 12:46:58 +00:00
|
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
2011-07-07 08:21:25 +00:00
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2015-10-22 12:23:11 +02:00
|
|
|
#include "webrtc/modules/video_coding/codecs/i420/include/i420.h"
|
2012-07-11 18:20:39 +00:00
|
|
|
|
2013-03-18 16:39:03 +00:00
|
|
|
#include <limits>
|
2013-07-16 12:32:05 +00:00
|
|
|
#include <string>
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2013-07-16 12:32:05 +00:00
|
|
|
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
2012-07-11 18:20:39 +00:00
|
|
|
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
namespace {
|
|
|
|
|
const size_t kI420HeaderSize = 4;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:39:03 +00:00
|
|
|
namespace webrtc {
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2015-12-21 03:04:49 -08:00
|
|
|
I420Encoder::I420Encoder()
|
|
|
|
|
: _inited(false), _encodedImage(), _encodedCompleteCallback(NULL) {}
|
2012-07-10 20:58:08 +00:00
|
|
|
|
|
|
|
|
I420Encoder::~I420Encoder() {
|
|
|
|
|
_inited = false;
|
2015-12-21 03:04:49 -08:00
|
|
|
delete[] _encodedImage._buffer;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-07-10 20:58:08 +00:00
|
|
|
int I420Encoder::Release() {
|
|
|
|
|
// Should allocate an encoded frame and then release it here, for that we
|
|
|
|
|
// actually need an init flag.
|
|
|
|
|
if (_encodedImage._buffer != NULL) {
|
2015-12-21 03:04:49 -08:00
|
|
|
delete[] _encodedImage._buffer;
|
2012-07-10 20:58:08 +00:00
|
|
|
_encodedImage._buffer = NULL;
|
|
|
|
|
}
|
|
|
|
|
_inited = false;
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-07-10 20:58:08 +00:00
|
|
|
int I420Encoder::InitEncode(const VideoCodec* codecSettings,
|
2012-07-31 15:53:44 +00:00
|
|
|
int /*numberOfCores*/,
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
size_t /*maxPayloadSize */) {
|
2012-07-10 20:58:08 +00:00
|
|
|
if (codecSettings == NULL) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
if (codecSettings->width < 1 || codecSettings->height < 1) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocating encoded memory.
|
|
|
|
|
if (_encodedImage._buffer != NULL) {
|
2015-12-21 03:04:49 -08:00
|
|
|
delete[] _encodedImage._buffer;
|
2012-07-10 20:58:08 +00:00
|
|
|
_encodedImage._buffer = NULL;
|
|
|
|
|
_encodedImage._size = 0;
|
|
|
|
|
}
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
const size_t newSize =
|
|
|
|
|
CalcBufferSize(kI420, codecSettings->width, codecSettings->height) +
|
|
|
|
|
kI420HeaderSize;
|
2012-07-10 20:58:08 +00:00
|
|
|
uint8_t* newBuffer = new uint8_t[newSize];
|
|
|
|
|
if (newBuffer == NULL) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
_encodedImage._size = newSize;
|
|
|
|
|
_encodedImage._buffer = newBuffer;
|
|
|
|
|
|
|
|
|
|
// If no memory allocation, no point to init.
|
|
|
|
|
_inited = true;
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2015-05-29 17:21:40 -07:00
|
|
|
int I420Encoder::Encode(const VideoFrame& inputImage,
|
2012-10-24 18:33:04 +00:00
|
|
|
const CodecSpecificInfo* /*codecSpecificInfo*/,
|
2015-10-19 02:39:06 -07:00
|
|
|
const std::vector<FrameType>* /*frame_types*/) {
|
2012-07-10 20:58:08 +00:00
|
|
|
if (!_inited) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
|
|
|
|
}
|
|
|
|
|
if (_encodedCompleteCallback == NULL) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-23 15:58:18 +02:00
|
|
|
_encodedImage._frameType = kVideoFrameKey;
|
2012-10-24 18:33:04 +00:00
|
|
|
_encodedImage._timeStamp = inputImage.timestamp();
|
|
|
|
|
_encodedImage._encodedHeight = inputImage.height();
|
|
|
|
|
_encodedImage._encodedWidth = inputImage.width();
|
2012-07-10 20:58:08 +00:00
|
|
|
|
2013-03-18 16:39:03 +00:00
|
|
|
int width = inputImage.width();
|
|
|
|
|
if (width > std::numeric_limits<uint16_t>::max()) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_SIZE;
|
|
|
|
|
}
|
|
|
|
|
int height = inputImage.height();
|
|
|
|
|
if (height > std::numeric_limits<uint16_t>::max()) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
size_t req_length =
|
|
|
|
|
CalcBufferSize(kI420, inputImage.width(), inputImage.height()) +
|
|
|
|
|
kI420HeaderSize;
|
|
|
|
|
if (_encodedImage._size > req_length) {
|
2013-03-18 16:39:03 +00:00
|
|
|
// Reallocate buffer.
|
2015-12-21 03:04:49 -08:00
|
|
|
delete[] _encodedImage._buffer;
|
2013-03-18 16:39:03 +00:00
|
|
|
|
|
|
|
|
_encodedImage._buffer = new uint8_t[req_length];
|
2012-10-24 18:33:04 +00:00
|
|
|
_encodedImage._size = req_length;
|
2012-07-10 20:58:08 +00:00
|
|
|
}
|
2012-10-24 18:33:04 +00:00
|
|
|
|
2015-12-21 03:04:49 -08:00
|
|
|
uint8_t* buffer = _encodedImage._buffer;
|
2013-03-18 16:39:03 +00:00
|
|
|
|
|
|
|
|
buffer = InsertHeader(buffer, width, height);
|
|
|
|
|
|
2015-12-21 03:04:49 -08:00
|
|
|
int ret_length =
|
|
|
|
|
ExtractBuffer(inputImage, req_length - kI420HeaderSize, buffer);
|
2012-10-24 18:33:04 +00:00
|
|
|
if (ret_length < 0)
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_MEMORY;
|
2013-03-18 16:39:03 +00:00
|
|
|
_encodedImage._length = ret_length + kI420HeaderSize;
|
2012-10-24 18:33:04 +00:00
|
|
|
|
2015-02-09 09:14:03 +00:00
|
|
|
_encodedCompleteCallback->Encoded(_encodedImage, NULL, NULL);
|
2012-07-10 20:58:08 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2015-12-21 03:04:49 -08:00
|
|
|
uint8_t* I420Encoder::InsertHeader(uint8_t* buffer,
|
|
|
|
|
uint16_t width,
|
2013-03-18 16:39:03 +00:00
|
|
|
uint16_t height) {
|
|
|
|
|
*buffer++ = static_cast<uint8_t>(width >> 8);
|
|
|
|
|
*buffer++ = static_cast<uint8_t>(width & 0xFF);
|
|
|
|
|
*buffer++ = static_cast<uint8_t>(height >> 8);
|
|
|
|
|
*buffer++ = static_cast<uint8_t>(height & 0xFF);
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2015-12-21 03:04:49 -08:00
|
|
|
int I420Encoder::RegisterEncodeCompleteCallback(
|
|
|
|
|
EncodedImageCallback* callback) {
|
2012-07-10 20:58:08 +00:00
|
|
|
_encodedCompleteCallback = callback;
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2015-12-21 03:04:49 -08:00
|
|
|
I420Decoder::I420Decoder()
|
|
|
|
|
: _decodedImage(),
|
|
|
|
|
_width(0),
|
|
|
|
|
_height(0),
|
|
|
|
|
_inited(false),
|
|
|
|
|
_decodeCompleteCallback(NULL) {}
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-07-10 20:58:08 +00:00
|
|
|
I420Decoder::~I420Decoder() {
|
|
|
|
|
Release();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2015-12-21 03:04:49 -08:00
|
|
|
int I420Decoder::InitDecode(const VideoCodec* codecSettings,
|
|
|
|
|
int /*numberOfCores */) {
|
2012-07-10 20:58:08 +00:00
|
|
|
if (codecSettings == NULL) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
} else if (codecSettings->width < 1 || codecSettings->height < 1) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
_width = codecSettings->width;
|
|
|
|
|
_height = codecSettings->height;
|
|
|
|
|
_inited = true;
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2015-12-21 03:04:49 -08:00
|
|
|
int I420Decoder::Decode(const EncodedImage& inputImage,
|
|
|
|
|
bool /*missingFrames*/,
|
2013-03-18 16:39:03 +00:00
|
|
|
const RTPFragmentationHeader* /*fragmentation*/,
|
|
|
|
|
const CodecSpecificInfo* /*codecSpecificInfo*/,
|
|
|
|
|
int64_t /*renderTimeMs*/) {
|
2012-07-10 20:58:08 +00:00
|
|
|
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;
|
|
|
|
|
}
|
2012-11-14 17:56:46 +00:00
|
|
|
if (inputImage._completeFrame == false) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
|
|
|
|
}
|
2012-07-10 20:58:08 +00:00
|
|
|
if (!_inited) {
|
2013-03-18 16:39:03 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
2012-07-10 20:58:08 +00:00
|
|
|
}
|
2013-03-19 11:39:03 +00:00
|
|
|
if (inputImage._length < kI420HeaderSize) {
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:39:03 +00:00
|
|
|
const uint8_t* buffer = inputImage._buffer;
|
|
|
|
|
uint16_t width, height;
|
|
|
|
|
|
|
|
|
|
buffer = ExtractHeader(buffer, &width, &height);
|
|
|
|
|
_width = width;
|
|
|
|
|
_height = height;
|
2012-07-10 20:58:08 +00:00
|
|
|
|
2012-11-14 17:56:46 +00:00
|
|
|
// Verify that the available length is sufficient:
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
size_t req_length = CalcBufferSize(kI420, _width, _height) + kI420HeaderSize;
|
2013-03-19 11:39:03 +00:00
|
|
|
|
|
|
|
|
if (req_length > inputImage._length) {
|
2012-11-14 17:56:46 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
|
|
|
}
|
2012-07-10 20:58:08 +00:00
|
|
|
// Set decoded image parameters.
|
2012-10-24 18:33:04 +00:00
|
|
|
int half_width = (_width + 1) / 2;
|
2015-12-21 03:04:49 -08:00
|
|
|
_decodedImage.CreateEmptyFrame(_width, _height, _width, half_width,
|
|
|
|
|
half_width);
|
2013-03-18 16:39:03 +00:00
|
|
|
// Converting from buffer to plane representation.
|
2015-03-09 17:07:31 +00:00
|
|
|
int ret = ConvertToI420(kI420, buffer, 0, 0, _width, _height, 0,
|
|
|
|
|
kVideoRotation_0, &_decodedImage);
|
2012-10-24 18:33:04 +00:00
|
|
|
if (ret < 0) {
|
2012-07-31 15:53:44 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_MEMORY;
|
|
|
|
|
}
|
2012-10-24 18:33:04 +00:00
|
|
|
_decodedImage.set_timestamp(inputImage._timeStamp);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2015-03-16 13:46:52 +00:00
|
|
|
_decodeCompleteCallback->Decoded(_decodedImage);
|
2012-07-10 20:58:08 +00:00
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:39:03 +00:00
|
|
|
const uint8_t* I420Decoder::ExtractHeader(const uint8_t* buffer,
|
2015-12-21 03:04:49 -08:00
|
|
|
uint16_t* width,
|
|
|
|
|
uint16_t* height) {
|
2013-03-18 16:39:03 +00:00
|
|
|
*width = static_cast<uint16_t>(*buffer++) << 8;
|
|
|
|
|
*width |= *buffer++;
|
|
|
|
|
*height = static_cast<uint16_t>(*buffer++) << 8;
|
|
|
|
|
*height |= *buffer++;
|
|
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int I420Decoder::RegisterDecodeCompleteCallback(
|
|
|
|
|
DecodedImageCallback* callback) {
|
2012-07-10 20:58:08 +00:00
|
|
|
_decodeCompleteCallback = callback;
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:39:03 +00:00
|
|
|
int I420Decoder::Release() {
|
2012-07-10 20:58:08 +00:00
|
|
|
_inited = false;
|
|
|
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2013-03-18 16:39:03 +00:00
|
|
|
} // namespace webrtc
|