1/* 2 * Copyright (c) 2001 Fabrice Bellard 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 */ 22 23/** 24 * @file 25 * video encoding with libavcodec API example 26 * 27 * @example encode_video.c 28 */ 29 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33 34#include <libavcodec/avcodec.h> 35 36#include <libavutil/opt.h> 37#include <libavutil/imgutils.h> 38 39static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt, 40 FILE *outfile) 41{ 42 int ret; 43 44 /* send the frame to the encoder */ 45 if (frame) 46 printf("Send frame %3"PRId64"\n", frame->pts); 47 48 ret = avcodec_send_frame(enc_ctx, frame); 49 if (ret < 0) { 50 fprintf(stderr, "Error sending a frame for encoding\n"); 51 exit(1); 52 } 53 54 while (ret >= 0) { 55 ret = avcodec_receive_packet(enc_ctx, pkt); 56 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) 57 return; 58 else if (ret < 0) { 59 fprintf(stderr, "Error during encoding\n"); 60 exit(1); 61 } 62 63 printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size); 64 fwrite(pkt->data, 1, pkt->size, outfile); 65 av_packet_unref(pkt); 66 } 67} 68 69int main(int argc, char **argv) 70{ 71 const char *filename, *codec_name; 72 const AVCodec *codec; 73 AVCodecContext *c= NULL; 74 int i, ret, x, y; 75 FILE *f; 76 AVFrame *frame; 77 AVPacket *pkt; 78 uint8_t endcode[] = { 0, 0, 1, 0xb7 }; 79 80 if (argc <= 2) { 81 fprintf(stderr, "Usage: %s <output file> <codec name>\n", argv[0]); 82 exit(0); 83 } 84 filename = argv[1]; 85 codec_name = argv[2]; 86 87 /* find the mpeg1video encoder */ 88 codec = avcodec_find_encoder_by_name(codec_name); 89 if (!codec) { 90 fprintf(stderr, "Codec '%s' not found\n", codec_name); 91 exit(1); 92 } 93 94 c = avcodec_alloc_context3(codec); 95 if (!c) { 96 fprintf(stderr, "Could not allocate video codec context\n"); 97 exit(1); 98 } 99 100 pkt = av_packet_alloc(); 101 if (!pkt) 102 exit(1); 103 104 /* put sample parameters */ 105 c->bit_rate = 400000; 106 /* resolution must be a multiple of two */ 107 c->width = 352; 108 c->height = 288; 109 /* frames per second */ 110 c->time_base = (AVRational){1, 25}; 111 c->framerate = (AVRational){25, 1}; 112 113 /* emit one intra frame every ten frames 114 * check frame pict_type before passing frame 115 * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I 116 * then gop_size is ignored and the output of encoder 117 * will always be I frame irrespective to gop_size 118 */ 119 c->gop_size = 10; 120 c->max_b_frames = 1; 121 c->pix_fmt = AV_PIX_FMT_YUV420P; 122 123 if (codec->id == AV_CODEC_ID_H264) 124 av_opt_set(c->priv_data, "preset", "slow", 0); 125 126 /* open it */ 127 ret = avcodec_open2(c, codec, NULL); 128 if (ret < 0) { 129 fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret)); 130 exit(1); 131 } 132 133 f = fopen(filename, "wb"); 134 if (!f) { 135 fprintf(stderr, "Could not open %s\n", filename); 136 exit(1); 137 } 138 139 frame = av_frame_alloc(); 140 if (!frame) { 141 fprintf(stderr, "Could not allocate video frame\n"); 142 exit(1); 143 } 144 frame->format = c->pix_fmt; 145 frame->width = c->width; 146 frame->height = c->height; 147 148 ret = av_frame_get_buffer(frame, 0); 149 if (ret < 0) { 150 fprintf(stderr, "Could not allocate the video frame data\n"); 151 exit(1); 152 } 153 154 /* encode 1 second of video */ 155 for (i = 0; i < 25; i++) { 156 fflush(stdout); 157 158 /* Make sure the frame data is writable. 159 On the first round, the frame is fresh from av_frame_get_buffer() 160 and therefore we know it is writable. 161 But on the next rounds, encode() will have called 162 avcodec_send_frame(), and the codec may have kept a reference to 163 the frame in its internal structures, that makes the frame 164 unwritable. 165 av_frame_make_writable() checks that and allocates a new buffer 166 for the frame only if necessary. 167 */ 168 ret = av_frame_make_writable(frame); 169 if (ret < 0) 170 exit(1); 171 172 /* Prepare a dummy image. 173 In real code, this is where you would have your own logic for 174 filling the frame. FFmpeg does not care what you put in the 175 frame. 176 */ 177 /* Y */ 178 for (y = 0; y < c->height; y++) { 179 for (x = 0; x < c->width; x++) { 180 frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3; 181 } 182 } 183 184 /* Cb and Cr */ 185 for (y = 0; y < c->height/2; y++) { 186 for (x = 0; x < c->width/2; x++) { 187 frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2; 188 frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5; 189 } 190 } 191 192 frame->pts = i; 193 194 /* encode the image */ 195 encode(c, frame, pkt, f); 196 } 197 198 /* flush the encoder */ 199 encode(c, NULL, pkt, f); 200 201 /* Add sequence end code to have a real MPEG file. 202 It makes only sense because this tiny examples writes packets 203 directly. This is called "elementary stream" and only works for some 204 codecs. To create a valid file, you usually need to write packets 205 into a proper file format or protocol; see muxing.c. 206 */ 207 if (codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO) 208 fwrite(endcode, 1, sizeof(endcode), f); 209 fclose(f); 210 211 avcodec_free_context(&c); 212 av_frame_free(&frame); 213 av_packet_free(&pkt); 214 215 return 0; 216} 217