在使用 ffmpeg 处理 h264 转 mp4 时,生成的 mp4 无法播放,经排查发现是原始数据包没有时间戳信息。

​

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

int main() {

    QString input = QString("input.h264");
    QString output = QString("output.mp4");
    std::string inputfile = input.toStdString();
    std::string outputfile = output.toStdString();
    AVFormatContext *input_ctx = nullptr;
    AVFormatContext *output_ctx = nullptr;

    if (avformat_open_input(&input_ctx, inputfile.c_str(), nullptr, nullptr) < 0) {
        return -1;
    }

    if (avformat_find_stream_info(input_ctx, nullptr) < 0) {
        return -1;
    }

    int video_stream_index = -1;
    for (unsigned int i = 0; i < input_ctx->nb_streams; i++) {
        if (input_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_index = i;
            break;
        }
    }

    if (video_stream_index == -1) {
        return -1;
    }

    avformat_alloc_output_context2(&output_ctx, nullptr, "mp4", outputfile.c_str());
    if (!output_ctx) {
        return -1;
    }

    AVStream *out_stream = avformat_new_stream(output_ctx, nullptr);
    if (!out_stream) {
        return -1;
    }

    AVStream *in_stream = input_ctx->streams[video_stream_index];
    avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);

    out_stream->codecpar->codec_tag = av_codec_get_tag(
        output_ctx->oformat->codec_tag, in_stream->codecpar->codec_id);
    if (out_stream->codecpar->codec_tag == 0) {
        return -1;
    }

    out_stream->time_base = in_stream->time_base;
    out_stream->r_frame_rate = in_stream->r_frame_rate;

    if (!(output_ctx->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&output_ctx->pb, outputfile.c_str(), AVIO_FLAG_WRITE) < 0) {
            return -1;
        }
    }

    if (avformat_write_header(output_ctx, nullptr) < 0) {
        return -1;
    }

    AVPacket* packet = av_packet_alloc();
    av_packet_unref(packet);
    int64_t next_pts = 0;
    AVRational frame_rate = av_guess_frame_rate(input_ctx, in_stream, nullptr);
    while (av_read_frame(input_ctx, packet) >= 0) {
        // 计算时间戳
        if (packet->stream_index == video_stream_index) {
            if (packet->pts == AV_NOPTS_VALUE) {
                packet->pts = next_pts;
                packet->dts = next_pts;
                next_pts += av_rescale_q(1, frame_rate.den ? (AVRational){frame_rate.den, frame_rate.num} : (AVRational){1,25}, out_stream->time_base);
            }
            av_packet_rescale_ts(packet,
                                 in_stream->time_base,
                                 out_stream->time_base);
            packet->stream_index = out_stream->index;

            if (av_interleaved_write_frame(output_ctx, packet) < 0) {
                av_packet_unref(packet);
                break;
            }
        }
        av_packet_unref(packet);
    }
    av_write_trailer(output_ctx);

    avformat_close_input(&input_ctx);
    if (output_ctx && !(output_ctx->oformat->flags & AVFMT_NOFILE))
        avio_closep(&output_ctx->pb);
    avformat_free_context(output_ctx);

    return 0;
}

[点击并拖拽以移动]
​

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐