Changing JPEG API to to accept rawImage and encodedImage; moved video_image.h from modules/video_coding/codecs to common_video/interface, and some general re-write to JPEG, especially with regard to memory handling. Required VCM/ViE changes are also included.
Review URL: http://webrtc-codereview.appspot.com/55002 git-svn-id: http://webrtc.googlecode.com/svn/trunk@139 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
67d7282900
commit
b5427cbd35
@ -8,8 +8,8 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef VIDEO_IMAGE_H
|
||||
#define VIDEO_IMAGE_H
|
||||
#ifndef COMMON_VIDEO_INTERFACE_VIDEO_IMAGE_H
|
||||
#define COMMON_VIDEO_INTERFACE_VIDEO_IMAGE_H
|
||||
|
||||
#include "typedefs.h"
|
||||
#include <stdlib.h>
|
||||
@ -33,7 +33,7 @@ public:
|
||||
_length(0), _size(0) {}
|
||||
|
||||
RawImage(WebRtc_UWord8* buffer, WebRtc_UWord32 length,
|
||||
WebRtc_UWord32 size) :
|
||||
WebRtc_UWord32 size) :
|
||||
_width(0), _height(0), _timeStamp(0),
|
||||
_buffer(buffer), _length(length), _size(size) {}
|
||||
|
||||
@ -50,8 +50,8 @@ class EncodedImage
|
||||
public:
|
||||
EncodedImage() :
|
||||
_encodedWidth(0), _encodedHeight(0), _timeStamp(0),
|
||||
_frameType(kDeltaFrame), _buffer(NULL), _length(0), _size(0),
|
||||
_completeFrame(false) {}
|
||||
_frameType(kDeltaFrame), _buffer(NULL), _length(0),
|
||||
_size(0), _completeFrame(false) {}
|
||||
|
||||
EncodedImage(WebRtc_UWord8* buffer,
|
||||
WebRtc_UWord32 length,
|
||||
@ -63,7 +63,7 @@ public:
|
||||
WebRtc_UWord32 _encodedWidth;
|
||||
WebRtc_UWord32 _encodedHeight;
|
||||
WebRtc_UWord32 _timeStamp;
|
||||
VideoFrameType _frameType;
|
||||
VideoFrameType _frameType;
|
||||
WebRtc_UWord8* _buffer;
|
||||
WebRtc_UWord32 _length;
|
||||
WebRtc_UWord32 _size;
|
||||
@ -72,4 +72,4 @@ public:
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // VIDEO_IMAGE_H
|
||||
#endif // COMMON_VIDEO_INTERFACE_VIDEO_IMAGE_H
|
@ -16,6 +16,7 @@
|
||||
#define WEBRTC_COMMON_VIDEO_JPEG
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "video_image.h"
|
||||
|
||||
// jpeg forward declaration
|
||||
struct jpeg_compress_struct;
|
||||
@ -47,19 +48,12 @@ public:
|
||||
// Output:
|
||||
// - 0 : OK
|
||||
// - (-1) : Error
|
||||
WebRtc_Word32 Encode(const WebRtc_UWord8* imageBuffer,
|
||||
const WebRtc_UWord32 imageBufferSize,
|
||||
const WebRtc_UWord32 width,
|
||||
const WebRtc_UWord32 height);
|
||||
WebRtc_Word32 Encode(const RawImage& inputImage);
|
||||
|
||||
private:
|
||||
WebRtc_Word32 Encode(const WebRtc_UWord8* imageBuffer,
|
||||
const WebRtc_UWord32 imageBufferSize);
|
||||
|
||||
jpeg_compress_struct* _cinfo;
|
||||
WebRtc_Word8 _fileName[256];
|
||||
WebRtc_UWord32 _width;
|
||||
WebRtc_UWord32 _height;
|
||||
};
|
||||
|
||||
class JpegDecoder
|
||||
@ -68,25 +62,19 @@ class JpegDecoder
|
||||
JpegDecoder();
|
||||
~JpegDecoder();
|
||||
|
||||
//Decodes a JPEG-stream
|
||||
//Supports 1 image component. 3 interleaved image components, YCbCr sub-sampling 4:4:4, 4:2:2, 4:2:0.
|
||||
// Decodes a JPEG-stream
|
||||
// Supports 1 image component. 3 interleaved image components,
|
||||
// YCbCr sub-sampling 4:4:4, 4:2:2, 4:2:0.
|
||||
//
|
||||
//Input:
|
||||
// - encodedBuffer : Pointer to the encoded stream to be decoded.
|
||||
// - encodedBufferSize : Size of the data to be decoded
|
||||
// - decodedBuffer : Reference to the destination of the decoded I420-image.
|
||||
// - width : Reference returning width of decoded image.
|
||||
// - height : Reference returning height of decoded image.
|
||||
// Input:
|
||||
// - inputImage : encoded image to be decoded.
|
||||
// - outputImage : RawImage to store decoded output
|
||||
//
|
||||
// Output:
|
||||
// - 0 : OK
|
||||
// - (-1) : Error
|
||||
//Note: decodedBuffer should be freed by user
|
||||
WebRtc_Word32 Decode(const WebRtc_UWord8* encodedBuffer,
|
||||
const WebRtc_UWord32 encodedBufferSize,
|
||||
WebRtc_UWord8*& decodedBuffer,
|
||||
WebRtc_UWord32& width,
|
||||
WebRtc_UWord32& height);
|
||||
WebRtc_Word32 Decode(const EncodedImage& inputImage,
|
||||
RawImage& outputImage);
|
||||
private:
|
||||
jpeg_decompress_struct* _cinfo;
|
||||
};
|
||||
|
@ -52,18 +52,19 @@ MyErrorExit (j_common_ptr cinfo)
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
JpegEncoder::JpegEncoder():
|
||||
_width(0),
|
||||
_height(0)
|
||||
JpegEncoder::JpegEncoder()
|
||||
{
|
||||
_cinfo = new jpeg_compress_struct;
|
||||
_cinfo = new jpeg_compress_struct;
|
||||
strcpy(_fileName, "Snapshot.jpg");
|
||||
}
|
||||
|
||||
JpegEncoder::~JpegEncoder()
|
||||
{
|
||||
delete _cinfo;
|
||||
_cinfo = NULL;
|
||||
if (_cinfo != NULL)
|
||||
{
|
||||
delete _cinfo;
|
||||
_cinfo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -84,24 +85,21 @@ JpegEncoder::SetFileName(const WebRtc_Word8* fileName)
|
||||
|
||||
|
||||
WebRtc_Word32
|
||||
JpegEncoder::Encode(const WebRtc_UWord8* imageBuffer,
|
||||
const WebRtc_UWord32 imageBufferSize,
|
||||
const WebRtc_UWord32 width,
|
||||
const WebRtc_UWord32 height)
|
||||
JpegEncoder::Encode(const RawImage& inputImage)
|
||||
{
|
||||
if ((imageBuffer == NULL) || (imageBufferSize == 0))
|
||||
if (inputImage._buffer == NULL || inputImage._size == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (width < 1 || height < 1)
|
||||
if (inputImage._width < 1 || inputImage._height < 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE* outFile = NULL;
|
||||
|
||||
_width = width;
|
||||
_height = height;
|
||||
const WebRtc_Word32 width = inputImage._width;
|
||||
const WebRtc_Word32 height = inputImage._height;
|
||||
|
||||
// Set error handler
|
||||
myErrorMgr jerr;
|
||||
@ -121,7 +119,6 @@ JpegEncoder::Encode(const WebRtc_UWord8* imageBuffer,
|
||||
|
||||
if ((outFile = fopen(_fileName, "wb")) == NULL)
|
||||
{
|
||||
fprintf(stderr, "can't open %s\n", _fileName);
|
||||
return -2;
|
||||
}
|
||||
// Create a compression object
|
||||
@ -130,51 +127,12 @@ JpegEncoder::Encode(const WebRtc_UWord8* imageBuffer,
|
||||
// Setting destination file
|
||||
jpeg_stdio_dest(_cinfo, outFile);
|
||||
|
||||
WebRtc_Word32 ret = 0;
|
||||
|
||||
// Height of image buffer should be a multiple of 16
|
||||
if (_height % 16 == 0)
|
||||
{
|
||||
ret = Encode(imageBuffer, imageBufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
WebRtc_UWord32 height16 = ((_height + 15) - 16) & - 16;
|
||||
height16 = (height16 < _height) ? height16 + 16 : height16;
|
||||
|
||||
// Copy image to an adequate size buffer
|
||||
WebRtc_UWord32 requiredSize = height16 * _width * 3 >> 1;
|
||||
WebRtc_UWord8* origImagePtr = new WebRtc_UWord8[requiredSize];
|
||||
if (origImagePtr == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
memset(origImagePtr, 0, requiredSize);
|
||||
memcpy(origImagePtr, imageBuffer, imageBufferSize);
|
||||
|
||||
ret = Encode(origImagePtr, requiredSize);
|
||||
|
||||
// delete allocated buffer
|
||||
delete [] origImagePtr;
|
||||
origImagePtr = NULL;
|
||||
}
|
||||
|
||||
|
||||
fclose(outFile);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
JpegEncoder::Encode(const WebRtc_UWord8* imageBuffer,
|
||||
const WebRtc_UWord32 imageBufferSize)
|
||||
{
|
||||
// Set parameters for compression
|
||||
_cinfo->in_color_space = JCS_YCbCr;
|
||||
jpeg_set_defaults(_cinfo);
|
||||
|
||||
_cinfo->image_width = _width;
|
||||
_cinfo->image_height = _height;
|
||||
_cinfo->image_width = width;
|
||||
_cinfo->image_height = height;
|
||||
_cinfo->input_components = 3;
|
||||
|
||||
_cinfo->comp_info[0].h_samp_factor = 2; // Y
|
||||
@ -196,30 +154,31 @@ JpegEncoder::Encode(const WebRtc_UWord8* imageBuffer,
|
||||
|
||||
WebRtc_UWord32 i, j;
|
||||
|
||||
for (j = 0; j < _height; j += 16)
|
||||
for (j = 0; j < height; j += 16)
|
||||
{
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
y[i] = (JSAMPLE*) imageBuffer + _width * (i + j);
|
||||
y[i] = (JSAMPLE*) inputImage._buffer + width * (i + j);
|
||||
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
u[i / 2] = (JSAMPLE*) imageBuffer + _width * _height +
|
||||
_width / 2 * ((i + j) / 2);
|
||||
v[i / 2] = (JSAMPLE*) imageBuffer + _width * _height +
|
||||
_width * _height / 4 + _width / 2 * ((i + j) / 2);
|
||||
u[i / 2] = (JSAMPLE*) inputImage._buffer + width * height +
|
||||
width / 2 * ((i + j) / 2);
|
||||
v[i / 2] = (JSAMPLE*) inputImage._buffer + width * height +
|
||||
width * height / 4 + width / 2 * ((i + j) / 2);
|
||||
}
|
||||
}
|
||||
jpeg_write_raw_data(_cinfo, data, 16);
|
||||
jpeg_write_raw_data(_cinfo, data, 16);
|
||||
}
|
||||
|
||||
jpeg_finish_compress(_cinfo);
|
||||
jpeg_destroy_compress(_cinfo);
|
||||
|
||||
fclose(outFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
JpegDecoder::JpegDecoder()
|
||||
{
|
||||
_cinfo = new jpeg_decompress_struct;
|
||||
@ -227,18 +186,20 @@ JpegDecoder::JpegDecoder()
|
||||
|
||||
JpegDecoder::~JpegDecoder()
|
||||
{
|
||||
delete _cinfo;
|
||||
_cinfo = NULL;
|
||||
if (_cinfo != NULL)
|
||||
{
|
||||
delete _cinfo;
|
||||
_cinfo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
JpegDecoder::Decode(const WebRtc_UWord8* encodedBuffer,
|
||||
const WebRtc_UWord32 encodedBufferSize,
|
||||
WebRtc_UWord8*& decodedBuffer,
|
||||
WebRtc_UWord32& width,
|
||||
WebRtc_UWord32& height)
|
||||
JpegDecoder::Decode(const EncodedImage& inputImage,
|
||||
RawImage& outputImage)
|
||||
{
|
||||
// Set error handler
|
||||
|
||||
WebRtc_UWord8* tmpBuffer = NULL;
|
||||
// Set error handler
|
||||
myErrorMgr jerr;
|
||||
_cinfo->err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = MyErrorExit;
|
||||
@ -250,6 +211,10 @@ JpegDecoder::Decode(const WebRtc_UWord8* encodedBuffer,
|
||||
{
|
||||
jpeg_destroy_decompress(_cinfo);
|
||||
}
|
||||
if (tmpBuffer != NULL)
|
||||
{
|
||||
delete [] tmpBuffer;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -259,7 +224,7 @@ JpegDecoder::Decode(const WebRtc_UWord8* encodedBuffer,
|
||||
jpeg_create_decompress(_cinfo);
|
||||
|
||||
// Specify data source
|
||||
jpegSetSrcBuffer(_cinfo, (JOCTET*) encodedBuffer, encodedBufferSize);
|
||||
jpegSetSrcBuffer(_cinfo, (JOCTET*) inputImage._buffer, inputImage._size);
|
||||
|
||||
// Read header data
|
||||
jpeg_read_header(_cinfo, TRUE);
|
||||
@ -277,28 +242,47 @@ JpegDecoder::Decode(const WebRtc_UWord8* encodedBuffer,
|
||||
return -2; // not supported
|
||||
}
|
||||
|
||||
height = _cinfo->image_height;
|
||||
width = _cinfo->image_width;
|
||||
|
||||
WebRtc_UWord32 height = _cinfo->image_height;
|
||||
WebRtc_UWord32 width = _cinfo->image_width;
|
||||
|
||||
// Making sure width and height are even
|
||||
if (height % 2)
|
||||
{
|
||||
height++;
|
||||
if (width % 2)
|
||||
width++;
|
||||
|
||||
WebRtc_UWord32 height16 = ((height + 15) - 16) & - 16;
|
||||
height16 = (height16 < height) ? height16 + 16 : height16;
|
||||
|
||||
// allocate buffer to output
|
||||
if (decodedBuffer != NULL)
|
||||
{
|
||||
delete [] decodedBuffer;
|
||||
decodedBuffer = NULL;
|
||||
}
|
||||
decodedBuffer = new WebRtc_UWord8[width * height16 * 3 >> 1];
|
||||
if (decodedBuffer == NULL)
|
||||
if (width % 2)
|
||||
{
|
||||
return -1;
|
||||
width++;
|
||||
}
|
||||
|
||||
WebRtc_UWord32 height16 = (height + 15) & ~15;
|
||||
WebRtc_UWord32 stride = (width + 15) & ~15;
|
||||
WebRtc_UWord32 uvStride = (((stride + 1 >> 1) + 15) & ~15);
|
||||
|
||||
WebRtc_UWord32 tmpRequiredSize = stride * height16 +
|
||||
2 * (uvStride * ((height16 + 1) >> 1));
|
||||
WebRtc_UWord32 requiredSize = width * height * 3 >> 1;
|
||||
|
||||
// verify sufficient buffer size
|
||||
if (outputImage._buffer && outputImage._size < requiredSize)
|
||||
{
|
||||
delete [] outputImage._buffer;
|
||||
outputImage._buffer = NULL;
|
||||
}
|
||||
|
||||
if (outputImage._buffer == NULL)
|
||||
{
|
||||
outputImage._buffer = new WebRtc_UWord8[requiredSize];
|
||||
outputImage._size = requiredSize;
|
||||
}
|
||||
|
||||
WebRtc_UWord8* outPtr = outputImage._buffer;
|
||||
|
||||
if (tmpRequiredSize > requiredSize)
|
||||
{
|
||||
tmpBuffer = new WebRtc_UWord8[(int) (tmpRequiredSize)];
|
||||
outPtr = tmpBuffer;
|
||||
}
|
||||
|
||||
JSAMPROW y[16],u[8],v[8];
|
||||
@ -310,19 +294,21 @@ JpegDecoder::Decode(const WebRtc_UWord8* encodedBuffer,
|
||||
WebRtc_UWord32 hInd, i;
|
||||
WebRtc_UWord32 numScanLines = 16;
|
||||
WebRtc_UWord32 numLinesProcessed = 0;
|
||||
while(_cinfo->output_scanline < _cinfo->output_height)
|
||||
|
||||
while (_cinfo->output_scanline < _cinfo->output_height)
|
||||
{
|
||||
hInd = _cinfo->output_scanline;
|
||||
for (i = 0; i < numScanLines; i++)
|
||||
{
|
||||
y[i] = decodedBuffer + width * (i + hInd);
|
||||
y[i] = outPtr + stride * (i + hInd);
|
||||
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
u[i / 2] = decodedBuffer + width * height +
|
||||
width / 2 * ((i + hInd) / 2);
|
||||
v[i / 2] = decodedBuffer + width * height +
|
||||
width * height / 4 + width / 2 * ((i + hInd) / 2);
|
||||
u[i / 2] = outPtr + stride * height16 +
|
||||
stride / 2 * ((i + hInd) / 2);
|
||||
v[i / 2] = outPtr + stride * height16 +
|
||||
stride * height16 / 4 +
|
||||
stride / 2 * ((i + hInd) / 2);
|
||||
}
|
||||
}
|
||||
// Processes exactly one iMCU row per call
|
||||
@ -330,12 +316,43 @@ JpegDecoder::Decode(const WebRtc_UWord8* encodedBuffer,
|
||||
// Error in read
|
||||
if (numLinesProcessed == 0)
|
||||
{
|
||||
delete [] decodedBuffer;
|
||||
jpeg_abort((j_common_ptr)_cinfo);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpRequiredSize > requiredSize)
|
||||
{
|
||||
WebRtc_UWord8* dstFramePtr = outputImage._buffer;
|
||||
WebRtc_UWord8* tmpPtr = outPtr;
|
||||
|
||||
for (WebRtc_UWord32 p = 0; p < 3; p++)
|
||||
{
|
||||
const WebRtc_UWord32 h = (p == 0) ? height : height >> 1;
|
||||
const WebRtc_UWord32 h16 = (p == 0) ? height16 : height16 >> 1;
|
||||
const WebRtc_UWord32 w = (p == 0) ? width : width >> 1;
|
||||
const WebRtc_UWord32 s = (p == 0) ? stride : stride >> 1;
|
||||
|
||||
for (WebRtc_UWord32 i = 0; i < h; i++)
|
||||
{
|
||||
memcpy(dstFramePtr, tmpPtr, w);
|
||||
dstFramePtr += w;
|
||||
tmpPtr += s;
|
||||
}
|
||||
tmpPtr += (h16 - h) * s;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpBuffer != NULL)
|
||||
{
|
||||
delete [] tmpBuffer;
|
||||
}
|
||||
// Setting output Image parameter
|
||||
outputImage._width = width;
|
||||
outputImage._height = height;
|
||||
outputImage._length = requiredSize;
|
||||
outputImage._timeStamp = inputImage._timeStamp;
|
||||
|
||||
jpeg_finish_decompress(_cinfo);
|
||||
jpeg_destroy_decompress(_cinfo);
|
||||
return 0;
|
||||
|
@ -18,12 +18,14 @@
|
||||
'../../../vplib/main/source/vplib.gyp:webrtc_vplib',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../../../interface',
|
||||
'../interface',
|
||||
'../../../../../../',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../interface',
|
||||
'../../../interface',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
@ -78,12 +80,9 @@
|
||||
],
|
||||
'sources': [
|
||||
|
||||
# headers
|
||||
'../test/test_buffer.h',
|
||||
|
||||
# headers
|
||||
|
||||
# sources
|
||||
'../test/test_buffer.cc',
|
||||
'../test/test_jpeg.cc',
|
||||
|
||||
], # source
|
||||
|
@ -19,13 +19,11 @@
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "test_buffer.h"
|
||||
#include "video_image.h"
|
||||
#include "jpeg.h"
|
||||
|
||||
using namespace webrtc;
|
||||
|
||||
#define PRINT_LINE std::cout << "-------------------------------" << std::endl;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -37,13 +35,12 @@ main(int argc, char **argv)
|
||||
const char* fileNameDec = "TestJpegDec.yuv";
|
||||
const char* fileNameEnc = "TestJpegEnc.jpg";
|
||||
|
||||
std::string str;
|
||||
std::string str;
|
||||
std::cout << "---------------------" << std::endl;
|
||||
std::cout << "----- Test JPEG -----" << std::endl;
|
||||
std::cout << "---------------------" << std::endl;
|
||||
std::cout << " " << std::endl;
|
||||
|
||||
|
||||
JpegDecoder* JpgDecPtr = new JpegDecoder( );
|
||||
|
||||
// Open input file
|
||||
@ -55,38 +52,31 @@ main(int argc, char **argv)
|
||||
int length = ftell(openFile);
|
||||
fseek(openFile, 0, SEEK_SET);
|
||||
|
||||
|
||||
// Read input file to buffer
|
||||
TestBuffer encodedBuffer;
|
||||
encodedBuffer.VerifyAndAllocate(length);
|
||||
encodedBuffer.UpdateLength(length);
|
||||
fread(encodedBuffer.GetBuffer(), 1, length, openFile);
|
||||
EncodedImage encodedBuffer;
|
||||
encodedBuffer._buffer = new WebRtc_UWord8[length];
|
||||
encodedBuffer._size = length;
|
||||
encodedBuffer._length = length;
|
||||
fread(encodedBuffer._buffer, 1, length, openFile);
|
||||
fclose(openFile);
|
||||
|
||||
// ------------------
|
||||
// Decode
|
||||
// ------------------
|
||||
|
||||
TestBuffer imageBuffer;
|
||||
WebRtc_UWord32 width = 0;
|
||||
WebRtc_UWord32 height = 0;
|
||||
WebRtc_UWord8* tmp = NULL;
|
||||
int error = JpgDecPtr->Decode(encodedBuffer.GetBuffer(),
|
||||
encodedBuffer.GetSize(), tmp, width, height);
|
||||
RawImage imageBuffer;
|
||||
int error = JpgDecPtr->Decode(encodedBuffer, imageBuffer);
|
||||
|
||||
std::cout << error << " = Decode(" << fileName.c_str() << ", (" << width <<
|
||||
"x" << height << "))" << std::endl;
|
||||
PRINT_LINE;
|
||||
std::cout << error << " = Decode(" << fileName.c_str() << ", "
|
||||
"(" << imageBuffer._width <<
|
||||
"x" << imageBuffer._height << "))" << std::endl;
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
int imageBufferSize = width*height*3/2;
|
||||
//update buffer info
|
||||
imageBuffer.VerifyAndAllocate( imageBufferSize);
|
||||
imageBuffer.CopyBuffer(imageBufferSize, tmp);
|
||||
delete [] tmp;
|
||||
// Save decoded image to file
|
||||
FILE* saveFile = fopen(fileNameDec, "wb");
|
||||
fwrite(imageBuffer.GetBuffer(), 1, imageBuffer.GetLength(), saveFile);
|
||||
fwrite(imageBuffer._buffer, 1, imageBuffer._length, saveFile);
|
||||
fclose(saveFile);
|
||||
|
||||
// ------------------
|
||||
@ -96,39 +86,40 @@ main(int argc, char **argv)
|
||||
JpegEncoder* JpegEncoderPtr = new JpegEncoder();
|
||||
|
||||
// Test invalid inputs
|
||||
|
||||
// Test buffer
|
||||
TestBuffer empty;
|
||||
|
||||
RawImage empty;
|
||||
empty._width = 164;
|
||||
empty._height = 164;
|
||||
int error = JpegEncoderPtr->SetFileName(0);
|
||||
assert(error == -1);
|
||||
error = JpegEncoderPtr->Encode(empty.GetBuffer(), empty.GetSize(),
|
||||
164, 164);
|
||||
error = JpegEncoderPtr->Encode(empty);
|
||||
assert(error == -1);
|
||||
error = JpegEncoderPtr->Encode(empty.GetBuffer(), empty.GetSize(),
|
||||
0, height);
|
||||
empty._buffer = new WebRtc_UWord8[10];
|
||||
empty._size = 0;
|
||||
error = JpegEncoderPtr->Encode(empty);
|
||||
assert(error == -1);
|
||||
error = JpegEncoderPtr->Encode(empty.GetBuffer(), empty.GetSize(),
|
||||
width, 0);
|
||||
empty._size = 10;
|
||||
empty._height = 0;
|
||||
error = JpegEncoderPtr->Encode(empty);
|
||||
assert(error == -1);
|
||||
empty._height = 164;
|
||||
empty._width = 0;
|
||||
error = JpegEncoderPtr->Encode(empty);
|
||||
assert(error == -1);
|
||||
|
||||
error = JpegEncoderPtr->SetFileName(fileNameEnc);
|
||||
assert(error == 0);
|
||||
|
||||
delete [] empty._buffer;
|
||||
|
||||
// Actual Encode
|
||||
error = JpegEncoderPtr->Encode(imageBuffer.GetBuffer(),
|
||||
imageBuffer.GetSize(), width, height);
|
||||
error = JpegEncoderPtr->Encode(imageBuffer);
|
||||
assert(error == 0);
|
||||
|
||||
std::cout << error << " = Encode(" << fileNameDec << ")" << std::endl;
|
||||
|
||||
PRINT_LINE;
|
||||
|
||||
delete JpegEncoderPtr;
|
||||
}
|
||||
|
||||
imageBuffer.Free();
|
||||
encodedBuffer.Free();
|
||||
delete [] imageBuffer._buffer;
|
||||
delete [] encodedBuffer._buffer;
|
||||
delete JpgDecPtr;
|
||||
|
||||
std::cout << "Verify that the encoded and decoded images look correct."
|
||||
|
@ -16,10 +16,12 @@
|
||||
'include_dirs': [
|
||||
'../interface',
|
||||
'../../../interface',
|
||||
'../../../../../../common_video/interface',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../interface',
|
||||
'../../../../../../common_video/interface',
|
||||
],
|
||||
},
|
||||
'sources': [
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
'include_dirs': [
|
||||
'../interface',
|
||||
'../../../../common_video/interface',
|
||||
],
|
||||
|
||||
'direct_dependent_settings': {
|
||||
|
@ -15,6 +15,7 @@
|
||||
],
|
||||
'include_dirs': [
|
||||
'../interface',
|
||||
'../../../../../../common_video/interface',
|
||||
'../../../interface',
|
||||
'../../../../../interface',
|
||||
],
|
||||
@ -49,6 +50,7 @@
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../interface',
|
||||
'../../../../../../common_video/interface',
|
||||
'../../../interface',
|
||||
],
|
||||
},
|
||||
|
@ -20,6 +20,7 @@
|
||||
'../interface',
|
||||
'../../../interface',
|
||||
'../../codecs/interface',
|
||||
'../../../../common_video/interface',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
|
@ -21,6 +21,7 @@
|
||||
'../../../interface',
|
||||
'../../codecs/vp8/main/interface',
|
||||
'../../../../system_wrappers/interface',
|
||||
'../../../../common_video/interface',
|
||||
'../source',
|
||||
],
|
||||
'sources': [
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include "vie_file_image.h"
|
||||
#include "video_image.h"
|
||||
#include "jpeg.h"
|
||||
#include "trace.h"
|
||||
|
||||
@ -24,8 +25,8 @@ int ViEFileImage::ConvertJPEGToVideoFrame(int engineId,
|
||||
VideoFrame& videoFrame)
|
||||
{
|
||||
// read jpeg file into temporary buffer
|
||||
WebRtc_UWord8* imageBuffer;
|
||||
WebRtc_UWord32 imageBufferSize;
|
||||
EncodedImage imageBuffer;
|
||||
|
||||
FILE* imageFile = fopen(fileNameUTF8, "rb");
|
||||
if (NULL == imageFile)
|
||||
{
|
||||
@ -35,15 +36,15 @@ int ViEFileImage::ConvertJPEGToVideoFrame(int engineId,
|
||||
return -1;
|
||||
}
|
||||
fseek(imageFile, 0, SEEK_END);
|
||||
imageBufferSize = ftell(imageFile);
|
||||
imageBuffer._size = ftell(imageFile);
|
||||
fseek(imageFile, 0, SEEK_SET);
|
||||
imageBuffer = new WebRtc_UWord8[imageBufferSize + 1];
|
||||
if (imageBufferSize != fread(imageBuffer, sizeof(WebRtc_UWord8),
|
||||
imageBufferSize, imageFile))
|
||||
imageBuffer._buffer = new WebRtc_UWord8[ imageBuffer._size + 1];
|
||||
if ( imageBuffer._size != fread(imageBuffer._buffer, sizeof(WebRtc_UWord8),
|
||||
imageBuffer._size, imageFile))
|
||||
{
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, engineId,
|
||||
"%s could not read file %s", __FUNCTION__, fileNameUTF8);
|
||||
delete imageBuffer;
|
||||
delete [] imageBuffer._buffer;
|
||||
return -1;
|
||||
}
|
||||
fclose(imageFile);
|
||||
@ -52,13 +53,13 @@ int ViEFileImage::ConvertJPEGToVideoFrame(int engineId,
|
||||
JpegDecoder decoder;
|
||||
|
||||
int ret = 0;
|
||||
WebRtc_UWord8* imageDecodedBuffer = NULL;
|
||||
WebRtc_UWord32 imageWidth, imageHeight = 0;
|
||||
ret = decoder.Decode(imageBuffer, imageBufferSize, imageDecodedBuffer,
|
||||
imageWidth, imageHeight);
|
||||
|
||||
RawImage decodedImage;
|
||||
ret = decoder.Decode(imageBuffer, decodedImage);
|
||||
|
||||
// done with this.
|
||||
delete imageBuffer;
|
||||
delete [] imageBuffer._buffer;
|
||||
imageBuffer._buffer = NULL;
|
||||
|
||||
if (-1 == ret)
|
||||
{
|
||||
@ -74,20 +75,25 @@ int ViEFileImage::ConvertJPEGToVideoFrame(int engineId,
|
||||
__FUNCTION__, fileNameUTF8);
|
||||
}
|
||||
|
||||
WebRtc_UWord32 imageLength = (WebRtc_UWord32)(imageWidth * imageHeight
|
||||
* 1.5);
|
||||
if (-1 == videoFrame.Swap(imageDecodedBuffer, imageLength, imageLength))
|
||||
WebRtc_UWord32 imageLength = (WebRtc_UWord32)(decodedImage._width *
|
||||
decodedImage._height * 1.5);
|
||||
if (-1 == videoFrame.Swap(decodedImage._buffer, imageLength, imageLength))
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
webrtc::kTraceDebug,
|
||||
webrtc::kTraceVideo,
|
||||
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideo,
|
||||
engineId,
|
||||
"%s could not copy frame imageDecodedBuffer to frame videoFrame ",
|
||||
"%s could not copy frame imageDecodedBuffer to videoFrame ",
|
||||
__FUNCTION__, fileNameUTF8);
|
||||
return -1;
|
||||
}
|
||||
videoFrame.SetWidth(imageWidth);
|
||||
videoFrame.SetHeight(imageHeight);
|
||||
|
||||
if (decodedImage._buffer)
|
||||
{
|
||||
delete [] decodedImage._buffer;
|
||||
decodedImage._buffer = NULL;
|
||||
}
|
||||
|
||||
videoFrame.SetWidth(decodedImage._width);
|
||||
videoFrame.SetHeight(decodedImage._height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -96,7 +102,7 @@ int ViEFileImage::ConvertPictureToVideoFrame(int engineId,
|
||||
VideoFrame& videoFrame)
|
||||
{
|
||||
WebRtc_UWord32 pictureLength = (WebRtc_UWord32)(picture.width
|
||||
* picture.height * 1.5);
|
||||
* picture.height * 1.5);
|
||||
videoFrame.CopyFrame(pictureLength, picture.data);
|
||||
videoFrame.SetWidth(picture.width);
|
||||
videoFrame.SetHeight(picture.height);
|
||||
|
@ -696,28 +696,40 @@ int ViEFileImpl::GetRenderSnapshot(const int videoChannel,
|
||||
// *** Thusly, we are not going to be writing to the disk here
|
||||
|
||||
JpegEncoder jpegEncoder;
|
||||
RawImage inputImage;
|
||||
|
||||
if (-1 == jpegEncoder.SetFileName(fileNameUTF8))
|
||||
{
|
||||
// could not set filename for whatever reason
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||
_instanceId,
|
||||
"\tCould not open output file '%s' for writing!",
|
||||
fileNameUTF8);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-1 == jpegEncoder.Encode(videoFrame.Buffer(),
|
||||
videoFrame.Length(),
|
||||
videoFrame.Width(),
|
||||
videoFrame.Height()))
|
||||
inputImage._width = videoFrame.Width();
|
||||
inputImage._height = videoFrame.Height();
|
||||
videoFrame.Swap(inputImage._buffer, inputImage._length,
|
||||
inputImage._size);
|
||||
|
||||
if (-1 == jpegEncoder.Encode(inputImage))
|
||||
{
|
||||
// could not encode i420->jpeg
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||
_instanceId,
|
||||
"\tCould not encode i420 -> jpeg file '%s' for "
|
||||
"writing!", fileNameUTF8);
|
||||
if (inputImage._buffer)
|
||||
{
|
||||
delete [] inputImage._buffer;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
delete [] inputImage._buffer;
|
||||
inputImage._buffer = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -805,28 +817,45 @@ int ViEFileImpl::GetCaptureDeviceSnapshot(const int captureId,
|
||||
// *** Thusly, we are not going to be writing to the disk here
|
||||
|
||||
JpegEncoder jpegEncoder;
|
||||
RawImage inputImage;
|
||||
|
||||
inputImage._width = videoFrame.Width();
|
||||
inputImage._height = videoFrame.Height();
|
||||
videoFrame.Swap(inputImage._buffer, inputImage._length,
|
||||
inputImage._size);
|
||||
|
||||
if (-1 == jpegEncoder.SetFileName(fileNameUTF8))
|
||||
{
|
||||
// could not set filename for whatever reason
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||
_instanceId,
|
||||
"\tCould not open output file '%s' for writing!",
|
||||
fileNameUTF8);
|
||||
|
||||
if (inputImage._buffer)
|
||||
{
|
||||
delete [] inputImage._buffer;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-1 == jpegEncoder.Encode(videoFrame.Buffer(),
|
||||
videoFrame.Length(),
|
||||
videoFrame.Width(),
|
||||
videoFrame.Height()))
|
||||
if (-1 == jpegEncoder.Encode(inputImage))
|
||||
{
|
||||
// could not encode i420->jpeg
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||
_instanceId,
|
||||
"\tCould not encode i420 -> jpeg file '%s' for "
|
||||
"writing!", fileNameUTF8);
|
||||
|
||||
if (inputImage._buffer)
|
||||
{
|
||||
delete [] inputImage._buffer;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
delete [] inputImage._buffer;
|
||||
inputImage._buffer = NULL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -22,6 +22,7 @@
|
||||
'../../interface',
|
||||
'../../source',
|
||||
'../../../../modules/video_coding/codecs/interface/',
|
||||
'../../../../common_video/interface/',
|
||||
],
|
||||
'sources': [
|
||||
# interfaces
|
||||
|
Loading…
x
Reference in New Issue
Block a user