xengine-qyt 2023-03-16 14:51 采纳率: 89.5%
浏览 15
已结题

拉取的流保存为h264无法播放 是为什么?

avpacket 的 data 不能直接保存为h264吗?


#include <thread>
#include <iostream>
#include <fstream>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavcodec/bsf.h>
#include <libavformat/avformat.h>
}

#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avdevice.lib")
#pragma comment(lib,"avfilter.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swresample.lib")
#pragma comment(lib,"swscale.lib")

int mp4toannexb(AVBSFContext* bsf_ctx, AVPacket* pkt, std::ofstream& out)
{
    int ret;

    ret = av_bsf_send_packet(bsf_ctx, pkt);
    if (ret < 0) {
        std::cout << "bsf send packet failed, errno:" << ret << std::endl;
        return -1;
    }

    for (;;) {
        ret = av_bsf_receive_packet(bsf_ctx, pkt);
        if (AVERROR_EOF == ret || AVERROR(EAGAIN) == ret) {
            return 0;
        }
        if (ret < 0) {
            std::cout << "Could not receive packet, errno:" << ret << std::endl;
            return -1;
        }
        out.write((const char*)pkt->data, pkt->size);
    }
    return 0;
}


int main()
{
    AVOutputFormat* ofmt = NULL;
    AVFormatContext* ifmt_ctx = NULL;
    AVBSFContext* bsf_ctx = NULL;
    AVPacket* pkt = NULL;
    const char* in_filename = "http://219.151.31.38/liveplay-kk.rtxapp.com/live/program/live/hnwshd/4000000/mnf.m3u8";
    int ret = -1;
    int video_index = -1;
    std::ofstream outh264("D:\\ConsoleApplication1\\Debug\\out.h264", std::ios::binary | std::ios::trunc);
    // 初始化网络
    avformat_network_init();

    // 初始化输入格式上下文  
    if ((ifmt_ctx = avformat_alloc_context()) == NULL) {
        std::cout << "avformat_alloc_context failed." << std::endl;
        exit(1);
    }

    // 打开输入格式上下文
    if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
        std::cout << "Could not open input file." << std::endl;
        exit(1);
    }

    // 获取输入信息
    if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
        std::cout << "Failed to retrieve input stream information" << std::endl;
        return -1;
    }

    // 申请pkt
    if (!(pkt = av_packet_alloc())) {
        std::cout << "Could not allocate packet" << std::endl;
        return -1;
    }

    video_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if (video_index < 0) {
        std::cout << "Could not find stream " << std::string(av_get_media_type_string(AVMEDIA_TYPE_VIDEO)) << std::endl;
        return -1;
    }

    av_dump_format(ifmt_ctx, 0, in_filename, 0);

    const AVBitStreamFilter* filter = av_bsf_get_by_name("h264_mp4toannexb");
    if (NULL == filter) {
        std::cout << "Could not create filter" << std::endl;
        return -1;
    }

    ret = av_bsf_alloc(filter, &bsf_ctx);
    if (ret < 0) {
        printf("Could not alloc bitstream filter \n");
        return -1;
    }

    // avcodec_parameters_from_context
    ret = avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[video_index]->codecpar);
    if (ret < 0) {
        printf("Parameter copy filed, errno: %d \n", ret);
        return -1;
    }

    ret = av_bsf_init(bsf_ctx);
    if (ret < 0) {
        printf("BSF init failed, errno: %d \n", ret);
        return -1;
    }

    while (av_read_frame(ifmt_ctx, pkt) >= 0) {
        if (pkt->stream_index == video_index)
        {
            mp4toannexb(bsf_ctx, pkt, outh264);
        }
        av_packet_unref(pkt);
    }
    // 释放
    outh264.close();
    avformat_close_input(&ifmt_ctx);
    av_packet_free(&pkt);
    av_bsf_free(&bsf_ctx);

    return 0;
}

  • 写回答

3条回答 默认 最新

  • 追cium 2023-03-16 15:19
    关注

    参考GPT和自己的思路:

    avpacket 的 data 保存为 h264 是不正确的方式。avpacket 中的 data 是视频压缩数据的一部分,需要进行解码才能得到原始图像数据。如果希望保存为 h264,可以将 avpacket 中的压缩数据写入到一个编码器中,编码成 h264 格式后再保存为文件。在代码中,可以使用 libx264 之类的编码器进行编码。另外,在编码之前需要设置编码器的参数,包括分辨率、帧率、码率等等。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 3月25日
  • 已采纳回答 3月17日
  • 创建了问题 3月16日

悬赏问题

  • ¥15 请问读取环境变量文件失败是什么原因?
  • ¥15 在若依框架下实现人脸识别
  • ¥15 网络科学导论,网络控制
  • ¥100 安卓tv程序连接SQLSERVER2008问题
  • ¥15 利用Sentinel-2和Landsat8做一个水库的长时序NDVI的对比,为什么Snetinel-2计算的结果最小值特别小,而Lansat8就很平均
  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载