我编写了一些代码来生成 MP4 视频。这是代码的简化版本:
#include <iostream>
#include <fstream>
#include <cstdio>
#include <string>
#include <list>
#include <unistd.h>
extern "C"
{
#include "libavformat/avformat.h"
#include "libavutil/frame.h"
#include "libavcodec/avcodec.h"
#include "libavutil/imgutils.h"
}
using namespace std;
const int output_width = 180;
const int output_height = 320;
int main(int argc, char **argv)
{
AVCodec *output_avc = avcodec_find_encoder_by_name("libx264");
if (!output_avc)
abort();
AVCodecContext *output_cc = avcodec_alloc_context3(output_avc);
if (!output_cc)
abort();
output_cc->time_base.num = output_cc->time_base.den = 1;
output_cc->pix_fmt = AV_PIX_FMT_YUV420P;
output_cc->width = output_width;
output_cc->height = output_height;
if (avcodec_is_open(output_cc) == 0)
{
if (avcodec_open2(output_cc, output_avc, 0) < 0)
abort();
}
string outf = "res.mp4";
AVFormatContext *output_ctx;
avformat_alloc_output_context2(&output_ctx, NULL, NULL, outf.c_str());
AVStream *out_stream = avformat_new_stream(output_ctx, 0);
out_stream->codecpar->codec_id = AV_CODEC_ID_H264;
out_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
out_stream->codecpar->codec_tag = 0;
out_stream->codecpar->width = output_width;
out_stream->codecpar->height = output_height;
out_stream->codecpar->format = AV_PIX_FMT_YUV420P;
av_dump_format(output_ctx, 0, outf.c_str(), 1);
if (!(output_ctx->oformat->flags & AVFMT_NOFILE))
{
if (avio_open(&output_ctx->pb, outf.c_str(), AVIO_FLAG_WRITE) < 0)
abort();
}
if (avformat_write_header(output_ctx, NULL) < 0)
abort();
AVPacket packet;
AVFrame *frame;
int fileCount = 0;
for (int i = 0; i < 100; i++)
{
frame = av_frame_alloc();
frame->width = output_width;
frame->height = output_height;
frame->format = AV_PIX_FMT_YUV420P;
if (av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, AV_PIX_FMT_YUV420P, 32) < 0)
abort();
frame->pts = 60000 * i;
frame->pkt_dts = 60000 * i;
if (avcodec_send_frame(output_cc, frame) < 0)
abort();
av_frame_free(&frame);
av_new_packet(&packet, 0);
while (avcodec_receive_packet(output_cc, &packet) >= 0)
{
packet.pos = -1;
packet.dts = 4500 * fileCount;
packet.pts = 4500 * fileCount;
packet.duration = 4500;
av_write_frame(output_ctx, &packet);
av_packet_unref(&packet);
av_new_packet(&packet, 0);
fileCount++;
}
av_packet_unref(&packet);
}
avcodec_free_context(&output_cc);
av_write_trailer(output_ctx);
if (output_ctx && !(output_ctx->oformat->flags & AVFMT_NOFILE))
avio_close(output_ctx->pb);
avformat_free_context(output_ctx);
}
然后,我编译它(使用
g++ encode.cpp -lavcodec -lavformat -lavutil -g
并通过 Ubuntu 20.04 apt 安装库)并运行它。这是我得到的 MP4 文件(2872 字节,base64 编码):
AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAB39tZGF0AAAAAWdkAAys
2UMCnn4QAAADABAAAAMAIPFCmWAAAAABaOvjyyLAAAABBgX//6rcRem95tlIt5Ys2CDZI+7veDI2
NCAtIGNvcmUgMTU1IHIyOTE3IDBhODRkOTggLSBILjI2NC9NUEVHLTQgQVZDIGNvZGVjIC0gQ29w
eWxlZnQgMjAwMy0yMDE4IC0gaHR0cDovL3d3dy52aWRlb2xhbi5vcmcveDI2NC5odG1sIC0gb3B0
aW9uczogY2FiYWM9MSByZWY9MyBkZWJsb2NrPTE6MDowIGFuYWx5c2U9MHgzOjB4MTEzIG1lPWhl
eCBzdWJtZT03IHBzeT0xIHBzeV9yZD0xLjAwOjAuMDAgbWl4ZWRfcmVmPTEgbWVfcmFuZ2U9MTYg
Y2hyb21hX21lPTEgdHJlbGxpcz0xIDh4OGRjdD0xIGNxbT0wIGRlYWR6b25lPTIxLDExIGZhc3Rf
cHNraXA9MSBjaHJvbWFfcXBfb2Zmc2V0PS0yIHRocmVhZHM9MTAgbG9va2FoZWFkX3RocmVhZHM9
MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2Nv
bXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9
MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50
PTI1MCBrZXlpbnRfbWluPTEgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVh
ZD00MCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIzLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5
IHFwc3RlcD00IGlwX3JhdGlvPTEuNDAgYXE9MToxLjAwAIAAAAFliIQAF//+7oK+BTeKk2/DVSCr
MT4MeFdCVv4gBUyU0LeeB3T/sW2Y2XML/dzzR/1dfS/wWmJ+KGm0PX/sHuGpnyAn2gs5wsYABhgA
WoTf+9Y7PDk9QANDAAAAAUGaJGxBf/rtlHe1U64AATcAAAABQZ5CeILfbxYfLVgA1IEAAAABAZ5h
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
YQAAAAEAAAAATGF2ZjU4LjI5LjEwMA==
我尝试在 Windows 11 的媒体播放器中播放它。它根本无法播放,并且失败并出现 0xC00D36C4 错误。
后来我在Ubuntu 22.04中编译并运行了相同的代码。这次我得到了一个3161字节的文件(base64编码),可以在Media Player中正确播放:
AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACF5tZGF0AAAAGWdkAAys
2UMCnn4QAAADABAAAAMAIPFCmWAAAAAGaOvjyyLAAAACrgYF//+q3EXpvebZSLeWLNgg2SPu73gy
NjQgLSBjb3JlIDE2MyByMzA2MCA1ZGI2YWE2IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENv
cHlsZWZ0IDIwMDMtMjAyMSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9w
dGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1o
ZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2
IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0
X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTEwIGxvb2thaGVhZF90aHJlYWRz
PTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9j
b21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBiX3B5cmFtaWQ9MiBiX2FkYXB0
PTEgYl9iaWFzPTAgZGlyZWN0PTEgd2VpZ2h0Yj0xIG9wZW5fZ29wPTAgd2VpZ2h0cD0yIGtleWlu
dD0yNTAga2V5aW50X21pbj0xIHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhl
YWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02
OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAWmWIhAAV//7sz34FN2u2Mv14
OUV1GW52wf6mv09Y/+Eq5ywBqFdjI7RiQruDqkHmD84Ah+1pD+u+Ju9pbKoJmVnS6c+DhXKzmU8A
AEJAA5Q0japbJSyuwAA24QAAAENBmiRsR/93Hj0GFYn+ROeWur9cQ/zaceE37Gsw8XYMMBmtQahK
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
HWRhdGEAAAABAAAAAExhdmY1OC43Ni4xMDA=
无法播放的文件在 MP4 中缺少 AVC 配置框。
添加
output_cc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
在打开编解码器之前。