视频的裁剪后缩放功能。
/**
* 等比例截源图像
* @param[in] src 源I420图像
* @param[in] src_width 源I420图像长度
* @param[in] src_height 源I420图像高度
* @param[out] dst 输出I420图像
* @param[in] dst_width 目的I420图像长度
* @param[in] dst_height 目的I420图像高度
* @return bool 是否正确裁剪
*/
bool CutScale(unsigned char* src, int src_width, int src_height, std::string &dst, int dst_width, int dst_height)
{
int src_width_ = src_width; //图像宽高
int src_height_ = src_height;
int dst_width_ = dst_width; //画布宽高
int dst_height_ = dst_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 =
min(src_width_, dst_width_ * src_height_ / dst_height_);
const int cropped_src_height =
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;
unsigned char *Y_data_src = src;
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 *)dst.c_str();
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;
bool ret=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_,
libyuv::kFilterBox);
return ret == 0;
}