ffmpeg avframe yuv 旋转

本文详细介绍了如何使用FFmpeg库中的AVFrame结构实现视频帧的顺时针旋转功能,包括90度、180度及270度旋转的具体算法实现,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// 顺时针旋转 ffmpeg avframe yuv  rotation


enum VideoRotationMode {
  kRotateNone = 0,
  kRotate90 = 90,
  kRotate180 = 180,
  kRotate270 = 270,
};






VideoRotationMode rotation_ = kRotateNone;






bool Rotate(const AVFrame* src, AVFrame** dst)
{
    if (rotation_ == kRotateNone) {
        return false;
    }
    AVFrame* tmp = *dst;
    if (!tmp) {
        tmp = av_frame_alloc();
    }
// width_、height_ 为src的宽高,若是90或者270则宽高交换值
    if (tmp->width != width_ || tmp->height != height_) {
        av_frame_free(&tmp);
        tmp = av_frame_alloc();
        uint8_t* buffer = (uint8_t*)av_malloc(P_av_image_get_buffer_size(AV_PIX_FMT_YUV420P, width_, height_, 1));
        av_image_fill_arrays(tmp->data, tmp->linesize, buffer, AV_PIX_FMT_YUV420P, width_, height_, 1);
    }




    if (rotation_ == kRotate90) {
        Rotate90(src, tmp);
    }
    else if (rotation_ == kRotate180) {
        Rotate180(src, tmp);
    }
    else if (rotation_ == kRotate270) {
        Rotate270(src, tmp);
    }
    else {
        return false;
    }


    tmp->format     = src->format;
    tmp->pts        = src->pts;
    tmp->pkt_pts    = src->pkt_pts;
    tmp->pkt_dts    = src->pkt_dts;
    tmp->key_frame  = src->key_frame;


    *dst = tmp;


    return true;
}




void Rotate90(const AVFrame* src, AVFrame* dst)
{
    int half_width = src->width >> 1;
    int half_height = src->height >> 1;




    int size = src->linesize[0] * src->height;
    int half_size = size >> 2;




    for (int j = 0, n = 0; j < src->width; j++) {
        int pos = size;
        for (int i = src->height - 1; i >= 0; i--) {
            pos -= src->linesize[0];
            dst->data[0][n++] = src->data[0][pos + j];
        }
    }




    for (int j = 0, n = 0; j < half_width; j++) {
        int pos = half_size;
        for (int i = half_height - 1; i >= 0; i--) {
            pos -= src->linesize[1];
            dst->data[1][n] = src->data[1][pos + j];
            dst->data[2][n++] = src->data[2][pos + j];
        }
    }




    dst->height = src->width;
    dst->width  = src->height;
}




void Rotate180(const AVFrame* src, AVFrame* dst)
{
    int half_width = src->width >> 1;
    int half_height = src->height >> 1;




    int pos = src->linesize[0] * src->height;
    for (int i = 0, n = 0; i < src->height; i++) {
        pos -= src->linesize[0];
        for (int j = src->width - 1; j >= 0; j--) {
            dst->data[0][n++] = src->data[0][pos + j];
        }
    }




    pos = src->linesize[0] * src->height >> 2;
    for (int i = 0, n = 0; i < half_height; i++) {
        pos -= src->linesize[1];
        for (int j = half_width - 1; j >= 0; j--) {
            dst->data[1][n] = src->data[1][pos + j];
            dst->data[2][n++] = src->data[2][pos + j];
        }
    }




    dst->width  = src->width;
    dst->height = src->height;
}




void Rotate270(const AVFrame* src, AVFrame* dst)
{
    int half_width = src->linesize[0] >> 1;
    int half_height = src->height >> 1;




    for (int i = src->width - 1, n = 0; i >= 0; i--) {
        for (int j = 0, pos = 0; j < src->height; j++) {
            dst->data[0][n++] = src->data[0][pos + i];
            pos += src->linesize[0];
        }
    }




    for (int i = (src->width >> 1) - 1, n = 0; i >= 0; i--) {
        for (int j = 0, pos = 0; j < half_height; j++) {
            dst->data[1][n] = src->data[1][pos + i];
            dst->data[2][n++] = src->data[2][pos + i];
            pos += half_width;
        }
    }




    dst->width = src->height;
    dst->height = src->width;
}

参考:http://blog.youkuaiyun.com/veilling/article/details/52200326


                
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

满衣兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值