Merge commit '5f102a9559099429826e84758b8b5182244c52db'
authorClément Bœsch <cboesch@gopro.com>
Tue, 4 Apr 2017 09:44:45 +0000 (11:44 +0200)
committerClément Bœsch <cboesch@gopro.com>
Tue, 4 Apr 2017 09:44:45 +0000 (11:44 +0200)
* commit '5f102a9559099429826e84758b8b5182244c52db':
  examples/encode_video: switch to the new encoding API

Merged-by: Clément Bœsch <cboesch@gopro.com>
1  2 
doc/examples/encode_video.c

@@@ -1,23 -1,21 +1,23 @@@
  /*
 - * copyright (c) 2001 Fabrice Bellard
 + * Copyright (c) 2001 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * Permission is hereby granted, free of charge, to any person obtaining a copy
 + * of this software and associated documentation files (the "Software"), to deal
 + * in the Software without restriction, including without limitation the rights
 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 + * copies of the Software, and to permit persons to whom the Software is
 + * furnished to do so, subject to the following conditions:
   *
 - * Libav is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU Lesser General Public
 - * License as published by the Free Software Foundation; either
 - * version 2.1 of the License, or (at your option) any later version.
 + * The above copyright notice and this permission notice shall be included in
 + * all copies or substantial portions of the Software.
   *
 - * Libav is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - * Lesser General Public License for more details.
 - *
 - * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 + * THE SOFTWARE.
   */
  
  /**
  #include <stdlib.h>
  #include <string.h>
  
 -#include "libavcodec/avcodec.h"
 +#include <libavcodec/avcodec.h>
  
 -#include "libavutil/frame.h"
 -#include "libavutil/imgutils.h"
 +#include <libavutil/opt.h>
 +#include <libavutil/imgutils.h>
  
 -        fprintf(stderr, "error sending a frame for encoding\n");
+ static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
+                    FILE *outfile)
+ {
+     int ret;
+     /* send the frame to the encoder */
+     ret = avcodec_send_frame(enc_ctx, frame);
+     if (ret < 0) {
 -            fprintf(stderr, "error during encoding\n");
++        fprintf(stderr, "Error sending a frame for encoding\n");
+         exit(1);
+     }
+     while (ret >= 0) {
+         ret = avcodec_receive_packet(enc_ctx, pkt);
+         if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+             return;
+         else if (ret < 0) {
 -        printf("encoded frame %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
++            fprintf(stderr, "Error during encoding\n");
+             exit(1);
+         }
++        printf("Write frame %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
+         fwrite(pkt->data, 1, pkt->size, outfile);
+         av_packet_unref(pkt);
+     }
+ }
  int main(int argc, char **argv)
  {
 -    const char *filename;
 +    const char *filename, *codec_name;
      const AVCodec *codec;
      AVCodecContext *c= NULL;
-     int i, ret, x, y, got_output;
+     int i, ret, x, y;
      FILE *f;
 -    AVFrame *picture;
 +    AVFrame *frame;
      AVPacket pkt;
      uint8_t endcode[] = { 0, 0, 1, 0xb7 };
  
 -    if (argc <= 1) {
 -        fprintf(stderr, "Usage: %s <output file>\n", argv[0]);
 +    if (argc <= 2) {
 +        fprintf(stderr, "Usage: %s <output file> <codec name>\n", argv[0]);
          exit(0);
      }
      filename = argv[1];
 +    codec_name = argv[2];
  
      avcodec_register_all();
  
      /* find the mpeg1video encoder */
 -    codec = avcodec_find_encoder(AV_CODEC_ID_MPEG1VIDEO);
 +    codec = avcodec_find_encoder_by_name(codec_name);
      if (!codec) {
 -        fprintf(stderr, "codec not found\n");
 +        fprintf(stderr, "Codec not found\n");
          exit(1);
      }
  
      c = avcodec_alloc_context3(codec);
 -    picture = av_frame_alloc();
 +    if (!c) {
 +        fprintf(stderr, "Could not allocate video codec context\n");
 +        exit(1);
 +    }
  
      /* put sample parameters */
      c->bit_rate = 400000;
      c->time_base = (AVRational){1, 25};
      c->framerate = (AVRational){25, 1};
  
 -    c->gop_size = 10; /* emit one intra frame every ten frames */
 -    c->max_b_frames=1;
 +    /* emit one intra frame every ten frames
 +     * check frame pict_type before passing frame
 +     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
 +     * then gop_size is ignored and the output of encoder
 +     * will always be I frame irrespective to gop_size
 +     */
 +    c->gop_size = 10;
 +    c->max_b_frames = 1;
      c->pix_fmt = AV_PIX_FMT_YUV420P;
  
 +    if (codec->id == AV_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");
 +        fprintf(stderr, "Could not open codec\n");
          exit(1);
      }
  
      f = fopen(filename, "wb");
      if (!f) {
 -        fprintf(stderr, "could not open %s\n", filename);
 +        fprintf(stderr, "Could not open %s\n", filename);
          exit(1);
      }
  
 -    picture->format = c->pix_fmt;
 -    picture->width  = c->width;
 -    picture->height = c->height;
 +    frame = av_frame_alloc();
 +    if (!frame) {
 +        fprintf(stderr, "Could not allocate video frame\n");
 +        exit(1);
 +    }
 +    frame->format = c->pix_fmt;
 +    frame->width  = c->width;
 +    frame->height = c->height;
  
 -    ret = av_frame_get_buffer(picture, 32);
 +    ret = av_frame_get_buffer(frame, 32);
      if (ret < 0) {
 -        fprintf(stderr, "could not alloc the frame data\n");
 +        fprintf(stderr, "Could not allocate the video frame data\n");
          exit(1);
      }
  
      /* encode 1 second of video */
 -    for(i=0;i<25;i++) {
 +    for (i = 0; i < 25; i++) {
          av_init_packet(&pkt);
          pkt.data = NULL;    // packet data will be allocated by the encoder
          pkt.size = 0;
          fflush(stdout);
  
          /* make sure the frame data is writable */
 -        ret = av_frame_make_writable(picture);
 +        ret = av_frame_make_writable(frame);
          if (ret < 0)
              exit(1);
  
          /* 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;
 +        for (y = 0; y < c->height; y++) {
 +            for (x = 0; x < c->width; x++) {
 +                frame->data[0][y * frame->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;
 +        for (y = 0; y < c->height/2; y++) {
 +            for (x = 0; x < c->width/2; x++) {
 +                frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
 +                frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
              }
          }
  
 -        picture->pts = i;
 +        frame->pts = i;
  
          /* encode the image */
-         ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
-         if (ret < 0) {
-             fprintf(stderr, "Error encoding frame\n");
-             exit(1);
-         }
-         if (got_output) {
-             printf("Write frame %3d (size=%5d)\n", i, pkt.size);
-             fwrite(pkt.data, 1, pkt.size, f);
-             av_packet_unref(&pkt);
-         }
 -        encode(c, picture, &pkt, f);
++        encode(c, frame, &pkt, f);
      }
  
-     /* get the delayed frames */
-     for (got_output = 1; got_output; i++) {
-         fflush(stdout);
-         ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);
-         if (ret < 0) {
-             fprintf(stderr, "Error encoding frame\n");
-             exit(1);
-         }
-         if (got_output) {
-             printf("Write frame %3d (size=%5d)\n", i, pkt.size);
-             fwrite(pkt.data, 1, pkt.size, f);
-             av_packet_unref(&pkt);
-         }
-     }
+     /* flush the encoder */
+     encode(c, NULL, &pkt, f);
  
      /* add sequence end code to have a real MPEG file */
      fwrite(endcode, 1, sizeof(endcode), f);
      fclose(f);
  
      avcodec_free_context(&c);
 -    av_frame_free(&picture);
 +    av_frame_free(&frame);
  
      return 0;
  }