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
encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt, FILE *outfile)39 static 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
main(int argc, char **argv)69 int 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