Question

So I'm kind of new to this, I'm writing a WIN32 app that records video to .AVI, then I planned to use ffmpeg to encode to .MP4. Based on a sample I found, I got this far. It compiles and says that it encoded and wrote the file but the output file can't be opened and played. I tried using MPEG1 encoding like the original sample was using but it only gives me weird colors for a few seconds.

Am I missing something that should be done with the file?

Anyone with experience in encoding/ffmpeg, some pointers, advice or help would make me outmost grateful. Thanks in advance!

int _tmain(int argc, _TCHAR* argv[])
{

    AVFormatContext *pFormatCtx;
    int codec_id = CODEC_ID_MPEG4;
    char filename [] ="C:\\wav\\test2.flv";
// Open video file
     AVCodec *codec;
     AVCodecContext *c= NULL;
     int i, out_size, x, y, outbuf_size;
    FILE *f;
     AVFrame *picture;
    uint8_t *outbuf;
     int had_output=0;

    av_register_all();
   printf("Encode video file %s\n", filename);

    codec = avcodec_find_encoder(CODEC_ID_H264);
    if (!codec) {
         fprintf(stderr, "codec not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(codec);
    picture= avcodec_alloc_frame();

   /* put sample parameters */
   c->bit_rate = 40000;
   //c->bit_rate_tolerance=30;
     /* resolution must be a multiple of two */
    c->width = 352;
    c->height = 288;
    /* frames per second */

    c->time_base.den=  25;
    c->time_base.num= 1;
     c->gop_size = 10; /* emit one intra frame every ten frames */
   c->max_b_frames=1;
     c->pix_fmt = PIX_FMT_YUV420P;

    if(codec_id == CODEC_ID_H264)
        av_opt_set(c->priv_data, "preset", "slow", 0);
/* open it */
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
       exit(1);
    }


     f = fopen(filename, "wb");
     if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
         exit(1);
     }

    /* alloc image and output buffer */
    outbuf_size = 100000 + 12*c->width*c->height;
     outbuf = (uint8_t*)malloc(outbuf_size); //CHANGED

     /* the image can be allocated by any means and av_image_alloc() is
      * just the most convenient way if av_malloc() is to be used */
    av_image_alloc(picture->data, picture->linesize,
                   c->width, c->height, c->pix_fmt, 1);

     /* encode 1 second of video */
     for(i=0;i<25;i++) {
         fflush(stdout);
         /* prepare a dummy image */
        /* Y */
         for(y=0;y<c->height;y++) {
            for(x=0;x<c->width;x++) {
                picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;
            }
         }

        /* Cb and Cr */
        for(y=0;y<c->height/2;y++) {
            for(x=0;x<c->width/2;x++) {
                picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;
                picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;
            }
        }

         /* encode the image */
        out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
         had_output |= out_size;
        printf("encoding frame %3d (size=%5d)\n", i, out_size);
        fwrite(outbuf, 1, out_size, f);
     }

     /* get the delayed frames */
     for(; out_size || !had_output; i++) {
         fflush(stdout);

        out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
        had_output |= out_size;
         printf("write 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);
        fclose(p);
    free(outbuf);

     avcodec_close(c);
     av_free(c);
     av_free(picture->data[0]);
    av_free(picture);
     printf("\n");

    return 0;
}
Was it helpful?

Solution

You are not writing .MP4, .flv nor AVI file. You are writing raw H.264 video stream without any container. Most players won't be able to play it, but it works fine with ffplay and mplayer.

It seems to be working as intended. It encodes 25 frames of weird color gradients. Though, due to low bitrate, it might look like some garbage.

All you need to do, is to put this stream into some container using libavformat. And, provide some real video frames to encode.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top