当前位置: 首页 > 知识库问答 >
问题:

FFMPEG库-将原始图像转换为h264流,并且输出文件不包含pts和dts信息

钮鸿煊
2023-03-14

我正在尝试使用ffmpeg C++库将几个原始的yuyv图像转换成h264流,图像来自内存并以24fps左右的字符串形式传递,我按照以下步骤进行约定:

  1. 初始化AVFormatContext、AVCodec、AVCodecContext并创建新的AVStream。本步骤主要参考ffmpeg-libav-tutorial,和AVFormatContext使用自定义write_buffer()函数(参考simplest_ffmpeg_mem_handler)
  2. 接收原始帧数据,设置宽度和高度(1920x1080),并设置pts和DTS。在这里,我手动将输出fps设置为24,并使用全局计数器计算帧数,并且pts由该计数器计算,代码段(video_avs是AVStream,output_fps是24并且time_base是1/24):
    input_frame->width = w;  // 1920
    input_frame->height = h;  // 1080
    input_frame->pkt_dts = input_frame->pts = global_pts;
    global_pts += video_avs->time_base.den/video_avs->time_base.num / output_fps.num * output_fps.den;

将其从yuyv转换为yuv422(因为h264不支持yuyv),并将其大小从1920x1080调整为640x480(因为我需要此分辨率输出),使用sws_scale()

使用avcodec_send_frame()avcodec_receive_packet()获取输出数据包。设置output_packetduration和stream_index,然后使用av_write_frame()写入帧数据。

    AVPacket *output_packet = av_packet_alloc();
    int response = avcodec_send_frame(encoder->video_avcc, frame);
    while (response >= 0) {
        response = avcodec_receive_packet(encoder->video_avcc, output_packet); // !! here output_packet.size is calculated
        if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
            break;
        } 
        else if (response < 0) {
            printf("Error while sending packet to decoder");  // ??av_err2str(response)会报错
            return response;
        }

        // duration = next_pts - this_pts = timescale / fps = 1 / timebase / fps
        output_packet->duration = (encoder->video_avs->time_base.den / encoder->video_avs->time_base.num) / (output_fps.num / output_fps.den);
        output_packet->stream_index = 0;
        int response = av_write_frame(encoder->avfc, output_packet);  // packet order are not ensure
        if (response != 0) { printf("Error %d while receiving packet from decoder", response); return -1;}   
    }
    av_packet_unref(output_packet);
    av_packet_free(&output_packet);

完成以上所有步骤后,output.mp4无法播放,FFProbe output.mp4-show_frames输出为(映像):

Input #0, h264, from '/Users/ming/code/dev/haomo/output.mp4':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: h264 (High 4:2:2), yuv422p(progressive), 640x480, 24.92 fps, 24 tbr, 1200k tbn, 48 tbc
[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=N/A
pkt_pts_time=N/A
pkt_dts=N/A
pkt_dts_time=N/A
best_effort_timestamp=N/A
best_effort_timestamp_time=N/A

请注意,在步骤4中调用av_write_frame()之前和之后,传递的参数output_packet包含正确的pts和dts信息,我无法弄清楚输出流丢失这些信息的原因。

共有1个答案

赵智勇
2023-03-14

我想通了,输出流是一个原始的h264流,我直接将这个流存储到一个后缀为“.mp4”的文件中,所以它实际上不是一个正确的mp4文件。

然后将流存储到output.h264文件中,并使用ffmpeg将其转换为mp4文件:ffmpeg-framerate 24-i output.h264-c copy output.mp4,最后该output.mp4包含正确的pts数据并可以播放。

 类似资料:
  • 下面是我的代码 函数executeCommand 误差 libavdevice 57。0.101/57。0.101 libavfilter 6。31.100/6。31.100 libswscale 4。0.100/4。0.100 输出#0,mp4,到'ffmpeg-ss 0-I/storage/emulated/0/video/demo.mp4-t 30-c copy/storage/emulat

  • 大小范围在2.5MB-20MB之间。这个问题在较长的剪辑上变得更糟,例如7分钟的范围是9MB-120MB。 正常吗? 我试图捕捉同样的场景,但还是得到了不同的结果。

  • 问题内容: 我想将PDF文档转换为图像。我正在使用Ghost4j。 问题: Ghost4J需要gsdll32.dll文件在运行时,我也 并不 想使用的DLL文件。 问题1: 在ghost4j中,有没有办法在没有dll的情况下转换图像? 问题2: 我在PDFBox API中找到了解决方案。convertToImage()将PDF页面转换为图像格式。 PDF文档上只有文本。运行此代码时出现该异常: 问

  • 我想把PDF文档转换成图像。我用的是Ghost4j。 问题:Ghost4J需要gsdll32。dll文件,我不想使用dll文件。 问题1:是否有任何方法,在ghost4j转换图像没有dll? 问题2:我在PDFBox API中找到了解决方案<代码>组织。阿帕奇。pdfbox。pdmodel。PDPagep具有将PDF页面转换为图像格式的方法convertToImage()。 我只有PDF文档上的文

  • 我有html文本我想转换成一个文档文件。我尝试使用CloudConvert API控制台(https://CloudConvert.com/API/convert/html-to-doc)生成请求。在Code Snippets>HTML表单中,这给出了以下表单: 然而,这不起作用,我总是得到同样的错误: 错误是误导性的,因为这里没有输入“文件”;并且输出文件的名称是必需的--如果我不使用filen

  • 我在我的代码中使用ffmpeg库从摄像机捕获rtsp流并用FLV编写。如果我只从一个摄像机捕获流,而摄像机只有视频流,那么没有任何错误,我得到了第一个带有pts和DTS1698557894的包,其他包的pts和dts慢慢增加。但是如果摄像机有视频和音频流,那么奇怪的事情就会发生。例如,视频数据包pts和dts以1698557894开始并缓慢增加,音频数据包以0开始并缓慢增加,在~50之后,数据包跳