ffmpeg 使用示例
ffmpeg提供了多种示例来展示如何进行编解码. 示例代码在doc\examples.
这里逐一分析下这些示例的执行流程,不同版本的ffmpeg在流程上存在
一定的差异,本文针对ffmpeg5.0版本的代码.
decode audio
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 * audio decoding with libavcodec API example 26 * 27 * @example decode_audio.c 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 34 #include <libavutil/frame.h> 35 #include <libavutil/mem.h> 36 37 #include <libavcodec/avcodec.h> 38 39 #define AUDIO_INBUF_SIZE 20480 40 #define AUDIO_REFILL_THRESH 4096 41 42 static int get_format_from_sample_fmt(const char **fmt, 43 enum AVSampleFormat sample_fmt) 44 { 45 int i; 46 struct sample_fmt_entry { 47 enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le; 48 } sample_fmt_entries[] = { 49 { AV_SAMPLE_FMT_U8, "u8", "u8" }, 50 { AV_SAMPLE_FMT_S16, "s16be", "s16le" }, 51 { AV_SAMPLE_FMT_S32, "s32be", "s32le" }, 52 { AV_SAMPLE_FMT_FLT, "f32be", "f32le" }, 53 { AV_SAMPLE_FMT_DBL, "f64be", "f64le" }, 54 }; 55 *fmt = NULL; 56 57 for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) { 58 struct sample_fmt_entry *entry = &sample_fmt_entries[i]; 59 if (sample_fmt == entry->sample_fmt) { 60 *fmt = AV_NE(entry->fmt_be, entry->fmt_le); 61 return 0; 62 } 63 } 64 65 fprintf(stderr, 66 "sample format %s is not supported as output format\n", 67 av_get_sample_fmt_name(sample_fmt)); 68 return -1; 69 } 70 71 static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, 72 FILE *outfile) 73 { 74 int i, ch; 75 int ret, data_size; 76 77 /* send the packet with the compressed data to the decoder */ 78 ret = avcodec_send_packet(dec_ctx, pkt); 79 if (ret < 0) { 80 fprintf(stderr, "Error submitting the packet to the decoder\n"); 81 exit(1); 82 } 83 84 /* read all the output frames (in general there may be any number of them */ 85 while (ret >= 0) { 86 ret = avcodec_receive_frame(dec_ctx, frame); 87 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) 88 return; 89 else if (ret < 0) { 90 fprintf(stderr, "Error during decoding\n"); 91 exit(1); 92 } 93 data_size = av_get_bytes_per_sample(dec_ctx->sample_fmt); 94 if (data_size < 0) { 95 /* This should not occur, checking just for paranoia */ 96 fprintf(stderr, "Failed to calculate data size\n"); 97 exit(1); 98 } 99 for (i = 0; i < frame->nb_samples; i++) 100 for (ch = 0; ch < dec_ctx->ch_layout.nb_channels; ch++) 101 fwrite(frame->data[ch] + data_size*i, 1, data_size, outfile); 102 } 103 } 104 105 int main(int argc, char **argv) 106 { 107 const char *outfilename, *filename; 108 const AVCodec *codec; 109 AVCodecContext *c= NULL; 110 AVCodecParserContext *parser = NULL; 111 int len, ret; 112 FILE *f, *outfile; 113 uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; 114 uint8_t *data; 115 size_t data_size; 116 AVPacket *pkt; 117 AVFrame *decoded_frame = NULL; 118 enum AVSampleFormat sfmt; 119 int n_channels = 0; 120 const char *fmt; 121 122 if (argc <= 2) { 123 fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]); 124 exit(0); 125 } 126 filename = argv[1]; 127 outfilename = argv[2]; 128 129 pkt = av_packet_alloc(); 130 131 /* find the MPEG audio decoder */ 132 codec = avcodec_find_decoder(AV_CODEC_ID_MP2); 133 if (!codec) { 134 fprintf(stderr, "Codec not found\n"); 135 exit(1); 136 } 137 138 parser = av_parser_init(codec->id); 139 if (!parser) { 140 fprintf(stderr, "Parser not found\n"); 141 exit(1); 142 } 143 144 c = avcodec_alloc_context3(codec); 145 if (!c) { 146 fprintf(stderr, "Could not allocate audio codec context\n"); 147 exit(1); 148 } 149 150 /* open it */ 151 if (avcodec_open2(c, codec, NULL) < 0) { 152 fprintf(stderr, "Could not open codec\n"); 153 exit(1); 154 } 155 156 f = fopen(filename, "rb"); 157 if (!f) { 158 fprintf(stderr, "Could not open %s\n", filename); 159 exit(1); 160 } 161 outfile = fopen(outfilename, "wb"); 162 if (!outfile) { 163 av_free(c); 164 exit(1); 165 } 166 167 /* decode until eof */ 168 data = inbuf; 169 data_size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); 170 171 while (data_size > 0) { 172 if (!decoded_frame) { 173 if (!(decoded_frame = av_frame_alloc())) { 174 fprintf(stderr, "Could not allocate audio frame\n"); 175 exit(1); 176 } 177 } 178 179 ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size, 180 data, data_size, 181 AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); 182 if (ret < 0) { 183 fprintf(stderr, "Error while parsing\n"); 184 exit(1); 185 } 186 data += ret; 187 data_size -= ret; 188 189 if (pkt->size) 190 decode(c, pkt, decoded_frame, outfile); 191 192 if (data_size < AUDIO_REFILL_THRESH) { 193 memmove(inbuf, data, data_size); 194 data = inbuf; 195 len = fread(data + data_size, 1, 196 AUDIO_INBUF_SIZE - data_size, f); 197 if (len > 0) 198 data_size += len; 199 } 200 } 201 202 /* flush the decoder */ 203 pkt->data = NULL; 204 pkt->size = 0; 205 decode(c, pkt, decoded_frame, outfile); 206 207 /* print output pcm infomations, because there have no metadata of pcm */ 208 sfmt = c->sample_fmt; 209 210 if (av_sample_fmt_is_planar(sfmt)) { 211 const char *packed = av_get_sample_fmt_name(sfmt); 212 printf("Warning: the sample format the decoder produced is planar " 213 "(%s). This example will output the first channel only.\n", 214 packed ? packed : "?"); 215 sfmt = av_get_packed_sample_fmt(sfmt); 216 } 217 218 n_channels = c->ch_layout.nb_channels; 219 if ((ret = get_format_from_sample_fmt(&fmt, sfmt)) < 0) 220 goto end; 221 222 printf("Play the output audio file with the command:\n" 223 "ffplay -f %s -ac %d -ar %d %s\n", 224 fmt, n_channels, c->sample_rate, 225 outfilename); 226 end: 227 fclose(outfile); 228 fclose(f); 229 230 avcodec_free_context(&c); 231 av_parser_close(parser); 232 av_frame_free(&decoded_frame); 233 av_packet_free(&pkt); 234 235 return 0; 236 }
decode video
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 decoding with libavcodec API example 26 * 27 * @example decode_video.c 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 34 #include <libavcodec/avcodec.h> 35 36 #define INBUF_SIZE 4096 37 38 static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, 39 char *filename) 40 { 41 FILE *f; 42 int i; 43 44 f = fopen(filename,"wb"); 45 fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); 46 for (i = 0; i < ysize; i++) 47 fwrite(buf + i * wrap, 1, xsize, f); 48 fclose(f); 49 } 50 51 static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, 52 const char *filename) 53 { 54 char buf[1024]; 55 int ret; 56 57 ret = avcodec_send_packet(dec_ctx, pkt); 58 if (ret < 0) { 59 fprintf(stderr, "Error sending a packet for decoding\n"); 60 exit(1); 61 } 62 63 while (ret >= 0) { 64 ret = avcodec_receive_frame(dec_ctx, frame); 65 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) 66 return; 67 else if (ret < 0) { 68 fprintf(stderr, "Error during decoding\n"); 69 exit(1); 70 } 71 72 printf("saving frame %3d\n", dec_ctx->frame_number); 73 fflush(stdout); 74 75 /* the picture is allocated by the decoder. no need to 76 free it */ 77 snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number); 78 pgm_save(frame->data[0], frame->linesize[0], 79 frame->width, frame->height, buf); 80 } 81 } 82 83 int main(int argc, char **argv) 84 { 85 const char *filename, *outfilename; 86 const AVCodec *codec; 87 AVCodecParserContext *parser; 88 AVCodecContext *c= NULL; 89 FILE *f; 90 AVFrame *frame; 91 uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; 92 uint8_t *data; 93 size_t data_size; 94 int ret; 95 int eof; 96 AVPacket *pkt; 97 98 if (argc <= 2) { 99 fprintf(stderr, "Usage: %s <input file> <output file>\n" 100 "And check your input file is encoded by mpeg1video please.\n", argv[0]); 101 exit(0); 102 } 103 filename = argv[1]; 104 outfilename = argv[2]; 105 106 pkt = av_packet_alloc(); 107 if (!pkt) 108 exit(1); 109 110 /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */ 111 memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); 112 113 /* find the MPEG-1 video decoder */ 114 codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); 115 if (!codec) { 116 fprintf(stderr, "Codec not found\n"); 117 exit(1); 118 } 119 120 parser = av_parser_init(codec->id); 121 if (!parser) { 122 fprintf(stderr, "parser not found\n"); 123 exit(1); 124 } 125 126 c = avcodec_alloc_context3(codec); 127 if (!c) { 128 fprintf(stderr, "Could not allocate video codec context\n"); 129 exit(1); 130 } 131 132 /* For some codecs, such as msmpeg4 and mpeg4, width and height 133 MUST be initialized there because this information is not 134 available in the bitstream. */ 135 136 /* open it */ 137 if (avcodec_open2(c, codec, NULL) < 0) { 138 fprintf(stderr, "Could not open codec\n"); 139 exit(1); 140 } 141 142 f = fopen(filename, "rb"); 143 if (!f) { 144 fprintf(stderr, "Could not open %s\n", filename); 145 exit(1); 146 } 147 148 frame = av_frame_alloc(); 149 if (!frame) { 150 fprintf(stderr, "Could not allocate video frame\n"); 151 exit(1); 152 } 153 154 do { 155 /* read raw data from the input file */ 156 data_size = fread(inbuf, 1, INBUF_SIZE, f); 157 if (ferror(f)) 158 break; 159 eof = !data_size; 160 161 /* use the parser to split the data into frames */ 162 data = inbuf; 163 while (data_size > 0 || eof) { 164 ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size, 165 data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); 166 if (ret < 0) { 167 fprintf(stderr, "Error while parsing\n"); 168 exit(1); 169 } 170 data += ret; 171 data_size -= ret; 172 173 if (pkt->size) 174 decode(c, frame, pkt, outfilename); 175 else if (eof) 176 break; 177 } 178 } while (!eof); 179 180 /* flush the decoder */ 181 decode(c, frame, NULL, outfilename); 182 183 fclose(f); 184 185 av_parser_close(parser); 186 avcodec_free_context(&c); 187 av_frame_free(&frame); 188 av_packet_free(&pkt); 189 190 return 0; 191 }
有几个注意点:
1. av_packet_alloc(): 为AVPacket分配内存,不涉及存储压缩编码数据的buffer. 可以使用av_new_packet()接口指定分配存储压缩数据的buffer,也可以使用av_packet_from_data()来直接指定存储压缩编码数据的buffer地址空间,这里其实非常灵活的。
2. 一般意义上一个Packet并不代表会输出一帧数据,也有可能没有输出帧,也有可能有多帧数据输出。需要特殊处理。
- 一个Packet代表多帧的情况很少见而已,Demo代码中对于这里处理不是很好. 可以根据avcodec_send_packet()返回值来处理:
- send 0 :send_packet返回值为0,正常状态,意味着输入的packet被解码器正常接收。
- send EAGAIN :send_packet返回值为EAGAIN,输入的packet未被接收,需要输出一个或多个的frame后才能重新输入当前packet。 s
- send EOF :send_packet返回值为EOF,当send_packet输入为NULL时才会触发该状态,用于通知解码器输入packet已结束。
- send EINVAL :没有打开×××,或者这是一个编码器,或者要求刷新
- send ENOMEM: 内部错误,添加AVPacket失败
- other negative value:其他的解码错误
3. av_parser_parse2()可以从输入Buffer中解析出一个AVPacket,如果解析出来的数据为空(即Size为0)则说明无法解析完成,需要再填充数据再次调用完成解析得到一个AVPacket,之后才能调avcodec_send_packet()送给解码器.
4. avcodec_receive_frame()返回值,前面提到一个AVPacket并不一定代表有一帧输出,需要根据返回值来区分.
- receive 0 :receive_frame返回值为0,正常状态,意味着已经输出一帧。
- receive EAGAIN:receive_frame返回值为EAGAIN,未能输出frame,需要输入更多的packet才能输出当前frame。
- receive EOF :receive_frame返回值为EOF,当处于send EOF状态后,调用一次或者多次receive_frame后就能得到该状态,表示所有的帧已经被输出。
- receive EINVAL:代表codec未打开,或者当前操作的是一个编码器
- receive AVERROR_INPUT_CHANGED:代表当前解码的帧参数有变化,同第一个解码帧相比,多是SPS PPS等语法元素变化。
- AV_CODEC_FLAG_DROPCHANGED如果开启了,还允许再出现这种情况的时候丢帧。
- other negative value: 其他的解码错误
encode audio
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 * audio encoding with libavcodec API example. 26 * 27 * @example encode_audio.c 28 */ 29 30 #include <stdint.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 34 #include <libavcodec/avcodec.h> 35 36 #include <libavutil/channel_layout.h> 37 #include <libavutil/common.h> 38 #include <libavutil/frame.h> 39 #include <libavutil/samplefmt.h> 40 41 /* check that a given sample format is supported by the encoder */ 42 static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt) 43 { 44 const enum AVSampleFormat *p = codec->sample_fmts; 45 46 while (*p != AV_SAMPLE_FMT_NONE) { 47 if (*p == sample_fmt) 48 return 1; 49 p++; 50 } 51 return 0; 52 } 53 54 /* just pick the highest supported samplerate */ 55 static int select_sample_rate(const AVCodec *codec) 56 { 57 const int *p; 58 int best_samplerate = 0; 59 60 if (!codec->supported_samplerates) 61 return 44100; 62 63 p = codec->supported_samplerates; 64 while (*p) { 65 if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate)) 66 best_samplerate = *p; 67 p++; 68 } 69 return best_samplerate; 70 } 71 72 /* select layout with the highest channel count */ 73 static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst) 74 { 75 const AVChannelLayout *p, *best_ch_layout; 76 int best_nb_channels = 0; 77 78 if (!codec->ch_layouts) 79 return av_channel_layout_copy(dst, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); 80 81 p = codec->ch_layouts; 82 while (p->nb_channels) { 83 int nb_channels = p->nb_channels; 84 85 if (nb_channels > best_nb_channels) { 86 best_ch_layout = p; 87 best_nb_channels = nb_channels; 88 } 89 p++; 90 } 91 return av_channel_layout_copy(dst, best_ch_layout); 92 } 93 94 static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, 95 FILE *output) 96 { 97 int ret; 98 99 /* send the frame for encoding */ 100 ret = avcodec_send_frame(ctx, frame); 101 if (ret < 0) { 102 fprintf(stderr, "Error sending the frame to the encoder\n"); 103 exit(1); 104 } 105 106 /* read all the available output packets (in general there may be any 107 * number of them */ 108 while (ret >= 0) { 109 ret = avcodec_receive_packet(ctx, pkt); 110 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) 111 return; 112 else if (ret < 0) { 113 fprintf(stderr, "Error encoding audio frame\n"); 114 exit(1); 115 } 116 117 fwrite(pkt->data, 1, pkt->size, output); 118 av_packet_unref(pkt); 119 } 120 } 121 122 int main(int argc, char **argv) 123 { 124 const char *filename; 125 const AVCodec *codec; 126 AVCodecContext *c= NULL; 127 AVFrame *frame; 128 AVPacket *pkt; 129 int i, j, k, ret; 130 FILE *f; 131 uint16_t *samples; 132 float t, tincr; 133 134 if (argc <= 1) { 135 fprintf(stderr, "Usage: %s <output file>\n", argv[0]); 136 return 0; 137 } 138 filename = argv[1]; 139 140 /* find the MP2 encoder */ 141 codec = avcodec_find_encoder(AV_CODEC_ID_MP2); 142 if (!codec) { 143 fprintf(stderr, "Codec not found\n"); 144 exit(1); 145 } 146 147 c = avcodec_alloc_context3(codec); 148 if (!c) { 149 fprintf(stderr, "Could not allocate audio codec context\n"); 150 exit(1); 151 } 152 153 /* put sample parameters */ 154 c->bit_rate = 64000; 155 156 /* check that the encoder supports s16 pcm input */ 157 c->sample_fmt = AV_SAMPLE_FMT_S16; 158 if (!check_sample_fmt(codec, c->sample_fmt)) { 159 fprintf(stderr, "Encoder does not support sample format %s", 160 av_get_sample_fmt_name(c->sample_fmt)); 161 exit(1); 162 } 163 164 /* select other audio parameters supported by the encoder */ 165 c->sample_rate = select_sample_rate(codec); 166 ret = select_channel_layout(codec, &c->ch_layout); 167 if (ret < 0) 168 exit(1); 169 170 /* open it */ 171 if (avcodec_open2(c, codec, NULL) < 0) { 172 fprintf(stderr, "Could not open codec\n"); 173 exit(1); 174 } 175 176 f = fopen(filename, "wb"); 177 if (!f) { 178 fprintf(stderr, "Could not open %s\n", filename); 179 exit(1); 180 } 181 182 /* packet for holding encoded output */ 183 pkt = av_packet_alloc(); 184 if (!pkt) { 185 fprintf(stderr, "could not allocate the packet\n"); 186 exit(1); 187 } 188 189 /* frame containing input raw audio */ 190 frame = av_frame_alloc(); 191 if (!frame) { 192 fprintf(stderr, "Could not allocate audio frame\n"); 193 exit(1); 194 } 195 196 frame->nb_samples = c->frame_size; 197 frame->format = c->sample_fmt; 198 ret = av_channel_layout_copy(&frame->ch_layout, &c->ch_layout); 199 if (ret < 0) 200 exit(1); 201 202 /* allocate the data buffers */ 203 ret = av_frame_get_buffer(frame, 0); 204 if (ret < 0) { 205 fprintf(stderr, "Could not allocate audio data buffers\n"); 206 exit(1); 207 } 208 209 /* encode a single tone sound */ 210 t = 0; 211 tincr = 2 * M_PI * 440.0 / c->sample_rate; 212 for (i = 0; i < 200; i++) { 213 /* make sure the frame is writable -- makes a copy if the encoder 214 * kept a reference internally */ 215 ret = av_frame_make_writable(frame); 216 if (ret < 0) 217 exit(1); 218 samples = (uint16_t*)frame->data[0]; 219 220 for (j = 0; j < c->frame_size; j++) { 221 samples[2*j] = (int)(sin(t) * 10000); 222 223 for (k = 1; k < c->ch_layout.nb_channels; k++) 224 samples[2*j + k] = samples[2*j]; 225 t += tincr; 226 } 227 encode(c, frame, pkt, f); 228 } 229 230 /* flush the encoder */ 231 encode(c, NULL, pkt, f); 232 233 fclose(f); 234 235 av_frame_free(&frame); 236 av_packet_free(&pkt); 237 avcodec_free_context(&c); 238 239 return 0; 240 }
encode video
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 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 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 }
filtering audio
1 /* 2 * Copyright (c) 2010 Nicolas George 3 * Copyright (c) 2011 Stefano Sabatini 4 * Copyright (c) 2012 Clément Bœsch 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 /** 26 * @file 27 * API example for audio decoding and filtering 28 * @example filtering_audio.c 29 */ 30 31 #include <unistd.h> 32 33 #include <libavcodec/avcodec.h> 34 #include <libavformat/avformat.h> 35 #include <libavfilter/buffersink.h> 36 #include <libavfilter/buffersrc.h> 37 #include <libavutil/channel_layout.h> 38 #include <libavutil/opt.h> 39 40 static const char *filter_descr = "aresample=8000,aformat=sample_fmts=s16:channel_layouts=mono"; 41 static const char *player = "ffplay -f s16le -ar 8000 -ac 1 -"; 42 43 static AVFormatContext *fmt_ctx; 44 static AVCodecContext *dec_ctx; 45 AVFilterContext *buffersink_ctx; 46 AVFilterContext *buffersrc_ctx; 47 AVFilterGraph *filter_graph; 48 static int audio_stream_index = -1; 49 50 static int open_input_file(const char *filename) 51 { 52 const AVCodec *dec; 53 int ret; 54 55 if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) { 56 av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n"); 57 return ret; 58 } 59 60 if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) { 61 av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n"); 62 return ret; 63 } 64 65 /* select the audio stream */ 66 ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0); 67 if (ret < 0) { 68 av_log(NULL, AV_LOG_ERROR, "Cannot find an audio stream in the input file\n"); 69 return ret; 70 } 71 audio_stream_index = ret; 72 73 /* create decoding context */ 74 dec_ctx = avcodec_alloc_context3(dec); 75 if (!dec_ctx) 76 return AVERROR(ENOMEM); 77 avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[audio_stream_index]->codecpar); 78 79 /* init the audio decoder */ 80 if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) { 81 av_log(NULL, AV_LOG_ERROR, "Cannot open audio decoder\n"); 82 return ret; 83 } 84 85 return 0; 86 } 87 88 static int init_filters(const char *filters_descr) 89 { 90 char args[512]; 91 int ret = 0; 92 const AVFilter *abuffersrc = avfilter_get_by_name("abuffer"); 93 const AVFilter *abuffersink = avfilter_get_by_name("abuffersink"); 94 AVFilterInOut *outputs = avfilter_inout_alloc(); 95 AVFilterInOut *inputs = avfilter_inout_alloc(); 96 static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_S16, -1 }; 97 static const int out_sample_rates[] = { 8000, -1 }; 98 const AVFilterLink *outlink; 99 AVRational time_base = fmt_ctx->streams[audio_stream_index]->time_base; 100 101 filter_graph = avfilter_graph_alloc(); 102 if (!outputs || !inputs || !filter_graph) { 103 ret = AVERROR(ENOMEM); 104 goto end; 105 } 106 107 /* buffer audio source: the decoded frames from the decoder will be inserted here. */ 108 if (dec_ctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) 109 av_channel_layout_default(&dec_ctx->ch_layout, dec_ctx->ch_layout.nb_channels); 110 ret = snprintf(args, sizeof(args), 111 "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=", 112 time_base.num, time_base.den, dec_ctx->sample_rate, 113 av_get_sample_fmt_name(dec_ctx->sample_fmt)); 114 av_channel_layout_describe(&dec_ctx->ch_layout, args + ret, sizeof(args) - ret); 115 ret = avfilter_graph_create_filter(&buffersrc_ctx, abuffersrc, "in", 116 args, NULL, filter_graph); 117 if (ret < 0) { 118 av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n"); 119 goto end; 120 } 121 122 /* buffer audio sink: to terminate the filter chain. */ 123 ret = avfilter_graph_create_filter(&buffersink_ctx, abuffersink, "out", 124 NULL, NULL, filter_graph); 125 if (ret < 0) { 126 av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n"); 127 goto end; 128 } 129 130 ret = av_opt_set_int_list(buffersink_ctx, "sample_fmts", out_sample_fmts, -1, 131 AV_OPT_SEARCH_CHILDREN); 132 if (ret < 0) { 133 av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n"); 134 goto end; 135 } 136 137 ret = av_opt_set(buffersink_ctx, "ch_layouts", "mono", 138 AV_OPT_SEARCH_CHILDREN); 139 if (ret < 0) { 140 av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n"); 141 goto end; 142 } 143 144 ret = av_opt_set_int_list(buffersink_ctx, "sample_rates", out_sample_rates, -1, 145 AV_OPT_SEARCH_CHILDREN); 146 if (ret < 0) { 147 av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n"); 148 goto end; 149 } 150 151 /* 152 * Set the endpoints for the filter graph. The filter_graph will 153 * be linked to the graph described by filters_descr. 154 */ 155 156 /* 157 * The buffer source output must be connected to the input pad of 158 * the first filter described by filters_descr; since the first 159 * filter input label is not specified, it is set to "in" by 160 * default. 161 */ 162 outputs->name = av_strdup("in"); 163 outputs->filter_ctx = buffersrc_ctx; 164 outputs->pad_idx = 0; 165 outputs->next = NULL; 166 167 /* 168 * The buffer sink input must be connected to the output pad of 169 * the last filter described by filters_descr; since the last 170 * filter output label is not specified, it is set to "out" by 171 * default. 172 */ 173 inputs->name = av_strdup("out"); 174 inputs->filter_ctx = buffersink_ctx; 175 inputs->pad_idx = 0; 176 inputs->next = NULL; 177 178 if ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr, 179 &inputs, &outputs, NULL)) < 0) 180 goto end; 181 182 if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) 183 goto end; 184 185 /* Print summary of the sink buffer 186 * Note: args buffer is reused to store channel layout string */ 187 outlink = buffersink_ctx->inputs[0]; 188 av_channel_layout_describe(&outlink->ch_layout, args, sizeof(args)); 189 av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n", 190 (int)outlink->sample_rate, 191 (char *)av_x_if_null(av_get_sample_fmt_name(outlink->format), "?"), 192 args); 193 194 end: 195 avfilter_inout_free(&inputs); 196 avfilter_inout_free(&outputs); 197 198 return ret; 199 } 200 201 static void print_frame(const AVFrame *frame) 202 { 203 const int n = frame->nb_samples * frame->ch_layout.nb_channels; 204 const uint16_t *p = (uint16_t*)frame->data[0]; 205 const uint16_t *p_end = p + n; 206 207 while (p < p_end) { 208 fputc(*p & 0xff, stdout); 209 fputc(*p>>8 & 0xff, stdout); 210 p++; 211 } 212 fflush(stdout); 213 } 214 215 int main(int argc, char **argv) 216 { 217 int ret; 218 AVPacket *packet = av_packet_alloc(); 219 AVFrame *frame = av_frame_alloc(); 220 AVFrame *filt_frame = av_frame_alloc(); 221 222 if (!packet || !frame || !filt_frame) { 223 fprintf(stderr, "Could not allocate frame or packet\n"); 224 exit(1); 225 } 226 if (argc != 2) { 227 fprintf(stderr, "Usage: %s file | %s\n", argv[0], player); 228 exit(1); 229 } 230 231 if ((ret = open_input_file(argv[1])) < 0) 232 goto end; 233 if ((ret = init_filters(filter_descr)) < 0) 234 goto end; 235 236 /* read all packets */ 237 while (1) { 238 if ((ret = av_read_frame(fmt_ctx, packet)) < 0) 239 break; 240 241 if (packet->stream_index == audio_stream_index) { 242 ret = avcodec_send_packet(dec_ctx, packet); 243 if (ret < 0) { 244 av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the decoder\n"); 245 break; 246 } 247 248 while (ret >= 0) { 249 ret = avcodec_receive_frame(dec_ctx, frame); 250 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { 251 break; 252 } else if (ret < 0) { 253 av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n"); 254 goto end; 255 } 256 257 if (ret >= 0) { 258 /* push the audio data from decoded frame into the filtergraph */ 259 if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { 260 av_log(NULL, AV_LOG_ERROR, "Error while feeding the audio filtergraph\n"); 261 break; 262 } 263 264 /* pull filtered audio from the filtergraph */ 265 while (1) { 266 ret = av_buffersink_get_frame(buffersink_ctx, filt_frame); 267 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) 268 break; 269 if (ret < 0) 270 goto end; 271 print_frame(filt_frame); 272 av_frame_unref(filt_frame); 273 } 274 av_frame_unref(frame); 275 } 276 } 277 } 278 av_packet_unref(packet); 279 } 280 end: 281 avfilter_graph_free(&filter_graph); 282 avcodec_free_context(&dec_ctx); 283 avformat_close_input(&fmt_ctx); 284 av_packet_free(&packet); 285 av_frame_free(&frame); 286 av_frame_free(&filt_frame); 287 288 if (ret < 0 && ret != AVERROR_EOF) { 289 fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); 290 exit(1); 291 } 292 293 exit(0); 294 }
filtering video
1 /* 2 * Copyright (c) 2010 Nicolas George 3 * Copyright (c) 2011 Stefano Sabatini 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to deal 7 * in the Software without restriction, including without limitation the rights 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 * THE SOFTWARE. 22 */ 23 24 /** 25 * @file 26 * API example for decoding and filtering 27 * @example filtering_video.c 28 */ 29 30 #define _XOPEN_SOURCE 600 /* for usleep */ 31 #include <unistd.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 35 #include <libavcodec/avcodec.h> 36 #include <libavformat/avformat.h> 37 #include <libavfilter/buffersink.h> 38 #include <libavfilter/buffersrc.h> 39 #include <libavutil/opt.h> 40 41 const char *filter_descr = "scale=78:24,transpose=cclock"; 42 /* other way: 43 scale=78:24 [scl]; [scl] transpose=cclock // assumes "[in]" and "[out]" to be input output pads respectively 44 */ 45 46 static AVFormatContext *fmt_ctx; 47 static AVCodecContext *dec_ctx; 48 AVFilterContext *buffersink_ctx; 49 AVFilterContext *buffersrc_ctx; 50 AVFilterGraph *filter_graph; 51 static int video_stream_index = -1; 52 static int64_t last_pts = AV_NOPTS_VALUE; 53 54 static int open_input_file(const char *filename) 55 { 56 const AVCodec *dec; 57 int ret; 58 59 if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) { 60 av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n"); 61 return ret; 62 } 63 64 if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) { 65 av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n"); 66 return ret; 67 } 68 69 /* select the video stream */ 70 ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0); 71 if (ret < 0) { 72 av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file\n"); 73 return ret; 74 } 75 video_stream_index = ret; 76 77 /* create decoding context */ 78 dec_ctx = avcodec_alloc_context3(dec); 79 if (!dec_ctx) 80 return AVERROR(ENOMEM); 81 avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[video_stream_index]->codecpar); 82 83 /* init the video decoder */ 84 if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) { 85 av_log(NULL, AV_LOG_ERROR, "Cannot open video decoder\n"); 86 return ret; 87 } 88 89 return 0; 90 } 91 92 static int init_filters(const char *filters_descr) 93 { 94 char args[512]; 95 int ret = 0; 96 const AVFilter *buffersrc = avfilter_get_by_name("buffer"); 97 const AVFilter *buffersink = avfilter_get_by_name("buffersink"); 98 AVFilterInOut *outputs = avfilter_inout_alloc(); 99 AVFilterInOut *inputs = avfilter_inout_alloc(); 100 AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base; 101 enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }; 102 103 filter_graph = avfilter_graph_alloc(); 104 if (!outputs || !inputs || !filter_graph) { 105 ret = AVERROR(ENOMEM); 106 goto end; 107 } 108 109 /* buffer video source: the decoded frames from the decoder will be inserted here. */ 110 snprintf(args, sizeof(args), 111 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", 112 dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, 113 time_base.num, time_base.den, 114 dec_ctx->sample_aspect_ratio.num, dec_ctx->sample_aspect_ratio.den); 115 116 ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", 117 args, NULL, filter_graph); 118 if (ret < 0) { 119 av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n"); 120 goto end; 121 } 122 123 /* buffer video sink: to terminate the filter chain. */ 124 ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", 125 NULL, NULL, filter_graph); 126 if (ret < 0) { 127 av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n"); 128 goto end; 129 } 130 131 ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts, 132 AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); 133 if (ret < 0) { 134 av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n"); 135 goto end; 136 } 137 138 /* 139 * Set the endpoints for the filter graph. The filter_graph will 140 * be linked to the graph described by filters_descr. 141 */ 142 143 /* 144 * The buffer source output must be connected to the input pad of 145 * the first filter described by filters_descr; since the first 146 * filter input label is not specified, it is set to "in" by 147 * default. 148 */ 149 outputs->name = av_strdup("in"); 150 outputs->filter_ctx = buffersrc_ctx; 151 outputs->pad_idx = 0; 152 outputs->next = NULL; 153 154 /* 155 * The buffer sink input must be connected to the output pad of 156 * the last filter described by filters_descr; since the last 157 * filter output label is not specified, it is set to "out" by 158 * default. 159 */ 160 inputs->name = av_strdup("out"); 161 inputs->filter_ctx = buffersink_ctx; 162 inputs->pad_idx = 0; 163 inputs->next = NULL; 164 165 if ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr, 166 &inputs, &outputs, NULL)) < 0) 167 goto end; 168 169 if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) 170 goto end; 171 172 end: 173 avfilter_inout_free(&inputs); 174 avfilter_inout_free(&outputs); 175 176 return ret; 177 } 178 179 static void display_frame(const AVFrame *frame, AVRational time_base) 180 { 181 int x, y; 182 uint8_t *p0, *p; 183 int64_t delay; 184 185 if (frame->pts != AV_NOPTS_VALUE) { 186 if (last_pts != AV_NOPTS_VALUE) { 187 /* sleep roughly the right amount of time; 188 * usleep is in microseconds, just like AV_TIME_BASE. */ 189 delay = av_rescale_q(frame->pts - last_pts, 190 time_base, AV_TIME_BASE_Q); 191 if (delay > 0 && delay < 1000000) 192 usleep(delay); 193 } 194 last_pts = frame->pts; 195 } 196 197 /* Trivial ASCII grayscale display. */ 198 p0 = frame->data[0]; 199 puts("\033c"); 200 for (y = 0; y < frame->height; y++) { 201 p = p0; 202 for (x = 0; x < frame->width; x++) 203 putchar(" .-+#"[*(p++) / 52]); 204 putchar('\n'); 205 p0 += frame->linesize[0]; 206 } 207 fflush(stdout); 208 } 209 210 int main(int argc, char **argv) 211 { 212 int ret; 213 AVPacket *packet; 214 AVFrame *frame; 215 AVFrame *filt_frame; 216 217 if (argc != 2) { 218 fprintf(stderr, "Usage: %s file\n", argv[0]); 219 exit(1); 220 } 221 222 frame = av_frame_alloc(); 223 filt_frame = av_frame_alloc(); 224 packet = av_packet_alloc(); 225 if (!frame || !filt_frame || !packet) { 226 fprintf(stderr, "Could not allocate frame or packet\n"); 227 exit(1); 228 } 229 230 if ((ret = open_input_file(argv[1])) < 0) 231 goto end; 232 if ((ret = init_filters(filter_descr)) < 0) 233 goto end; 234 235 /* read all packets */ 236 while (1) { 237 if ((ret = av_read_frame(fmt_ctx, packet)) < 0) 238 break; 239 240 if (packet->stream_index == video_stream_index) { 241 ret = avcodec_send_packet(dec_ctx, packet); 242 if (ret < 0) { 243 av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the decoder\n"); 244 break; 245 } 246 247 while (ret >= 0) { 248 ret = avcodec_receive_frame(dec_ctx, frame); 249 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { 250 break; 251 } else if (ret < 0) { 252 av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n"); 253 goto end; 254 } 255 256 frame->pts = frame->best_effort_timestamp; 257 258 /* push the decoded frame into the filtergraph */ 259 if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { 260 av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n"); 261 break; 262 } 263 264 /* pull filtered frames from the filtergraph */ 265 while (1) { 266 ret = av_buffersink_get_frame(buffersink_ctx, filt_frame); 267 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) 268 break; 269 if (ret < 0) 270 goto end; 271 display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base); 272 av_frame_unref(filt_frame); 273 } 274 av_frame_unref(frame); 275 } 276 } 277 av_packet_unref(packet); 278 } 279 end: 280 avfilter_graph_free(&filter_graph); 281 avcodec_free_context(&dec_ctx); 282 avformat_close_input(&fmt_ctx); 283 av_frame_free(&frame); 284 av_frame_free(&filt_frame); 285 av_packet_free(&packet); 286 287 if (ret < 0 && ret != AVERROR_EOF) { 288 fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); 289 exit(1); 290 } 291 292 exit(0); 293 }
hw decode
1 /* 2 * Copyright (c) 2017 Jun Zhao 3 * Copyright (c) 2017 Kaixuan Liu 4 * 5 * HW Acceleration API (video decoding) decode sample 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 /** 27 * @file 28 * HW-Accelerated decoding example. 29 * 30 * @example hw_decode.c 31 * This example shows how to do HW-accelerated decoding with output 32 * frames from the HW video surfaces. 33 */ 34 35 #include <stdio.h> 36 37 #include <libavcodec/avcodec.h> 38 #include <libavformat/avformat.h> 39 #include <libavutil/pixdesc.h> 40 #include <libavutil/hwcontext.h> 41 #include <libavutil/opt.h> 42 #include <libavutil/avassert.h> 43 #include <libavutil/imgutils.h> 44 45 static AVBufferRef *hw_device_ctx = NULL; 46 static enum AVPixelFormat hw_pix_fmt; 47 static FILE *output_file = NULL; 48 49 static int hw_decoder_init(AVCodecContext *ctx, const enum AVHWDeviceType type) 50 { 51 int err = 0; 52 53 if ((err = av_hwdevice_ctx_create(&hw_device_ctx, type, 54 NULL, NULL, 0)) < 0) { 55 fprintf(stderr, "Failed to create specified HW device.\n"); 56 return err; 57 } 58 ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx); 59 60 return err; 61 } 62 63 static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, 64 const enum AVPixelFormat *pix_fmts) 65 { 66 const enum AVPixelFormat *p; 67 68 for (p = pix_fmts; *p != -1; p++) { 69 if (*p == hw_pix_fmt) 70 return *p; 71 } 72 73 fprintf(stderr, "Failed to get HW surface format.\n"); 74 return AV_PIX_FMT_NONE; 75 } 76 77 static int decode_write(AVCodecContext *avctx, AVPacket *packet) 78 { 79 AVFrame *frame = NULL, *sw_frame = NULL; 80 AVFrame *tmp_frame = NULL; 81 uint8_t *buffer = NULL; 82 int size; 83 int ret = 0; 84 85 ret = avcodec_send_packet(avctx, packet); 86 if (ret < 0) { 87 fprintf(stderr, "Error during decoding\n"); 88 return ret; 89 } 90 91 while (1) { 92 if (!(frame = av_frame_alloc()) || !(sw_frame = av_frame_alloc())) { 93 fprintf(stderr, "Can not alloc frame\n"); 94 ret = AVERROR(ENOMEM); 95 goto fail; 96 } 97 98 ret = avcodec_receive_frame(avctx, frame); 99 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { 100 av_frame_free(&frame); 101 av_frame_free(&sw_frame); 102 return 0; 103 } else if (ret < 0) { 104 fprintf(stderr, "Error while decoding\n"); 105 goto fail; 106 } 107 108 if (frame->format == hw_pix_fmt) { 109 /* retrieve data from GPU to CPU */ 110 if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) < 0) { 111 fprintf(stderr, "Error transferring the data to system memory\n"); 112 goto fail; 113 } 114 tmp_frame = sw_frame; 115 } else 116 tmp_frame = frame; 117 118 size = av_image_get_buffer_size(tmp_frame->format, tmp_frame->width, 119 tmp_frame->height, 1); 120 buffer = av_malloc(size); 121 if (!buffer) { 122 fprintf(stderr, "Can not alloc buffer\n"); 123 ret = AVERROR(ENOMEM); 124 goto fail; 125 } 126 ret = av_image_copy_to_buffer(buffer, size, 127 (const uint8_t * const *)tmp_frame->data, 128 (const int *)tmp_frame->linesize, tmp_frame->format, 129 tmp_frame->width, tmp_frame->height, 1); 130 if (ret < 0) { 131 fprintf(stderr, "Can not copy image to buffer\n"); 132 goto fail; 133 } 134 135 if ((ret = fwrite(buffer, 1, size, output_file)) < 0) { 136 fprintf(stderr, "Failed to dump raw data.\n"); 137 goto fail; 138 } 139 140 fail: 141 av_frame_free(&frame); 142 av_frame_free(&sw_frame); 143 av_freep(&buffer); 144 if (ret < 0) 145 return ret; 146 } 147 } 148 149 int main(int argc, char *argv[]) 150 { 151 AVFormatContext *input_ctx = NULL; 152 int video_stream, ret; 153 AVStream *video = NULL; 154 AVCodecContext *decoder_ctx = NULL; 155 const AVCodec *decoder = NULL; 156 AVPacket *packet = NULL; 157 enum AVHWDeviceType type; 158 int i; 159 160 if (argc < 4) { 161 fprintf(stderr, "Usage: %s <device type> <input file> <output file>\n", argv[0]); 162 return -1; 163 } 164 165 type = av_hwdevice_find_type_by_name(argv[1]); 166 if (type == AV_HWDEVICE_TYPE_NONE) { 167 fprintf(stderr, "Device type %s is not supported.\n", argv[1]); 168 fprintf(stderr, "Available device types:"); 169 while((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE) 170 fprintf(stderr, " %s", av_hwdevice_get_type_name(type)); 171 fprintf(stderr, "\n"); 172 return -1; 173 } 174 175 packet = av_packet_alloc(); 176 if (!packet) { 177 fprintf(stderr, "Failed to allocate AVPacket\n"); 178 return -1; 179 } 180 181 /* open the input file */ 182 if (avformat_open_input(&input_ctx, argv[2], NULL, NULL) != 0) { 183 fprintf(stderr, "Cannot open input file '%s'\n", argv[2]); 184 return -1; 185 } 186 187 if (avformat_find_stream_info(input_ctx, NULL) < 0) { 188 fprintf(stderr, "Cannot find input stream information.\n"); 189 return -1; 190 } 191 192 /* find the video stream information */ 193 ret = av_find_best_stream(input_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); 194 if (ret < 0) { 195 fprintf(stderr, "Cannot find a video stream in the input file\n"); 196 return -1; 197 } 198 video_stream = ret; 199 200 for (i = 0;; i++) { 201 const AVCodecHWConfig *config = avcodec_get_hw_config(decoder, i); 202 if (!config) { 203 fprintf(stderr, "Decoder %s does not support device type %s.\n", 204 decoder->name, av_hwdevice_get_type_name(type)); 205 return -1; 206 } 207 if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && 208 config->device_type == type) { 209 hw_pix_fmt = config->pix_fmt; 210 break; 211 } 212 } 213 214 if (!(decoder_ctx = avcodec_alloc_context3(decoder))) 215 return AVERROR(ENOMEM); 216 217 video = input_ctx->streams[video_stream]; 218 if (avcodec_parameters_to_context(decoder_ctx, video->codecpar) < 0) 219 return -1; 220 221 decoder_ctx->get_format = get_hw_format; 222 223 if (hw_decoder_init(decoder_ctx, type) < 0) 224 return -1; 225 226 if ((ret = avcodec_open2(decoder_ctx, decoder, NULL)) < 0) { 227 fprintf(stderr, "Failed to open codec for stream #%u\n", video_stream); 228 return -1; 229 } 230 231 /* open the file to dump raw data */ 232 output_file = fopen(argv[3], "w+b"); 233 234 /* actual decoding and dump the raw data */ 235 while (ret >= 0) { 236 if ((ret = av_read_frame(input_ctx, packet)) < 0) 237 break; 238 239 if (video_stream == packet->stream_index) 240 ret = decode_write(decoder_ctx, packet); 241 242 av_packet_unref(packet); 243 } 244 245 /* flush the decoder */ 246 ret = decode_write(decoder_ctx, NULL); 247 248 if (output_file) 249 fclose(output_file); 250 av_packet_free(&packet); 251 avcodec_free_context(&decoder_ctx); 252 avformat_close_input(&input_ctx); 253 av_buffer_unref(&hw_device_ctx); 254 255 return 0; 256 }
http multiclient
1 /* 2 * Copyright (c) 2015 Stephan Holljes 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 * libavformat multi-client network API usage example. 26 * 27 * @example http_multiclient.c 28 * This example will serve a file without decoding or demuxing it over http. 29 * Multiple clients can connect and will receive the same file. 30 */ 31 32 #include <libavformat/avformat.h> 33 #include <libavutil/opt.h> 34 #include <unistd.h> 35 36 static void process_client(AVIOContext *client, const char *in_uri) 37 { 38 AVIOContext *input = NULL; 39 uint8_t buf[1024]; 40 int ret, n, reply_code; 41 uint8_t *resource = NULL; 42 while ((ret = avio_handshake(client)) > 0) { 43 av_opt_get(client, "resource", AV_OPT_SEARCH_CHILDREN, &resource); 44 // check for strlen(resource) is necessary, because av_opt_get() 45 // may return empty string. 46 if (resource && strlen(resource)) 47 break; 48 av_freep(&resource); 49 } 50 if (ret < 0) 51 goto end; 52 av_log(client, AV_LOG_TRACE, "resource=%p\n", resource); 53 if (resource && resource[0] == '/' && !strcmp((resource + 1), in_uri)) { 54 reply_code = 200; 55 } else { 56 reply_code = AVERROR_HTTP_NOT_FOUND; 57 } 58 if ((ret = av_opt_set_int(client, "reply_code", reply_code, AV_OPT_SEARCH_CHILDREN)) < 0) { 59 av_log(client, AV_LOG_ERROR, "Failed to set reply_code: %s.\n", av_err2str(ret)); 60 goto end; 61 } 62 av_log(client, AV_LOG_TRACE, "Set reply code to %d\n", reply_code); 63 64 while ((ret = avio_handshake(client)) > 0); 65 66 if (ret < 0) 67 goto end; 68 69 fprintf(stderr, "Handshake performed.\n"); 70 if (reply_code != 200) 71 goto end; 72 fprintf(stderr, "Opening input file.\n"); 73 if ((ret = avio_open2(&input, in_uri, AVIO_FLAG_READ, NULL, NULL)) < 0) { 74 av_log(input, AV_LOG_ERROR, "Failed to open input: %s: %s.\n", in_uri, 75 av_err2str(ret)); 76 goto end; 77 } 78 for(;;) { 79 n = avio_read(input, buf, sizeof(buf)); 80 if (n < 0) { 81 if (n == AVERROR_EOF) 82 break; 83 av_log(input, AV_LOG_ERROR, "Error reading from input: %s.\n", 84 av_err2str(n)); 85 break; 86 } 87 avio_write(client, buf, n); 88 avio_flush(client); 89 } 90 end: 91 fprintf(stderr, "Flushing client\n"); 92 avio_flush(client); 93 fprintf(stderr, "Closing client\n"); 94 avio_close(client); 95 fprintf(stderr, "Closing input\n"); 96 avio_close(input); 97 av_freep(&resource); 98 } 99 100 int main(int argc, char **argv) 101 { 102 AVDictionary *options = NULL; 103 AVIOContext *client = NULL, *server = NULL; 104 const char *in_uri, *out_uri; 105 int ret, pid; 106 av_log_set_level(AV_LOG_TRACE); 107 if (argc < 3) { 108 printf("usage: %s input http://hostname[:port]\n" 109 "API example program to serve http to multiple clients.\n" 110 "\n", argv[0]); 111 return 1; 112 } 113 114 in_uri = argv[1]; 115 out_uri = argv[2]; 116 117 avformat_network_init(); 118 119 if ((ret = av_dict_set(&options, "listen", "2", 0)) < 0) { 120 fprintf(stderr, "Failed to set listen mode for server: %s\n", av_err2str(ret)); 121 return ret; 122 } 123 if ((ret = avio_open2(&server, out_uri, AVIO_FLAG_WRITE, NULL, &options)) < 0) { 124 fprintf(stderr, "Failed to open server: %s\n", av_err2str(ret)); 125 return ret; 126 } 127 fprintf(stderr, "Entering main loop.\n"); 128 for(;;) { 129 if ((ret = avio_accept(server, &client)) < 0) 130 goto end; 131 fprintf(stderr, "Accepted client, forking process.\n"); 132 // XXX: Since we don't reap our children and don't ignore signals 133 // this produces zombie processes. 134 pid = fork(); 135 if (pid < 0) { 136 perror("Fork failed"); 137 ret = AVERROR(errno); 138 goto end; 139 } 140 if (pid == 0) { 141 fprintf(stderr, "In child.\n"); 142 process_client(client, in_uri); 143 avio_close(server); 144 exit(0); 145 } 146 if (pid > 0) 147 avio_close(client); 148 } 149 end: 150 avio_close(server); 151 if (ret < 0 && ret != AVERROR_EOF) { 152 fprintf(stderr, "Some errors occurred: %s\n", av_err2str(ret)); 153 return 1; 154 } 155 return 0; 156 }
vaapi encode
1 /* 2 * Video Acceleration API (video encoding) encode sample 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 * Intel VAAPI-accelerated encoding example. 26 * 27 * @example vaapi_encode.c 28 * This example shows how to do VAAPI-accelerated encoding. now only support NV12 29 * raw file, usage like: vaapi_encode 1920 1080 input.yuv output.h264 30 * 31 */ 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <errno.h> 36 37 #include <libavcodec/avcodec.h> 38 #include <libavutil/pixdesc.h> 39 #include <libavutil/hwcontext.h> 40 41 static int width, height; 42 static AVBufferRef *hw_device_ctx = NULL; 43 44 static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx) 45 { 46 AVBufferRef *hw_frames_ref; 47 AVHWFramesContext *frames_ctx = NULL; 48 int err = 0; 49 50 if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) { 51 fprintf(stderr, "Failed to create VAAPI frame context.\n"); 52 return -1; 53 } 54 frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data); 55 frames_ctx->format = AV_PIX_FMT_VAAPI; 56 frames_ctx->sw_format = AV_PIX_FMT_NV12; 57 frames_ctx->width = width; 58 frames_ctx->height = height; 59 frames_ctx->initial_pool_size = 20; 60 if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) { 61 fprintf(stderr, "Failed to initialize VAAPI frame context." 62 "Error code: %s\n",av_err2str(err)); 63 av_buffer_unref(&hw_frames_ref); 64 return err; 65 } 66 ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref); 67 if (!ctx->hw_frames_ctx) 68 err = AVERROR(ENOMEM); 69 70 av_buffer_unref(&hw_frames_ref); 71 return err; 72 } 73 74 static int encode_write(AVCodecContext *avctx, AVFrame *frame, FILE *fout) 75 { 76 int ret = 0; 77 AVPacket *enc_pkt; 78 79 if (!(enc_pkt = av_packet_alloc())) 80 return AVERROR(ENOMEM); 81 82 if ((ret = avcodec_send_frame(avctx, frame)) < 0) { 83 fprintf(stderr, "Error code: %s\n", av_err2str(ret)); 84 goto end; 85 } 86 while (1) { 87 ret = avcodec_receive_packet(avctx, enc_pkt); 88 if (ret) 89 break; 90 91 enc_pkt->stream_index = 0; 92 ret = fwrite(enc_pkt->data, enc_pkt->size, 1, fout); 93 av_packet_unref(enc_pkt); 94 } 95 96 end: 97 av_packet_free(&enc_pkt); 98 ret = ((ret == AVERROR(EAGAIN)) ? 0 : -1); 99 return ret; 100 } 101 102 int main(int argc, char *argv[]) 103 { 104 int size, err; 105 FILE *fin = NULL, *fout = NULL; 106 AVFrame *sw_frame = NULL, *hw_frame = NULL; 107 AVCodecContext *avctx = NULL; 108 const AVCodec *codec = NULL; 109 const char *enc_name = "h264_vaapi"; 110 111 if (argc < 5) { 112 fprintf(stderr, "Usage: %s <width> <height> <input file> <output file>\n", argv[0]); 113 return -1; 114 } 115 116 width = atoi(argv[1]); 117 height = atoi(argv[2]); 118 size = width * height; 119 120 if (!(fin = fopen(argv[3], "r"))) { 121 fprintf(stderr, "Fail to open input file : %s\n", strerror(errno)); 122 return -1; 123 } 124 if (!(fout = fopen(argv[4], "w+b"))) { 125 fprintf(stderr, "Fail to open output file : %s\n", strerror(errno)); 126 err = -1; 127 goto close; 128 } 129 130 err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, 131 NULL, NULL, 0); 132 if (err < 0) { 133 fprintf(stderr, "Failed to create a VAAPI device. Error code: %s\n", av_err2str(err)); 134 goto close; 135 } 136 137 if (!(codec = avcodec_find_encoder_by_name(enc_name))) { 138 fprintf(stderr, "Could not find encoder.\n"); 139 err = -1; 140 goto close; 141 } 142 143 if (!(avctx = avcodec_alloc_context3(codec))) { 144 err = AVERROR(ENOMEM); 145 goto close; 146 } 147 148 avctx->width = width; 149 avctx->height = height; 150 avctx->time_base = (AVRational){1, 25}; 151 avctx->framerate = (AVRational){25, 1}; 152 avctx->sample_aspect_ratio = (AVRational){1, 1}; 153 avctx->pix_fmt = AV_PIX_FMT_VAAPI; 154 155 /* set hw_frames_ctx for encoder's AVCodecContext */ 156 if ((err = set_hwframe_ctx(avctx, hw_device_ctx)) < 0) { 157 fprintf(stderr, "Failed to set hwframe context.\n"); 158 goto close; 159 } 160 161 if ((err = avcodec_open2(avctx, codec, NULL)) < 0) { 162 fprintf(stderr, "Cannot open video encoder codec. Error code: %s\n", av_err2str(err)); 163 goto close; 164 } 165 166 while (1) { 167 if (!(sw_frame = av_frame_alloc())) { 168 err = AVERROR(ENOMEM); 169 goto close; 170 } 171 /* read data into software frame, and transfer them into hw frame */ 172 sw_frame->width = width; 173 sw_frame->height = height; 174 sw_frame->format = AV_PIX_FMT_NV12; 175 if ((err = av_frame_get_buffer(sw_frame, 0)) < 0) 176 goto close; 177 if ((err = fread((uint8_t*)(sw_frame->data[0]), size, 1, fin)) <= 0) 178 break; 179 if ((err = fread((uint8_t*)(sw_frame->data[1]), size/2, 1, fin)) <= 0) 180 break; 181 182 if (!(hw_frame = av_frame_alloc())) { 183 err = AVERROR(ENOMEM); 184 goto close; 185 } 186 if ((err = av_hwframe_get_buffer(avctx->hw_frames_ctx, hw_frame, 0)) < 0) { 187 fprintf(stderr, "Error code: %s.\n", av_err2str(err)); 188 goto close; 189 } 190 if (!hw_frame->hw_frames_ctx) { 191 err = AVERROR(ENOMEM); 192 goto close; 193 } 194 if ((err = av_hwframe_transfer_data(hw_frame, sw_frame, 0)) < 0) { 195 fprintf(stderr, "Error while transferring frame data to surface." 196 "Error code: %s.\n", av_err2str(err)); 197 goto close; 198 } 199 200 if ((err = (encode_write(avctx, hw_frame, fout))) < 0) { 201 fprintf(stderr, "Failed to encode.\n"); 202 goto close; 203 } 204 av_frame_free(&hw_frame); 205 av_frame_free(&sw_frame); 206 } 207 208 /* flush encoder */ 209 err = encode_write(avctx, NULL, fout); 210 if (err == AVERROR_EOF) 211 err = 0; 212 213 close: 214 if (fin) 215 fclose(fin); 216 if (fout) 217 fclose(fout); 218 av_frame_free(&sw_frame); 219 av_frame_free(&hw_frame); 220 avcodec_free_context(&avctx); 221 av_buffer_unref(&hw_device_ctx); 222 223 return err; 224 }
vaapi trancode
1 /* 2 * Video Acceleration API (video transcoding) transcode sample 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 * Intel VAAPI-accelerated transcoding example. 26 * 27 * @example vaapi_transcode.c 28 * This example shows how to do VAAPI-accelerated transcoding. 29 * Usage: vaapi_transcode input_stream codec output_stream 30 * e.g: - vaapi_transcode input.mp4 h264_vaapi output_h264.mp4 31 * - vaapi_transcode input.mp4 vp9_vaapi output_vp9.ivf 32 */ 33 34 #include <stdio.h> 35 #include <errno.h> 36 37 #include <libavutil/hwcontext.h> 38 #include <libavcodec/avcodec.h> 39 #include <libavformat/avformat.h> 40 41 static AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL; 42 static AVBufferRef *hw_device_ctx = NULL; 43 static AVCodecContext *decoder_ctx = NULL, *encoder_ctx = NULL; 44 static int video_stream = -1; 45 static AVStream *ost; 46 static int initialized = 0; 47 48 static enum AVPixelFormat get_vaapi_format(AVCodecContext *ctx, 49 const enum AVPixelFormat *pix_fmts) 50 { 51 const enum AVPixelFormat *p; 52 53 for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { 54 if (*p == AV_PIX_FMT_VAAPI) 55 return *p; 56 } 57 58 fprintf(stderr, "Unable to decode this file using VA-API.\n"); 59 return AV_PIX_FMT_NONE; 60 } 61 62 static int open_input_file(const char *filename) 63 { 64 int ret; 65 const AVCodec *decoder = NULL; 66 AVStream *video = NULL; 67 68 if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) { 69 fprintf(stderr, "Cannot open input file '%s', Error code: %s\n", 70 filename, av_err2str(ret)); 71 return ret; 72 } 73 74 if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) { 75 fprintf(stderr, "Cannot find input stream information. Error code: %s\n", 76 av_err2str(ret)); 77 return ret; 78 } 79 80 ret = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); 81 if (ret < 0) { 82 fprintf(stderr, "Cannot find a video stream in the input file. " 83 "Error code: %s\n", av_err2str(ret)); 84 return ret; 85 } 86 video_stream = ret; 87 88 if (!(decoder_ctx = avcodec_alloc_context3(decoder))) 89 return AVERROR(ENOMEM); 90 91 video = ifmt_ctx->streams[video_stream]; 92 if ((ret = avcodec_parameters_to_context(decoder_ctx, video->codecpar)) < 0) { 93 fprintf(stderr, "avcodec_parameters_to_context error. Error code: %s\n", 94 av_err2str(ret)); 95 return ret; 96 } 97 98 decoder_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx); 99 if (!decoder_ctx->hw_device_ctx) { 100 fprintf(stderr, "A hardware device reference create failed.\n"); 101 return AVERROR(ENOMEM); 102 } 103 decoder_ctx->get_format = get_vaapi_format; 104 105 if ((ret = avcodec_open2(decoder_ctx, decoder, NULL)) < 0) 106 fprintf(stderr, "Failed to open codec for decoding. Error code: %s\n", 107 av_err2str(ret)); 108 109 return ret; 110 } 111 112 static int encode_write(AVPacket *enc_pkt, AVFrame *frame) 113 { 114 int ret = 0; 115 116 av_packet_unref(enc_pkt); 117 118 if ((ret = avcodec_send_frame(encoder_ctx, frame)) < 0) { 119 fprintf(stderr, "Error during encoding. Error code: %s\n", av_err2str(ret)); 120 goto end; 121 } 122 while (1) { 123 ret = avcodec_receive_packet(encoder_ctx, enc_pkt); 124 if (ret) 125 break; 126 127 enc_pkt->stream_index = 0; 128 av_packet_rescale_ts(enc_pkt, ifmt_ctx->streams[video_stream]->time_base, 129 ofmt_ctx->streams[0]->time_base); 130 ret = av_interleaved_write_frame(ofmt_ctx, enc_pkt); 131 if (ret < 0) { 132 fprintf(stderr, "Error during writing data to output file. " 133 "Error code: %s\n", av_err2str(ret)); 134 return -1; 135 } 136 } 137 138 end: 139 if (ret == AVERROR_EOF) 140 return 0; 141 ret = ((ret == AVERROR(EAGAIN)) ? 0:-1); 142 return ret; 143 } 144 145 static int dec_enc(AVPacket *pkt, const AVCodec *enc_codec) 146 { 147 AVFrame *frame; 148 int ret = 0; 149 150 ret = avcodec_send_packet(decoder_ctx, pkt); 151 if (ret < 0) { 152 fprintf(stderr, "Error during decoding. Error code: %s\n", av_err2str(ret)); 153 return ret; 154 } 155 156 while (ret >= 0) { 157 if (!(frame = av_frame_alloc())) 158 return AVERROR(ENOMEM); 159 160 ret = avcodec_receive_frame(decoder_ctx, frame); 161 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { 162 av_frame_free(&frame); 163 return 0; 164 } else if (ret < 0) { 165 fprintf(stderr, "Error while decoding. Error code: %s\n", av_err2str(ret)); 166 goto fail; 167 } 168 169 if (!initialized) { 170 /* we need to ref hw_frames_ctx of decoder to initialize encoder's codec. 171 Only after we get a decoded frame, can we obtain its hw_frames_ctx */ 172 encoder_ctx->hw_frames_ctx = av_buffer_ref(decoder_ctx->hw_frames_ctx); 173 if (!encoder_ctx->hw_frames_ctx) { 174 ret = AVERROR(ENOMEM); 175 goto fail; 176 } 177 /* set AVCodecContext Parameters for encoder, here we keep them stay 178 * the same as decoder. 179 * xxx: now the sample can't handle resolution change case. 180 */ 181 encoder_ctx->time_base = av_inv_q(decoder_ctx->framerate); 182 encoder_ctx->pix_fmt = AV_PIX_FMT_VAAPI; 183 encoder_ctx->width = decoder_ctx->width; 184 encoder_ctx->height = decoder_ctx->height; 185 186 if ((ret = avcodec_open2(encoder_ctx, enc_codec, NULL)) < 0) { 187 fprintf(stderr, "Failed to open encode codec. Error code: %s\n", 188 av_err2str(ret)); 189 goto fail; 190 } 191 192 if (!(ost = avformat_new_stream(ofmt_ctx, enc_codec))) { 193 fprintf(stderr, "Failed to allocate stream for output format.\n"); 194 ret = AVERROR(ENOMEM); 195 goto fail; 196 } 197 198 ost->time_base = encoder_ctx->time_base; 199 ret = avcodec_parameters_from_context(ost->codecpar, encoder_ctx); 200 if (ret < 0) { 201 fprintf(stderr, "Failed to copy the stream parameters. " 202 "Error code: %s\n", av_err2str(ret)); 203 goto fail; 204 } 205 206 /* write the stream header */ 207 if ((ret = avformat_write_header(ofmt_ctx, NULL)) < 0) { 208 fprintf(stderr, "Error while writing stream header. " 209 "Error code: %s\n", av_err2str(ret)); 210 goto fail; 211 } 212 213 initialized = 1; 214 } 215 216 if ((ret = encode_write(pkt, frame)) < 0) 217 fprintf(stderr, "Error during encoding and writing.\n"); 218 219 fail: 220 av_frame_free(&frame); 221 if (ret < 0) 222 return ret; 223 } 224 return 0; 225 } 226 227 int main(int argc, char **argv) 228 { 229 const AVCodec *enc_codec; 230 int ret = 0; 231 AVPacket *dec_pkt; 232 233 if (argc != 4) { 234 fprintf(stderr, "Usage: %s <input file> <encode codec> <output file>\n" 235 "The output format is guessed according to the file extension.\n" 236 "\n", argv[0]); 237 return -1; 238 } 239 240 ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, NULL, NULL, 0); 241 if (ret < 0) { 242 fprintf(stderr, "Failed to create a VAAPI device. Error code: %s\n", av_err2str(ret)); 243 return -1; 244 } 245 246 dec_pkt = av_packet_alloc(); 247 if (!dec_pkt) { 248 fprintf(stderr, "Failed to allocate decode packet\n"); 249 goto end; 250 } 251 252 if ((ret = open_input_file(argv[1])) < 0) 253 goto end; 254 255 if (!(enc_codec = avcodec_find_encoder_by_name(argv[2]))) { 256 fprintf(stderr, "Could not find encoder '%s'\n", argv[2]); 257 ret = -1; 258 goto end; 259 } 260 261 if ((ret = (avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, argv[3]))) < 0) { 262 fprintf(stderr, "Failed to deduce output format from file extension. Error code: " 263 "%s\n", av_err2str(ret)); 264 goto end; 265 } 266 267 if (!(encoder_ctx = avcodec_alloc_context3(enc_codec))) { 268 ret = AVERROR(ENOMEM); 269 goto end; 270 } 271 272 ret = avio_open(&ofmt_ctx->pb, argv[3], AVIO_FLAG_WRITE); 273 if (ret < 0) { 274 fprintf(stderr, "Cannot open output file. " 275 "Error code: %s\n", av_err2str(ret)); 276 goto end; 277 } 278 279 /* read all packets and only transcoding video */ 280 while (ret >= 0) { 281 if ((ret = av_read_frame(ifmt_ctx, dec_pkt)) < 0) 282 break; 283 284 if (video_stream == dec_pkt->stream_index) 285 ret = dec_enc(dec_pkt, enc_codec); 286 287 av_packet_unref(dec_pkt); 288 } 289 290 /* flush decoder */ 291 av_packet_unref(dec_pkt); 292 ret = dec_enc(dec_pkt, enc_codec); 293 294 /* flush encoder */ 295 ret = encode_write(dec_pkt, NULL); 296 297 /* write the trailer for output stream */ 298 av_write_trailer(ofmt_ctx); 299 300 end: 301 avformat_close_input(&ifmt_ctx); 302 avformat_close_input(&ofmt_ctx); 303 avcodec_free_context(&decoder_ctx); 304 avcodec_free_context(&encoder_ctx); 305 av_buffer_unref(&hw_device_ctx); 306 av_packet_free(&dec_pkt); 307 return ret; 308 }
2022/05/31
本文来自博客园,作者:追随技术,转载请注明原文链接:https://www.cnblogs.com/545235abc/p/16329765.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)