h264 codec not found

For the developers that use FFmpeg in Windows software.

h264 codec not found

Postby technique » Wed May 16, 2012 6:16 pm

Hi,

as far as i know for x264 encoding a third codec is needed. For windows i found only the precompiled binary x264.exe. Is that the so called "codec"? I searched for a .dll file but i had no luck.

If i want to encode h264 files with ffmpeg in my own software (slightly modified output-example.c) but i get an error on avcodec_open (could not be found). I put the x264.exe into the same folder as my .exe but that didnt help (as expected..). I didnt get how to "install" the x264 codec on windows so i can use ffmpeg to encode h264 videos.

so it must be easy cause i have the feeling nearly everyone else is using x264 & ffmpeg without a problem... -.-
technique
 
Posts: 14
Joined: Wed May 09, 2012 2:20 pm

Re: h264 codec not found

Postby rogerdpack » Wed May 16, 2012 6:36 pm

"codecs" for ffmpeg-land are always hard-coded and built-in.
So you have to compile ffmpeg with libx264 "included" at compile time.

viewtopic.php?f=5&t=459 might help.
rogerdpack
 
Posts: 1210
Joined: Fri Aug 05, 2011 9:56 pm

Re: h264 codec not found

Postby technique » Thu May 17, 2012 8:25 am

thanks for the reply!

so i really have to build ffmpeg on my own? no Zeranoe builds + x264? okay if that is the way - i'll follow!
technique
 
Posts: 14
Joined: Wed May 09, 2012 2:20 pm

Re: h264 codec not found

Postby rogerdpack » Thu May 17, 2012 3:25 pm

if you download the zeranoe builds they already have x264 "built in" so you should be good to go.
You can see the "included" list with
$ ffmpeg -codecs
rogerdpack
 
Posts: 1210
Joined: Fri Aug 05, 2011 9:56 pm

Re: h264 codec not found

Postby technique » Mon May 21, 2012 8:26 am

okay i downloaded the static build and libx264/libx264rgb is listed as "EV" whatever that means. i use the same "shared" build which should have the x264 included too?

hmm - but i cant load the h264 codec - the avcodec_open function failed! as mentioned in the output message i used av_opt_set(c->priv_data, "preset", "medium", 0); for x264 - but nothing changed.

Image

here is my code (as said - mainly output-example)

Code: Select all
#include <iostream>
#include <string>

#include <stdlib.h>
#include <stdio.h>


extern "C" {
        #include <avcodec.h>
        #include <avformat.h>
        #include <swscale.h>
      #include <avio.h>
      #include <opt.h>
}

#define WIDTH 800
#define HEIGHT 480
#define STREAM_NB_FRAMES  ((int)(STREAM_DURATION * FRAME_RATE))
#define FRAME_RATE 24
#define PIXEL_FORMAT PIX_FMT_YUV420P
#define STREAM_DURATION 5.0 //seconds
#define BIT_RATE 400000

static int sws_flags = SWS_BICUBIC;

AVFrame *picture, *tmp_picture;
uint8_t *video_outbuf;
int frame_count, video_outbuf_size;

static void closeVideo(AVFormatContext *oc, AVStream *st)
{
   avcodec_close(st->codec);
   av_free(picture->data[0]);
   av_free(picture);
   if (tmp_picture)
   {
      av_free(tmp_picture->data[0]);
      av_free(tmp_picture);
   }
   av_free(video_outbuf);
}

static AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height)
{
   AVFrame *picture;
   uint8_t *picture_buf;
   int size;

   picture = avcodec_alloc_frame();
   if(!picture)
      return NULL;
   size = avpicture_get_size(pix_fmt, width, height);
   picture_buf = (uint8_t*)(av_malloc(size));
   if (!picture_buf)
   {
      av_free(picture);
      return NULL;
   }
   avpicture_fill((AVPicture *) picture, picture_buf, pix_fmt, WIDTH, HEIGHT);
   return picture;
}

static void openVideo(AVFormatContext *oc, AVStream *st)
{
   AVCodec *codec;
   AVCodecContext *c;

   c = st->codec;
   if(c->idct_algo == CodecID::CODEC_ID_H264)
      av_opt_set(c->priv_data, "preset", "slow", 0);

   codec = avcodec_find_encoder(c->codec_id);
   if(!codec)
   {
      std::cout << "Codec not found." << std::endl;
      std::cin.get();std::cin.get();exit(1);
   }

   if(codec->id == CODEC_ID_H264)
      av_opt_set(c->priv_data, "preset", "medium", 0);

   if(avcodec_open2(c, codec, NULL) < 0)
   {
      std::cout << "Could not open codec." << std::endl;
      std::cin.get();std::cin.get();exit(1);
   }
   video_outbuf = NULL;
   if(!(oc->oformat->flags & AVFMT_RAWPICTURE))
   {
      video_outbuf_size = 200000;
      video_outbuf = (uint8_t*)(av_malloc(video_outbuf_size));
   }
   picture = alloc_picture(c->pix_fmt, c->width, c->height);
   if(!picture)
   {
      std::cout << "Could not allocate picture" << std::endl;
      std::cin.get();exit(1);
   }
   tmp_picture = NULL;
   if(c->pix_fmt != PIX_FMT_YUV420P)
   {
      tmp_picture = alloc_picture(PIX_FMT_YUV420P, WIDTH, HEIGHT);
      if(!tmp_picture)
      {
         std::cout << " Could not allocate temporary picture" << std::endl;
         std::cin.get();exit(1);
      }
   }
}


static AVStream* addVideoStream(AVFormatContext *context, enum CodecID codecID)
{
   AVCodecContext *codec;
   AVStream *stream;
   stream = av_new_stream(context, 0);
   if(!stream)
   {
      std::cout << "Could not alloc stream." << std::endl;
      std::cin.get();exit(1);
   }

   codec = stream->codec;
   codec->codec_id = codecID;
   codec->codec_type = AVMEDIA_TYPE_VIDEO;

   // sample rate
   codec->bit_rate = BIT_RATE;
   // resolution must be a multiple of two
   codec->width = WIDTH;
   codec->height = HEIGHT;
   codec->time_base.den = FRAME_RATE; // stream fps
   codec->time_base.num = 1;
   codec->gop_size = 12; // intra frame every twelve frames at most
   codec->pix_fmt = PIXEL_FORMAT;
   if(codec->codec_id == CODEC_ID_MPEG2VIDEO)
      codec->max_b_frames = 2; // for testing, B frames

   if(codec->codec_id == CODEC_ID_MPEG1VIDEO)
      codec->mb_decision = 2;

   if(context->oformat->flags & AVFMT_GLOBALHEADER)
      codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

   return stream;
}

static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
{
    int x, y, i;
    i = frame_index;

    /* Y */
    for(y=0;y<height;y++) {
        for(x=0;x<width;x++) {
            pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
        }
    }

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

static void write_video_frame(AVFormatContext *oc, AVStream *st)
{
   int out_size, ret;
   AVCodecContext *c;
   static struct SwsContext *img_convert_ctx;
   c = st->codec;

   if(frame_count >= STREAM_NB_FRAMES)
   {

   }
   else
   {
      if(c->pix_fmt != PIX_FMT_YUV420P)
      {
         if(img_convert_ctx = NULL)
         {
            img_convert_ctx = sws_getContext(WIDTH, HEIGHT, PIX_FMT_YUV420P, WIDTH, HEIGHT,
                                    c->pix_fmt, sws_flags, NULL, NULL, NULL);
            if(img_convert_ctx == NULL)
            {
               std::cout << "Cannot initialize the conversion context" << std::endl;
               std::cin.get();exit(1);
            }
         }
         fill_yuv_image(tmp_picture, frame_count, WIDTH, HEIGHT);
         sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize, 0, HEIGHT,
                  picture->data, picture->linesize);
      }
      else
      {
         fill_yuv_image(picture, frame_count, WIDTH, HEIGHT);
      }
   }

    if (oc->oformat->flags & AVFMT_RAWPICTURE) {
        /* raw video case. The API will change slightly in the near
           futur for that */
        AVPacket pkt;
        av_init_packet(&pkt);

        pkt.flags |= AV_PKT_FLAG_KEY;
        pkt.stream_index= st->index;
        pkt.data= (uint8_t *)picture;
        pkt.size= sizeof(AVPicture);

        ret = av_interleaved_write_frame(oc, &pkt);
    } else {
        /* encode the image */
        out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
        /* if zero size, it means the image was buffered */
        if (out_size > 0) {
            AVPacket pkt;
            av_init_packet(&pkt);

            if (c->coded_frame->pts != AV_NOPTS_VALUE)
                pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
            if(c->coded_frame->key_frame)
                pkt.flags |= AV_PKT_FLAG_KEY;
            pkt.stream_index= st->index;
            pkt.data= video_outbuf;
            pkt.size= out_size;
            /* write the compressed frame in the media file */
            ret = av_interleaved_write_frame(oc, &pkt);
        } else {
            ret = 0;
        }
    }
    if (ret != 0) {
        std::cout << "Error while writing video frames" << std::endl;
        std::cin.get();exit(1);
    }
    frame_count++;
}

int main(int argc, char** argv)
{
   const char* filename = "test.h264";
   AVOutputFormat *outputFormat;
   AVFormatContext *context;
   AVCodecContext *codec;
   AVStream *videoStream;
   double videoPTS;

   // init libavcodec, register all codecs and formats
   av_register_all();
   // auto detect the output format from the name
   outputFormat = av_guess_format(NULL, filename, NULL);
   if(!outputFormat)
   {
      std::cout << "Cannot guess output format! Using mpeg!" << std::endl;
      std::cin.get();
      outputFormat = av_guess_format(NULL, "h263" , NULL);
   }
   if(!outputFormat)
   {
      std::cout << "Could not find suitable output format." << std::endl;
      std::cin.get();exit(1);
   }

   context = avformat_alloc_context();
   if(!context)
   {
      std::cout << "Cannot allocate avformat memory." << std::endl;
      std::cin.get();exit(1);
   }
   context->oformat = outputFormat;
   sprintf_s(context->filename, sizeof(context->filename), "%s", filename);
   std::cout << "Is '" << context->filename << "' = '" << filename << "'" << std::endl;

   videoStream = NULL;
   outputFormat->audio_codec = CODEC_ID_NONE;
   videoStream = addVideoStream(context, outputFormat->video_codec);

   /* still needed?
   if(av_set_parameters(context, NULL) < 0)
   {
      std::cout << "Invalid output format parameters." << std::endl;
      exit(0);
   }*/

   av_dump_format(context, 0, filename, 1);

   if(videoStream)
      openVideo(context, videoStream);

   if(!outputFormat->flags & AVFMT_NOFILE)
   {
      if(avio_open(&context->pb, filename, AVIO_FLAG_READ_WRITE) < 0)
      {
         std::cout << "Could not open " << filename << std::endl;
         std::cin.get();exit(1);
      }
   }

   avformat_write_header(context, 0);

   while(true)
   {
      if(videoStream)
         videoPTS = (double) videoStream->pts.val * videoStream->time_base.num / videoStream->time_base.den;
      else
         videoPTS = 0.;

      if((!videoStream || videoPTS >= STREAM_DURATION))
      {
         break;
      }
      write_video_frame(context, videoStream);
   }
   av_write_trailer(context);
   if(videoStream)
      closeVideo(context, videoStream);
   for(int i = 0; i < context->nb_streams; i++)
   {
      av_freep(&context->streams[i]->codec);
      av_freep(&context->streams[i]);
   }

   if(!(outputFormat->flags & AVFMT_NOFILE))
   {
      avio_close(context->pb);
   }
   av_free(context);
   std::cin.get();
   return 0;
};
technique
 
Posts: 14
Joined: Wed May 09, 2012 2:20 pm

Re: h264 codec not found

Postby technique » Mon May 21, 2012 8:46 am

i tried the encoding function of the decoding_encoding example (slightly modified for vc++ compiler) and this way the codec could not be found! i really have no idea whats going wrong...

Code: Select all
/*
 * Video encoding example
 */
static void video_encode_example(const char *filename, int codec_id)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int i, out_size, x, y, outbuf_size;
    FILE *f;
    AVFrame *picture;
    uint8_t *outbuf;
    int had_output=0;

    printf("Video encoding\n");

    /* find the mpeg1 video encoder */
    codec = avcodec_find_encoder(CodecID(codec_id));
    if (!codec) {  // if statement is taken
        fprintf(stderr, "codec not found\n");  // this is what i get
        std::cin.get();
      exit(1);
    }

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

    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 352;
    c->height = 288;
    /* frames per second */
   c->time_base.den = 30;
   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");
      std::cin.get();
        exit(1);
    }

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

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

    /* 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);
    free(outbuf);

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

int main(int argc, char** argv)
{
   video_encode_example("test.h264", CODEC_ID_H264);
}


technique
 
Posts: 14
Joined: Wed May 09, 2012 2:20 pm

Re: h264 codec not found

Postby rogerdpack » Mon May 21, 2012 5:15 pm

after googling, http://stackoverflow.com/a/3993501/32453 might be related
rogerdpack
 
Posts: 1210
Joined: Fri Aug 05, 2011 9:56 pm

Re: h264 codec not found

Postby technique » Wed May 23, 2012 9:10 am

thank you for your reply.

the problem is - most of the flags which are used in that codec example are deprecated and not longer served by avcodec.h. but i have no idea how to replace those flags with new ones (cause i dont know what they do at all). without the flags i can load the codec (awesome!) but during the encoding the software crashes on av_interleaved_write_frame (after 20-30 frame) and i get the error "[libx264 @ 00608e80] non-strictly-monotonic PTS" on each frame.
so i looked for another preset from the lib but i only found "libx264-ipod320.ffpreset" and "libx264-ipod640.ffpreset" which consist of only 3-4 lines.

what i need is a working codec configuration (working on actual zeranoe build).

may somebody can post a working x264 preset (in c-style)?
technique
 
Posts: 14
Joined: Wed May 09, 2012 2:20 pm

Re: h264 codec not found

Postby technique » Wed May 23, 2012 12:18 pm

I figured out how to get - lets say default - values for x264 encoding which seems to work (encoding itself so far).

Code: Select all
   if(avcodec_get_context_defaults3 (c, codec) < 0)
   {
      std::cout << "Cannot get default codec context! \n" << std::endl;
      std::cin.get();
      exit(1);
   }
   c->bit_rate = BIT_RATE;
   c->width = WIDTH;
   c->height = HEIGHT;
   c->time_base.den = FRAME_RATE;
   c->time_base.num = 1;
   c->gop_size = FRAME_RATE;
   c->pix_fmt = PIX_FMT_YUV420P;

   if(oc->oformat->flags & AVFMT_GLOBALHEADER)
      c->flags |= CODEC_FLAG_GLOBAL_HEADER;


Next step was to get rid of the "non-strictly-monotonic PTS"-Error. I figured out that i have to compute the right PTS for each AVFrame i want to encode. That way works for me so far:

Code: Select all
picture->pts = (float) frame_count * (1000.0/(float)(FRAME_RATE)) * 90;


frame_count is the frame index (eg. 0, 1, 2, 3, ..)

Encoding works without any errors but the av_interleaved_write_frame function crashes on first call!

Code: Select all
      picture->pts = (float) frame_count * (1000.0/(float)(FRAME_RATE)) * 90;

      int result, result2;
      AVPacket pkt;
      av_init_packet(&pkt);
      pkt.dts = AV_NOPTS_VALUE;
      pkt.stream_index = st->index;
      pkt.data = video_outbuf;
      pkt.size = video_outbuf_size;
      result2 = avcodec_encode_video2(c, &pkt, picture, &result);
        /* if zero size, it means the image was buffered */
        if (result == 1 && result2 == 0) {
            ret = av_interleaved_write_frame(oc, &pkt);
}


after exactly 32 frames - av_interleaved_write_frame is getting called.

Any ideas?
technique
 
Posts: 14
Joined: Wed May 09, 2012 2:20 pm

Re: h264 codec not found

Postby rogerdpack » Wed May 23, 2012 1:30 pm

I've never used that method, but maybe "run it in linux under valgrind" or "ask the ffmpeg users group"
what's the exact crash?
maybe it's trying to write an i-frame or some such/
rogerdpack
 
Posts: 1210
Joined: Fri Aug 05, 2011 9:56 pm

Next

Return to Using FFmpeg In Windows Software

Who is online

Users browsing this forum: No registered users and 3 guests