我在vs2012的Windows中使用ffmpeg库,将一系列图像转换为具有H264编码的Mp4。我是FFMPEG的新手。
下面是我的代码。一切都很好。创建了视频。但是,只有将扩展名更改为“.h264”,我才能在vlc播放器中播放视频,而且当我检查编解码器信息时,它也显示“H264-MPEG-4 AVC(第10部分)(h264)”。但是,当我为从网上下载的其他mp4视频检查了相同内容时。它说:“H264-MPEG-4” AVC(第10部分)(avc1)。我不知道哪里出了问题。我也搜索了很多,有些人说像添加SPS和PPS。
const uint8_t sps[] = { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00,
0x0a, 0xf8, 0x41, 0xa2 };
const uint8_t pps[] = { 0x00, 0x00, 0x00, 0x01, 0x68, 0xce,
0x38, 0x80 };
因此,我在添加图像流之前将上述值添加到了视频文件中。但是没有运气。
任何人都可以帮忙。。
const uint8_t sps[] = { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00,
0x0a, 0xf8, 0x41, 0xa2 };
const uint8_t pps[] = { 0x00, 0x00, 0x00, 0x01, 0x68, 0xce,
0x38, 0x80 };
const uint8_t slice_header[] = { 0x00, 0x00, 0x00, 0x01, 0x05, 0x88,
0x84, 0x21, 0xa0 };
const uint8_t macroblock_header[] = { 0x0d, 0x00 };
const uint8_t spspps[] = { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x0a, 0xf8, 0x41, 0xa2,
0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x38, 0x80
};
int ff_load_image(uint8_t *data[4], int linesize[4],
int *w, int *h, enum PixelFormat *pix_fmt,
const char *filename, void *log_ctx)
{
AVInputFormat *iformat = NULL;
AVFormatContext *format_ctx = NULL;
AVCodec *codec=NULL;
AVCodecContext *codec_ctx=NULL;
AVFrame *frame=NULL;
int frame_decoded, ret = 0;
AVPacket pkt;
av_register_all();
iformat = av_find_input_format("image2");
if ((ret = avformat_open_input(&format_ctx, filename, iformat, NULL)) < 0) {
return ret;
}
codec_ctx = format_ctx->streams[0]->codec;
codec = avcodec_find_decoder(codec_ctx->codec_id);
if (!codec) {
ret = AVERROR(EINVAL);
goto end;
}
if ((ret = avcodec_open2(codec_ctx, codec, NULL)) < 0) {
goto end;
}
//if (!(frame = avcodec_alloc_frame()) ) {
if (!(frame = av_frame_alloc()) ) {
ret = AVERROR(ENOMEM);
goto end;
}
ret = av_read_frame(format_ctx, &pkt);
if (ret < 0) {
goto end;
}
ret = avcodec_decode_video2(codec_ctx, frame, &frame_decoded, &pkt);
if (ret < 0 || !frame_decoded) {
goto end;
}
ret = 0;
*w = frame->width;
*h = frame->height;
*pix_fmt = (PixelFormat)frame->format;
if ((ret = av_image_alloc(data, linesize, *w, *h, (AVPixelFormat)*pix_fmt, 16)) < 0)
goto end;
ret = 0;
av_image_copy(data, linesize, (const uint8_t **)frame->data, frame->linesize, (AVPixelFormat)*pix_fmt, *w, *h);
end:
if(codec_ctx) { avcodec_close(codec_ctx); }
if(format_ctx) { avformat_close_input(&format_ctx); }
if(frame) { av_freep(&frame); }
av_free_packet(&pkt);
return ret;
}
int load_image_into_frame(AVFrame *frame, const char *filename)
{
int retval = -1, res;
static struct SwsContext *sws_ctx;
uint8_t *image_data[4];
int linesize[4];
int source_width, source_height;
enum PixelFormat source_fmt;
res = ff_load_image(image_data, linesize, &source_width, &source_height, &source_fmt, filename, NULL);
if (source_fmt != frame->format) {
sws_ctx = sws_getContext(source_width, source_height, (AVPixelFormat)source_fmt,
frame->width, frame->height, (AVPixelFormat)frame->format,
sws_flags, NULL, NULL, NULL);
sws_scale(sws_ctx,
(const uint8_t * const *)image_data, linesize,
0, frame->height, frame->data, frame->linesize);
}
retval = 0;
error:
av_freep(&image_data[0]);
sws_freeContext(sws_ctx);
return retval;
}
int write_frame_to_file(FILE *file, AVFrame *frame, AVCodecContext *codec_context, AVPacket *pkt) {
int res, got_output;
av_init_packet(pkt);
pkt->data = NULL;
pkt->size = 0;
/* generate synthetic video */
frame->pts += 30;
res = avcodec_encode_video2(codec_context, pkt, frame, &got_output);
if (got_output) {
fwrite(pkt->data, 1, pkt->size, file);
av_free_packet(pkt);
}
return 0;
error:
return -1;
}
int write_image_to_file(FILE *file, const char *filename, int count, AVFrame *frame, AVCodecContext *codec_context, AVPacket *pkt) {
int res, i;
res = load_image_into_frame(frame, filename);
for (i = 0; i < count; i++) {
res = write_frame_to_file(file, frame, codec_context, pkt);
}
return 0;
error:
return -1;
}
int write_delayed_frames_to_file(FILE *file, AVFrame *frame, AVCodecContext *codec_context, AVPacket *pkt) {
int res, got_output;
for (got_output = 1; got_output;) {
res = avcodec_encode_video2(codec_context, pkt, NULL, &got_output);
if (got_output) {
fwrite(pkt->data, 1, pkt->size, file);
av_free_packet(pkt);
}
}
return 0;
error:
return -1;
}
AVCodecContext *get_codec_context(int width, int height, int fps)
{
int res;
avcodec_register_all();
AVCodec *codec;
AVCodecContext *codec_context = NULL;
codec = avcodec_find_encoder(AV_CODEC_ID_H264);
codec_context = avcodec_alloc_context3(codec);
codec_context->bit_rate = 441000;
codec_context->width = width;
codec_context->height = height;
AVRational temp_113 = {1, fps};
AVRational temp_114 = {fps, 1};
codec_context->time_base= temp_113;
codec_context->gop_size = 10;
codec_context->max_b_frames=1;
codec_context->pix_fmt = AV_PIX_FMT_YUV420P;
res = avcodec_open2(codec_context, codec, NULL);
return codec_context;
error:
return NULL;
}
AVFrame *get_av_frame(AVCodecContext *codec_context) {
int res;
AVFrame *frame;
frame = av_frame_alloc();
frame->height = codec_context->height;
frame->width = codec_context->width;
frame->format = codec_context->pix_fmt;
frame->pts = 0;
res = av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, (AVPixelFormat)frame->format, 1);
return frame;
error:
return NULL;
}
int main(int argc, char **argv)
{
const char *filename = "result video\\test.mp4";
FILE *file=NULL;
int res, retval=-1;
AVCodecContext *codec_context= NULL;
AVFrame *frame=NULL;
AVPacket pkt;
uint8_t endcode[] = { 0, 0, 1, 0xb7 };
codec_context = get_codec_context(1920, 1080, 30);
file = fopen(filename, "wb");
//check(file != NULL, "could not open destination file %s", filename);
frame = get_av_frame(codec_context);
//fwrite(sps, 1, sizeof(sps), file);
//fwrite(pps, 1, sizeof(pps), file);
/*codec_context->extradata = (uint8_t *)malloc(sizeof(uint8_t) * sizeof(spspps));
for(unsigned int index = 0; index < sizeof(spspps); index++)
{
codec_context->extradata[index] = spspps[index];
}
codec_context->extradata_size = (int)sizeof(spspps);*/
codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
int i, frames= 51;
for (i = 0; i < frames; i++) {
std::stringstream ss;
ss<<"\\frames\\out"<<( i + 1)<<".jpg";
res = write_image_to_file(file, ss.str().c_str(), 3, frame, codec_context, &pkt);
}
res = write_delayed_frames_to_file(file, frame, codec_context, &pkt);
fwrite(endcode, 1, sizeof(endcode), file);
retval = 0;
error:
if (file)
fclose(file);
if (codec_context) {
avcodec_close(codec_context);
av_free(codec_context);
}
if (frame) {
av_freep(&frame->data[0]);
av_free(frame);
}
return retval;
}
}
最佳答案
您没有使用AVFormatContext
进行编码,因此我知道您无法根据需要输出.mp4文件的原因。
你应该:
我会发布代码,但在线上有很多示例,您可以将这些函数名称与“ffmpeg编码”关键字混合使用。
关于c++ - FFmpeg:用C++生成H264视频,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33100486/