LibYUVトランスコードトリミングC++

11765 ワード

  • 32 bgra to yuv 420変換
  • 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;
    }
    
  • yuv 420回転ミラー
  • 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;
        }
        
    }
    
  • yuv 420ミラー
  • 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);
    }
    
  • yuv最大表示範囲の拡大/縮小を維持
  • 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);
        }
    }