c++ - FFMpeg 编码的视频只会在 FFPlay 中播放

标签 c++ ffmpeg video-encoding

我已经调试我的程序几个星期了,输出视频只显示一个空白屏幕(使用 VLC、WMP 和 WMPClassic 进行测试)。我碰巧尝试使用 FFPlay 并且看到视频完美运行。我读到这通常是由不正确的像素格式引起的,切换到 PIX_FMT_YUV420P 将使它普遍工作......但我已经在编码过程中使用了该像素格式。是否还有其他原因导致此问题?

AVCodec* codec;
AVCodecContext* c = NULL;
uint8_t* outbuf;
int i, out_size, outbuf_size;

avcodec_register_all();

printf("Video encoding\n");

// Find the mpeg1 video encoder
codec = avcodec_find_encoder(CODEC_ID_H264);
if (!codec) {
    fprintf(stderr, "Codec not found\n");
    exit(1);
}
else printf("H264 codec found\n");

c = avcodec_alloc_context3(codec);

c->bit_rate = 400000;
c->width = 1920;                                        // resolution must be a multiple of two (1280x720),(1900x1080),(720x480)
c->height = 1200;
c->time_base.num = 1;                                   // framerate numerator
c->time_base.den = 25;                                  // framerate denominator
c->gop_size = 10;                                       // emit one intra frame every ten frames
c->max_b_frames = 1;                                    // maximum number of b-frames between non b-frames
//c->keyint_min = 1;                                        // minimum GOP size
//c->i_quant_factor = (float)0.71;                      // qscale factor between P and I frames
//c->b_frame_strategy = 20;
//c->qcompress = (float)0.6;
//c->qmin = 20;                                         // minimum quantizer
//c->qmax = 51;                                         // maximum quantizer
//c->max_qdiff = 4;                                     // maximum quantizer difference between frames
//c->refs = 4;                                          // number of reference frames
//c->trellis = 1;                                           // trellis RD Quantization
c->pix_fmt = PIX_FMT_YUV420P;
c->codec_id = CODEC_ID_H264;
//c->codec_type = AVMEDIA_TYPE_VIDEO;

// Open the encoder
if (avcodec_open2(c, codec,NULL) < 0) {
    fprintf(stderr, "Could not open codec\n");
    exit(1);
}
else printf("H264 codec opened\n");

outbuf_size = 100000 + c->width*c->height*(32>>3);//*(32>>3);           // alloc image and output buffer
outbuf = static_cast<uint8_t *>(malloc(outbuf_size));
printf("Setting buffer size to: %d\n",outbuf_size);

FILE* f = fopen("example.mpg","wb");
if(!f) printf("x  -  Cannot open video file for writing\n");
else printf("Opened video file for writing\n");

// encode 5 seconds of video
for(i=0;i<STREAM_FRAME_RATE*STREAM_DURATION;i++) {
    fflush(stdout);

    screenCap();

    int nbytes = avpicture_get_size(PIX_FMT_YUV420P, c->width, c->height);
    uint8_t* outbuffer = (uint8_t*)av_malloc(nbytes*sizeof(uint8_t));

    AVFrame* inpic = avcodec_alloc_frame();
    AVFrame* outpic = avcodec_alloc_frame();

    outpic->pts = (int64_t)((float)i * (1000.0/((float)(c->time_base.den))) * 90);
    avpicture_fill((AVPicture*)inpic, (uint8_t*)pPixels, PIX_FMT_RGB32, c->width, c->height);                   // Fill picture with image
    avpicture_fill((AVPicture*)outpic, outbuffer, PIX_FMT_YUV420P, c->width, c->height);
    av_image_alloc(outpic->data, outpic->linesize, c->width, c->height, c->pix_fmt, 1); 

    inpic->data[0] += inpic->linesize[0]*(screenHeight-1);                                                      // Flipping frame
    inpic->linesize[0] = -inpic->linesize[0];                                                                   // Flipping frame

    struct SwsContext* fooContext = sws_getContext(screenWidth, screenHeight, PIX_FMT_RGB32, c->width, c->height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);
    sws_scale(fooContext, inpic->data, inpic->linesize, 0, c->height, outpic->data, outpic->linesize);

    // encode the image
    out_size = avcodec_encode_video(c, outbuf, outbuf_size, outpic);
    printf("Encoding frame %3d (size=%5d)\n", i, out_size);
    fwrite(outbuf, 1, out_size, f);
    delete [] pPixels;
    av_free(outbuffer);     
    av_free(inpic);
    av_free(outpic);
}

// get the delayed frames
for(; out_size; i++) {
    fflush(stdout);

    out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
    printf("Writing frame %3d (size=%5d)\n", i, out_size);
    fwrite(outbuf, 1, out_size, f);
}

// add sequence end code to have a real mpeg file
outbuf[0] = 0x00;
outbuf[1] = 0x00;
outbuf[2] = 0x01;
outbuf[3] = 0xb7;
fwrite(outbuf, 1, 4, f);
fclose(f);

avcodec_close(c);
free(outbuf);
av_free(c);
printf("Closed codec and Freed\n");

最佳答案

尝试将文件保存为 example.h264,而不是 example.mpg

关于c++ - FFMpeg 编码的视频只会在 FFPlay 中播放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16041621/

相关文章:

c++ - 一个关于字符串的最大子序列的程序

c++ - 为什么这是 gcc 中的 "overloading ambiguity"?

c++ - 未指定字符串化运算符的评估顺序

c++ - 将数组大小减少到 1 的最小成本

FFmpeg drawtext的字体文件无法加载

FFmpeg:如何有效地分割视频?

android - 使用 librtmp 为 android 构建 FFMPEG

c++ - 由于 linux 中的 HRESULT 、 LARGE_INTEGER 和 DWORD 而出错

video - FFmpeg 的 AAC ("libfaac") 编解码器选项?

internet-explorer - Internet Explorer 不支持高度大于 1088 像素的 HTML5 视频