柴_笔记 2023-10-15 20:42 采纳率: 28.6%
浏览 11
已结题

安卓平台的ffmpeg 库使用

Windows11系统,qt5.14开发工具,开发安卓平台的app,
如何将FFMPEG库导入使用,用来拉取网络视频流

  • 写回答

7条回答 默认 最新

  • bug菌¹ Java领域优质创作者 2023-10-15 20:49
    关注

    该回答引用ChatGPT,望对题主有所帮助/启发;若有帮助,还望采纳。


    首先,您需要下载安装 Android NDK 和 Android SDK。在 Android Studio 中,可以通过 SDK Manager 安装 Android SDK 和 NDK。确保您已设置好环境变量,并且 PATH 包含了 NDK 和 SDK 的路径。

    然后,您需要编译 FFMPEG 库。可以使用以下脚本编译 FFMPEG 库:

    #!/bin/bash
    
    NDK=$HOME/Library/Android/sdk/ndk-bundle
    SYSROOT=$NDK/platforms/android-21/arch-arm/
    TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
    function build_one
    {
        ./configure \
        --prefix=$PREFIX \
        --enable-shared \
        --disable-static \
        --disable-doc \
        --disable-ffmpeg \
        --disable-ffplay \
        --disable-ffprobe \
        --disable-ffserver \
        --disable-avdevice \
        --disable-doc \
        --disable-symver \
        --disable-demuxers \
        --disable-bsfs \
        --disable-filters \
        --disable-encoders \
        --disable-muxers \
        --disable-protocols \
        --disable-indevs \
        --disable-outdevs \
        --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
        --target-os=linux \
        --arch=arm \
        --sysroot=$SYSROOT \
        --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
        --extra-ldflags="$ADDI_LDFLAGS" \
        $ADDITIONAL_CONFIGURE_FLAG
        make clean
        make
        make install
    }
    CPU=arm
    PREFIX=$(pwd)/android/$CPU
    ADDI_CFLAGS="-marm"
    ADDI_LDFLAGS=""
    build_one
    

    此脚本会从源代码编译出一个 Android 平台可用的 FFMPEG 库,其输出路径为当前目录下的 android/arm 文件夹。

    接下来,在 Qt 项目中添加 FFMPEG 库。可以将 FFMPEG 库作为一个子文件夹,或者作为一个库文件添加到项目中。在 .pro 文件中,可以使用以下配置:

    android {
        LIBS += -L/path/to/ffmpeg/lib -lavformat -lavcodec -lswscale -lavutil -lm
        INCLUDEPATH += /path/to/ffmpeg/include
    }
    

    其中,/path/to/ffmpeg/lib 和 /path/to/ffmpeg/include 分别为 FFMPEG 库的路径。

    接下来,您可以使用 FFMPEG 库拉取网络视频流。您可以使用以下代码片段:

    #define AVMEDIA_TYPE_VIDEO 1
    #define AVMEDIA_TYPE_AUDIO 2
    
    AVFormatContext *pFormatCtx = NULL;
    AVCodecContext *pCodecCtx = NULL;
    AVCodec *pCodec = NULL;
    int videoStream, audioStream;
    
    // Open video file
    if(avformat_open_input(&pFormatCtx, "your video url", NULL, NULL)!=0)
        return -1; // Couldn't open file
    
    // Retrieve stream information
    if(avformat_find_stream_info(pFormatCtx, NULL)<0)
        return -1; // Couldn't find stream information
    
    // Dump information about file onto standard error
    av_dump_format(pFormatCtx, 0, "your video url", 0);
    
    // Find the first video stream
    videoStream=-1;
    audioStream=-1;
    for(unsigned int i=0; i<pFormatCtx->nb_streams; i++) {
        if(pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO && videoStream < 0) {
            videoStream=i;
        }
        if(pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_AUDIO && audioStream < 0) {
            audioStream=i;
        }
    }
    if(videoStream==-1)
        return -1; // Didn't find a video stream
    
    // Get a pointer to the codec context for the video stream
    pCodecCtx=pFormatCtx->streams[videoStream]->codec;
    // Find the decoder for the video stream
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec==NULL) {
        fprintf(stderr, "Unsupported codec!\n");
        return -1; // Codec not found
    }
    // Open codec
    if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
        return -1; // Could not open codec
    
    // Read frames and decode
    AVPacket packet;
    av_init_packet(&packet);
    packet.data = NULL;
    packet.size = 0;
    while(av_read_frame(pFormatCtx, &packet)>=0) {
        // Is this a packet from the video stream?
        if(packet.stream_index==videoStream) {
            // Decode video frame
            AVFrame *pFrame = av_frame_alloc();
            int frameFinished;
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
            // Did we get a video frame?
            if(frameFinished) {
                // Display frame
            }
            av_frame_free(&pFrame);
        }
        // Free the packet that was allocated by av_read_frame
        av_free_packet(&packet);
    }
    

    在这个代码片段中,您需要将 "your video url" 替换成您需要拉取的网络视频流的 URL。这段代码会从网络视频流中读取数据包,并且解码视频帧。解码后的视频帧可以在 Qt 中显示。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月17日
  • 创建了问题 10月15日

悬赏问题

  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图