C ++ h264 ffmpeg / libav编码/解码(无损)问题
洞察使用ffmpeg h264编码/解码视频(无损)
所以我在编码部分做了一些工作,在264中编码了一个AVI,但VLC不会播放它,但图腾会。 解码相同的文件证明麻烦。 (我想要完全相同的数据/框架出去),我得到这些;
saving frame 5
Video decoding
[h264 @ 0x1d19880] decode_slice_header error
frame :6
saving frame 6
Video decoding
[h264 @ 0x1d19880] error while decoding MB 15 7, bytestream -27
[h264 @ 0x1d19880] concealing 194 DC, 194 AC, 194 MV errors in I frame
frame :7
saving frame 7
Video decoding
[h264 @ 0x1d19880] decode_slice_header error
并最终达成此目的
[H264 Decoder @ 0x7f1320766040] frame :11
Broken frame packetizing
[h264 @ 0x1d19880] SPS changed in the middle of the frame
[h264 @ 0x1d19880] decode_slice_header error
[h264 @ 0x1d19880] no frame!
Error while decoding frame 11
游戏结束。
现在我怀疑我必须回到1.编码部分,有证据证明VLC不会播放它!
我这样编码。
void encode(char *Y,char *U,char *V){
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
fflush(stdout);
frame->data[0] = (uint8_t*)Y;
frame->data[1] = (uint8_t*)U;
frame->data[2] = (uint8_t*)V;
frame->pts = ++i;
ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
if (ret < 0) {
fprintf(stderr, "Error encoding framen");
exit (EXIT_FAILURE);
}
if (got_output) {
printf("Write frame %3d (size=%5d)n", i, pkt.size);
fwrite(pkt.data, 1, pkt.size, f);
av_free_packet(&pkt);
}
}
编解码器是这样设置的:
AVCodecID dasd = AV_CODEC_ID_H264;
codec = avcodec_find_encoder(dasd);
c = avcodec_alloc_context3(codec);
c->bit_rate = 400000;
c->width = 320;
c->height = 240;
c->time_base= (AVRational){1,25};
c->gop_size = 10;
c->max_b_frames=1;
c->pix_fmt = AV_PIX_FMT_YUV420P;
av_opt_set(c->priv_data, "preset", "slow", 0);
avcodec_open2(c, codec, NULL);
由于我是无损的,我没有处理延迟帧(这是一个正确的假设吗?)我可能实际上没有编码无损,看起来像我可能不得不采取类似
AVDictionary *param;
av_dict_set(¶m, "qp", "0", 0);
然后打开...
所以我想我的问题是这些:
谢谢。
有些东西在你的编码中是严重错误的。 错误“I帧中的MV错误”在这里是奇怪的,在I帧中不应该有任何MV。 它似乎解析它的头 - 自己出错了。 请分享VLC失败的比特流和更多细节
您正在将原始附件帧写入文件而没有任何容器包装。 使用像mp4或matroska容器和VLC应该很高兴。
所以,得到这个包裹。 因为在这里有很多半有效工作信息,或者只是在不同于我的情况下工作,这是我的代码:
init代码。 - 这里首先要注意的是av_guess_format“avi”不是“mp4”或其他什么奇异的h264 - 第二件事是,不要乱用比特率! 随着我在网上找到的所有样本都设置好了,这让我发疯。 保持独立并通过“av_opt_set(ctx-> priv_data,”crf“,”0“,0);”来控制质量。 当我设置了比特率时,编码的质量会随着时间的推移而恶化,直到帧变得模糊。 第三,使用avio_open和avformat_write_header,而不是使用自己的文件处理。
// av_log_set_level(AV_LOG_DEBUG);
av_register_all();
avcodec_register_all();
AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264); //
AVOutputFormat * outputFormat = av_guess_format("avi", NULL, NULL);
outFmtCtx = NULL;
int test = avformat_alloc_output_context2(&outFmtCtx, outputFormat, NULL, NULL);
if(test<0) exit(-1);
avstream = avformat_new_stream(outFmtCtx, codec);
avstream->time_base= (AVRational){1,25};;
avcodec_get_context_defaults3(avstream->codec, codec);
AVCodecContext *ctx = avstream->codec;
// ctx->bit_rate = 1000000; // messing with this POS is just gonna get you brainpain .. dont do it man..
ctx->width = 320;
ctx->height = 240;
//ctx->time_base= (AVRational){1,25};
ctx->gop_size = 10; /* emit one intra frame every ten frames */
ctx->max_b_frames=10;
ctx->pix_fmt = AV_PIX_FMT_YUV420P;
// FOR H264 ONLY
av_opt_set(ctx->priv_data, "preset", "slow", 0);
// av_opt_set(ctx->priv_data, "crf", "0", 0); // 17 megs for 35 secs ... without : 900k
// FOR H264 ONLY
test = av_opt_set(avstream->codec->priv_data, "preset", "slow", 0);
if(test<0) exit(-2);
test = avcodec_open2(avstream->codec, codec, NULL);
if(test<0) exit(-3);
test = avio_open2(&outFmtCtx->pb, filenamhen, AVIO_FLAG_WRITE, NULL, NULL);
if(test<0) exit(-4);
test = avformat_write_header(outFmtCtx, NULL);
if(test<0) exit(-5);
frame = avcodec_alloc_frame();
if (!frame) exit(-6);
frame->format = avstream->codec->pix_fmt;
frame->width = avstream->codec->width;
frame->height = avstream->codec->height;
ret = av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, avstream->codec->pix_fmt, 32);
if (ret < 0) exit(-7);
编码实时馈送。 我在这里留下了一些未注释的代码来审查快乐。 根据文件,这应该是合法的,赶上延迟帧并继续。 它不是,所以不要:),当我们关闭商店并写预告片时,我们会在最后一点做到这一点
pkt.data = NULL;
pkt.size = 0;
av_init_packet(&pkt);
frame->data[0] = (uint8_t*)Y;
frame->data[1] = (uint8_t*)U;
frame->data[2] = (uint8_t*)V;
frame->pts = i;
ret = avcodec_encode_video2(avstream->codec, &pkt, frame, &got_output);
if (ret < 0) {
fprintf(stderr, "Error encoding framen");
exit (EXIT_FAILURE);
}
if (got_output) {
printf("Write frame %3d (size=%5d)n", i, pkt.size);
//fwrite(pkt.data, 1, pkt.size, file_encoded_video);
// av_write_frame(outFmtCtx, &pkt);
av_interleaved_write_frame(outFmtCtx, &pkt);
av_free_packet(&pkt);
}
/*
for (got_output = 1; got_output; i++) {
fflush(stdout);
ret = avcodec_encode_video2(avstream->codec, &pkt, NULL, &got_output);
if (ret < 0) {
fprintf(stderr, "Error encoding framen");
exit(1);
}
if (got_output) {
printf("Write dealyed frame %3d (size=%5d)n", i, pkt.size);
// av_write_frame(outFmtCtx, &pkt);
av_interleaved_write_frame(outFmtCtx, &pkt);
av_free_packet(&pkt);
}
}
*/
}
并关闭店铺。 - 写延迟帧 - 写预告片 - 关闭流:
pkt.data = NULL;
pkt.size = 0;
av_init_packet(&pkt);
for (got_output = 1; got_output; i++) {
fflush(stdout);
ret = avcodec_encode_video2(avstream->codec, &pkt, NULL, &got_output);
if (ret < 0) {
fprintf(stderr, "Error encoding framen");
exit(1);
}
if (got_output) {
printf("Write dealyed frame %3d (size=%5d)n", i, pkt.size);
// av_write_frame(outFmtCtx, &pkt);
av_interleaved_write_frame(outFmtCtx, &pkt);
av_free_packet(&pkt);
}
}
av_write_trailer(outFmtCtx);
avio_close(outFmtCtx->pb);
希望这可以帮助其他人功夫谷歌搜索:)。
链接地址: http://www.djcxy.com/p/67557.html