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: 其他的解码错误

decode video

 

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
posted @   追随技术  阅读(999)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示