LibYUVトランスコードトリミングC++
11765 ワード
int transfer_32bgra_to_yuv420(FrameImage* frameImage) {
int width = frameImage->width;
int height = frameImage->height;
int yuvBufSize = width * height * 3 / 2;
uint8_t* yuvBuf= new uint8_t[yuvBufSize];
const int y_length = width * height;
const int32 uv_stride = (width+1) / 2;
int uv_length = uv_stride * ((height+1) / 2);
unsigned char *Y_data_Dst_rotate = yuvBuf;
unsigned char *U_data_Dst_rotate = yuvBuf + y_length;
unsigned char *V_data_Dst_rotate = U_data_Dst_rotate + uv_length;
int Dst_Stride_Y = width;
// ,ARGBToI420 BGRA
//BGRAToI420 ARGB
YOUME_libyuv::ARGBToI420((const uint8*)frameImage->data,
width*4,
Y_data_Dst_rotate, Dst_Stride_Y,
U_data_Dst_rotate, uv_stride,
V_data_Dst_rotate, uv_stride,
width, -height);
memcpy(frameImage->data, yuvBuf, yuvBufSize);
if(yuvBuf) {
delete[] yuvBuf;
}
return yuvBufSize;
}
void rotation_and_mirror(FrameImage* frameImage, int degree, bool need_mirror) {
switch(degree) {
case 90:
case 180:
case 270:
{
int src_width = frameImage->width;
int src_height = frameImage->height;
//copy origin data
unsigned char * origdata = NULL;
unsigned char * Dst_data = (unsigned char *)(frameImage->data);
int size = (frameImage->width) * (frameImage->height) * 3 / 2;
origdata = (unsigned char *)tsk_calloc(1, size);
memcpy(origdata, frameImage->data, size);
//YUV420 image size
int I420_Y_Size = src_width * src_height;
// int I420_U_Size = (src_width >> 1) * (src_height >> 1);
int I420_U_Size = src_width * src_height / 4 ;
// int I420_V_Size = I420_U_Size;
unsigned char *Y_data_src = NULL;
unsigned char *U_data_src = NULL;
unsigned char *V_data_src = NULL;
int Dst_Stride_Y_rotate;
int Dst_Stride_U_rotate;
int Dst_Stride_V_rotate;
int Dst_Stride_Y = src_width;
int Dst_Stride_U = src_width >> 1;
int Dst_Stride_V = Dst_Stride_U;
//
unsigned char *Y_data_Dst_rotate = Dst_data;
unsigned char *U_data_Dst_rotate = Dst_data + I420_Y_Size;
unsigned char *V_data_Dst_rotate = Dst_data + I420_Y_Size + I420_U_Size;
if (degree == YOUME_libyuv::kRotate90 || degree == YOUME_libyuv::kRotate270) {
Dst_Stride_Y_rotate = src_height;
Dst_Stride_U_rotate = (src_height+1) >> 1;
Dst_Stride_V_rotate = Dst_Stride_U_rotate;
}
else {
Dst_Stride_Y_rotate = src_width;
Dst_Stride_U_rotate = (src_width+1) >> 1;
Dst_Stride_V_rotate = Dst_Stride_U_rotate;
}
//mirro
if(need_mirror){
Y_data_src = Dst_data;
U_data_src = Dst_data + I420_Y_Size;
V_data_src = Dst_data + I420_Y_Size + I420_U_Size;
unsigned char *Y_data_Dst_mirror = origdata;
unsigned char *U_data_Dst_mirror = origdata + I420_Y_Size;
unsigned char *V_data_Dst_mirror = origdata + I420_Y_Size + I420_U_Size;
int Dst_Stride_Y_mirror = src_width;
int Dst_Stride_U_mirror = (src_width+1) >> 1;
int Dst_Stride_V_mirror = Dst_Stride_U_mirror;
YOUME_libyuv::I420Mirror(Y_data_src, Dst_Stride_Y,
U_data_src, Dst_Stride_U,
V_data_src, Dst_Stride_V,
Y_data_Dst_mirror, Dst_Stride_Y_mirror,
U_data_Dst_mirror, Dst_Stride_U_mirror,
V_data_Dst_mirror, Dst_Stride_V_mirror,
src_width, src_height);
//
YOUME_libyuv::I420Rotate(Y_data_Dst_mirror, Dst_Stride_Y,
U_data_Dst_mirror, Dst_Stride_U,
V_data_Dst_mirror, Dst_Stride_V,
Y_data_Dst_rotate, Dst_Stride_Y_rotate,
U_data_Dst_rotate, Dst_Stride_U_rotate,
V_data_Dst_rotate, Dst_Stride_V_rotate,
src_width, src_height,
(YOUME_libyuv::RotationMode) degree);
}else{
Y_data_src = origdata;
U_data_src = origdata + I420_Y_Size;
V_data_src = origdata + I420_Y_Size + I420_U_Size;
YOUME_libyuv::I420Rotate(Y_data_src, Dst_Stride_Y,
U_data_src, Dst_Stride_U,
V_data_src, Dst_Stride_V,
Y_data_Dst_rotate, Dst_Stride_Y_rotate,
U_data_Dst_rotate, Dst_Stride_U_rotate,
V_data_Dst_rotate, Dst_Stride_V_rotate,
src_width, src_height,
(YOUME_libyuv::RotationMode) degree);
}
if (degree == YOUME_libyuv::kRotate90 || degree == YOUME_libyuv::kRotate270){
frameImage->width = src_height;
frameImage->height = src_width;
}
tsk_free((void**)&origdata);
}
default:
break;
}
}
void mirror(FrameImage* frameImage) {
if (NULL == frameImage) {
TSK_DEBUG_ERROR("Invalid parameter.");
return;
}
int src_width = frameImage->width;
int src_height = frameImage->height;
//copy origin data
unsigned char * origdata = NULL;
unsigned char * Dst_data = (unsigned char *)(frameImage->data);
int size = (frameImage->width) * (frameImage->height) * 3 / 2;
origdata = (unsigned char *)tsk_calloc(1, size);
memcpy(origdata, frameImage->data, size);
//YUV420 image size
int I420_Y_Size = src_width * src_height;
int I420_U_Size = (src_width >> 1) * (src_height >> 1);
// int I420_V_Size = I420_U_Size;
unsigned char *Y_data_src = origdata;
unsigned char *U_data_src = origdata + I420_Y_Size ;
unsigned char *V_data_src = origdata + I420_Y_Size + I420_U_Size;
int Src_Stride_Y = src_width;
int Src_Stride_U = (src_width+1) >> 1;
int Src_Stride_V = Src_Stride_U;
//
unsigned char *Y_data_Dst_rotate = Dst_data;
unsigned char *U_data_Dst_rotate = Dst_data + I420_Y_Size;
unsigned char *V_data_Dst_rotate = Dst_data + I420_Y_Size + I420_U_Size;
//mirro
int Dst_Stride_Y_mirror = src_width;
int Dst_Stride_U_mirror = (src_width+1) >> 1;
int Dst_Stride_V_mirror = Dst_Stride_U_mirror;
YOUME_libyuv::I420Mirror(Y_data_src, Src_Stride_Y,
U_data_src, Src_Stride_U,
V_data_src, Src_Stride_V,
Y_data_Dst_rotate, Dst_Stride_Y_mirror,
U_data_Dst_rotate, Dst_Stride_U_mirror,
V_data_Dst_rotate, Dst_Stride_V_mirror,
src_width, src_height);
tsk_free((void**)&origdata);
}
std::shared_ptr video_scale_and_crop_yuv(std::shared_ptr src, int out_width ,int out_height) {
//////////////////////////////////////////////////////////////////////////
std::shared_ptr dest = std::shared_ptr(new FrameImage(out_width, out_height));
int src_width_ = src->width;
int src_height_= src->height;
int dst_width_ = out_width;
int dst_height_ = out_height;
// Making sure that destination frame is of sufficient size.
// We want to preserve aspect ratio instead of stretching the frame.
// Therefore, we need to crop the source frame. Calculate the largest center
// aligned region of the source frame that can be used.
const int cropped_src_width =
std::min(src_width_, dst_width_ * src_height_ / dst_height_);
const int cropped_src_height =
std::min(src_height_, dst_height_ * src_width_ / dst_width_);
// Make sure the offsets are even to avoid rounding errors for the U/V planes.
const int src_offset_x = ((src_width_ - cropped_src_width) / 2) & ~1;
const int src_offset_y = ((src_height_ - cropped_src_height) / 2) & ~1;
//YUV420 image size
int I420_Y_Size = src_width_ * src_height_;
int I420_U_Size = src_width_ * src_height_ / 4;
// int I420_V_Size = I420_U_Size;
unsigned char *Y_data_src = (unsigned char *) src->data;
unsigned char *U_data_src = Y_data_src + I420_Y_Size;
unsigned char *V_data_src = Y_data_src + I420_Y_Size + I420_U_Size;
int src_stride_Y = src_width_;
int src_stride_U = (src_width_+1) >> 1;
int src_stride_V = src_stride_U;
//
int dest_I420_Y_Size = dst_width_ * dst_height_;
int dest_I420_U_Size = dst_width_ * dst_height_ / 4;
unsigned char *Y_data_dest = (unsigned char *) dest->data;
unsigned char *U_data_dest = Y_data_dest + dest_I420_Y_Size;
unsigned char *V_data_dest = Y_data_dest + dest_I420_Y_Size + dest_I420_U_Size;
int dest_stride_Y = dst_width_;
int dest_stride_U = (dst_width_+1) >> 1;
int dest_stride_V = dest_stride_U;
const uint8_t* y_ptr =
Y_data_src +
src_offset_y * src_stride_Y +
src_offset_x;
const uint8_t* u_ptr =
U_data_src +
src_offset_y / 2 * src_stride_U +
src_offset_x / 2;
const uint8_t* v_ptr =
V_data_src +
src_offset_y / 2 * src_stride_V +
src_offset_x / 2;
YOUME_libyuv::I420Scale(
y_ptr,
src_stride_Y,
u_ptr,
src_stride_U,
v_ptr,
src_stride_V,
cropped_src_width, cropped_src_height,
Y_data_dest,
dest_stride_Y,
U_data_dest,
dest_stride_U,
V_data_dest,
dest_stride_V,
dst_width_, dst_height_,
YOUME_libyuv::kFilterBilinear);
return dest;
}
YUV 420を格納するクラス宣言
class FrameImage
{
private:
bool need_delete_data=false;
public:
int width;
int height;
void* data;
public:
FrameImage(int width, int height, void* data);
FrameImage(int width, int height);
~FrameImage();
};
FrameImage::FrameImage(int width, int height, void* data) {
this->height = height;
this->width = width;
this->data = data;
}
FrameImage::FrameImage(int width, int height) {
this->height = height;
this->width = width;
int size = this->height * this->width * 3 / 2;
this->data = malloc(size);
memset(this->data, 128, size);
need_delete_data = true;
}
FrameImage::~FrameImage(){
if(need_delete_data){
free(this->data);
}
}