zoukankan      html  css  js  c++  java
  • FFmpeg(10)-利用FFmpeg进行视频像素格式和尺寸的转换(sws_getCachedContext(), sws_scale())

    一.包含头文件和库文件

    像素格式的相关函数包含在 libswscale.so 库中,CMakeLists需要做下列改动:

    # swscale
    add_library(swscale SHARED IMPORTED)
    set_target_properties(swscale PROPERTIES IMPORTED_LOCATION ${FF}/libswscale.so)

    target_link_libraries

    target_link_libraries( # Specifies the target library.
                           native-lib
                           avcodec
                           avformat
                           avutil
                           swscale
    
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib} )

    同时在代码中包含头文件 #include <libswscale/swscale.h> 

    二. 相关函数说明

    a)

    sws_getContext()                                                        // 像素格式转换的上下文。会创建新的空间

    struct SwsContext *sws_getCachedContext();           // 函数名补全。会根据传入的上下文到缓冲里面去找。

    参数说明:

    1. 第一参数可以传NULL,默认会开辟一块新的空间。
    2. srcW,srcH, srcFormat, 原始数据的宽高和原始像素格式(YUV420),
    3. dstW,dstH,dstFormat;   目标宽,目标高,目标的像素格式(这里的宽高可能是手机屏幕分辨率,RGBA8888),这里不仅仅包含了尺寸的转换和像素格式的转换
    4. flag 提供了一系列的算法,快速线性,差值,矩阵,不同的算法性能也不同,快速线性算法性能相对较高。只针对尺寸的变换。对像素格式转换无此问题
    5. #define SWS_FAST_BILINEAR 1

      #define SWS_BILINEAR 2

      #define SWS_BICUBIC 4

      #define SWS_X      8

      #define SWS_POINT 0x10

      #define SWS_AREA 0x20

      #define SWS_BICUBLIN 0x40

    后面还有两个参数是做过滤器用的,一般用不到,传NULL,最后一个参数是跟flag算法相关,也可以传NULL。

    b)

     int sws_scale();

    具体每一帧数据的处理。

    struct SwsContext *c                   // 像素格式转换的上下文

    uint8_t *const srcSlice[]                // src的Slice,对应的具体数据的数组,是指针数组,也就是二维数组,YUV420P(三行数据)

    const int srcStride[]                      // linesize, 一行对应的大小。

    int srcSliceY                                 // 用不到,直接传0即可。

    int srcSliceH                                // 图像的高度。

    uint8_t *const dst[]                      // 目标的地址。也是一个指针数组。

    const int dstStride[]                     // 输入的linesize

    三, 相关代码参考

    // 初始化像素格式转换上下文
        SwsContext *vctx = NULL;
        int outWidth = 1280;
        int outHeight = 720;
        char *rgb = new char[1920*1080*4];
    
        for (;;) {
    
            if (getNowMs() - start >= 3000) {
                LOGI("now decoder fps is: %d", frameCount / 3);
                start = getNowMs();
                frameCount = 0;
            }
            int ret = av_read_frame(ic, packet);
            if (ret != 0) {
                LOGE("读取到结尾处");
                int pos = 20 * r2d(ic->streams[videoStream]->time_base);
                // 改变播放进度
                av_seek_frame(ic, videoStream, pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);
                continue;
            }
    
    //        LOGI("Read a Packet. streamIndex=%d, size=%d, pts=%lld, flag=%d",
    //             packet->stream_index,
    //             packet->size,
    //             packet->pts,
    //             packet->flags
    //        );
    
            AVCodecContext *cc = vc;
            if (packet->stream_index == audioStream) cc = ac;
            // 发送到线程中去解码(将packet写入到解码队列当中去)
            ret = avcodec_send_packet(cc, packet);
            // 清理
            int p = packet->pts;
            av_packet_unref(packet);
            if (ret != 0) {
                // LOGE("avcodec_send_packet failed.");
                continue;
            }
    
            for(;;) {
                // 从已解码成功的数据当中取出一个frame, 要注意send一次,receive不一定是一次
                ret = avcodec_receive_frame(cc, frame);
                if (ret != 0) {
                    break;
                }
                if (cc == vc) {
                    frameCount++;
                    vctx = sws_getCachedContext(
                            vctx,
                            frame->width,
                            frame->height,
                            (AVPixelFormat)frame->format,
                            outWidth,
                            outHeight,
                            AV_PIX_FMT_RGBA,
                            SWS_FAST_BILINEAR,
                            0, 0, 0
                    );
                    if (!vctx) {
                        LOGE("sws_getCachedContext failed!");
                    } else {
                        // 开始像素格式转换
                        uint8_t  *data[AV_NUM_DATA_POINTERS] = {0};
                        data[0] = (uint8_t *)rgb;
                        int lines[AV_NUM_DATA_POINTERS] = {0};
                        lines[0] = outWidth * 4;
                        int h = sws_scale(
                                vctx,
                                (const uint8_t **)frame->data,
                                frame->linesize,
                                0,
                                frame->height,
                                data, lines
                        );
                        LOGI("sws_scale = %d", h);
                    }
                }
                // LOGI("Receive a frame.........");
            }
        }
  • 相关阅读:
    Leetcode 538. Convert BST to Greater Tree
    Leetcode 530. Minimum Absolute Difference in BST
    Leetcode 501. Find Mode in Binary Search Tree
    Leetcode 437. Path Sum III
    Leetcode 404. Sum of Left Leaves
    Leetcode 257. Binary Tree Paths
    Leetcode 235. Lowest Common Ancestor of a Binary Search Tree
    Leetcode 226. Invert Binary Tree
    Leetcode 112. Path Sum
    Leetcode 111. Minimum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/9829290.html
Copyright © 2011-2022 走看看