History

doc/examples: Add example transcoding.c

Andrey Utkin committed 12 years ago

Commit e10ab431 parent e21235f4 files · +601 −0Browse files

Unified · Split

4 files
  1. configure +2 −0
  2. doc/Makefile +1 −0
  3. doc/examples/Makefile +1 −0
  4. doc/examples/transcoding.c +597 −0
configure+2−0
@@ -1272,6 +1272,7 @@ EXAMPLE_LIST=" · 1271 unmodified lines
12721272 resampling_audio_example
12731273 scaling_video_example
12741274 transcode_aac_example
1275+ transcoding_example
12751276 "
12761277
12771278 EXTERNAL_LIBRARY_LIST="
@@ -2482,6 +2483,7 @@ remuxing_example_deps="avcodec avformat avutil" · 1204 unmodified lines
24822483 resampling_audio_example_deps="avutil swresample"
24832484 scaling_video_example_deps="avutil swscale"
24842485 transcode_aac_example_deps="avcodec avformat swresample"
2486+transcoding_example_deps="avfilter avcodec avformat avutil"
24852487
24862488 # libraries
24872489 avcodec_deps="avutil"
doc/Makefile+1−0
@@ -48,6 +48,7 @@ DOC_EXAMPLES-$(CONFIG_REMUXING_EXAMPLE) += remuxing · 47 unmodified lines
4848 DOC_EXAMPLES-$(CONFIG_RESAMPLING_AUDIO_EXAMPLE) += resampling_audio
4949 DOC_EXAMPLES-$(CONFIG_SCALING_VIDEO_EXAMPLE) += scaling_video
5050 DOC_EXAMPLES-$(CONFIG_TRANSCODE_AAC_EXAMPLE) += transcode_aac
51+DOC_EXAMPLES-$(CONFIG_TRANSCODING_EXAMPLE) += transcoding
5152 ALL_DOC_EXAMPLES_LIST = $(DOC_EXAMPLES-) $(DOC_EXAMPLES-yes)
5253
5354 DOC_EXAMPLES := $(DOC_EXAMPLES-yes:%=doc/examples/%$(PROGSSUF)$(EXESUF))
doc/examples/Makefile+1−0
@@ -22,6 +22,7 @@ EXAMPLES= avio_reading \ · 21 unmodified lines
2222 resampling_audio \
2323 scaling_video \
2424 transcode_aac \
25+ transcoding \
2526
2627 OBJS=$(addsuffix .o,$(EXAMPLES))
2728
doc/examples/transcoding.c+597−0
@@ -0,0 +1,597 @@
1+/*
2+ * Copyright (c) 2010 Nicolas George
3+ * Copyright (c) 2011 Stefano Sabatini
4+ * Copyright (c) 2014 Andrey Utkin
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 demuxing, decoding, filtering, encoding and muxing
28+ * @example doc/examples/transcoding.c
29+ */
30+
31+#include <libavcodec/avcodec.h>
32+#include <libavformat/avformat.h>
33+#include <libavfilter/avfiltergraph.h>
34+#include <libavfilter/avcodec.h>
35+#include <libavfilter/buffersink.h>
36+#include <libavfilter/buffersrc.h>
37+#include <libavutil/opt.h>
38+#include <libavutil/pixdesc.h>
39+
40+static AVFormatContext *ifmt_ctx;
41+static AVFormatContext *ofmt_ctx;
42+typedef struct FilteringContext {
43+ AVFilterContext *buffersink_ctx;
44+ AVFilterContext *buffersrc_ctx;
45+ AVFilterGraph *filter_graph;
46+} FilteringContext;
47+static FilteringContext *filter_ctx;
48+
49+static int open_input_file(const char *filename)
50+{
51+ int ret;
52+ unsigned int i;
53+
54+ ifmt_ctx = NULL;
55+ if ((ret = avformat_open_input(&ifmt_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(ifmt_ctx, NULL)) < 0) {
61+ av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
62+ return ret;
63+ }
64+
65+ for (i = 0; i < ifmt_ctx->nb_streams; i++) {
66+ AVStream *stream;
67+ AVCodecContext *codec_ctx;
68+ stream = ifmt_ctx->streams[i];
69+ codec_ctx = stream->codec;
70+ /* Reencode video & audio and remux subtitles etc. */
71+ if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
72+ || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
73+ /* Open decoder */
74+ ret = avcodec_open2(codec_ctx,
75+ avcodec_find_decoder(codec_ctx->codec_id), NULL);
76+ if (ret < 0) {
77+ av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
78+ return ret;
79+ }
80+ }
81+ }
82+
83+ av_dump_format(ifmt_ctx, 0, filename, 0);
84+ return 0;
85+}
86+
87+static int open_output_file(const char *filename)
88+{
89+ AVStream *out_stream;
90+ AVStream *in_stream;
91+ AVCodecContext *dec_ctx, *enc_ctx;
92+ AVCodec *encoder;
93+ int ret;
94+ unsigned int i;
95+
96+ ofmt_ctx = NULL;
97+ avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);
98+ if (!ofmt_ctx) {
99+ av_log(NULL, AV_LOG_ERROR, "Could not create output context\n");
100+ return AVERROR_UNKNOWN;
101+ }
102+
103+
104+ for (i = 0; i < ifmt_ctx->nb_streams; i++) {
105+ out_stream = avformat_new_stream(ofmt_ctx, NULL);
106+ if (!out_stream) {
107+ av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n");
108+ return AVERROR_UNKNOWN;
109+ }
110+
111+ in_stream = ifmt_ctx->streams[i];
112+ dec_ctx = in_stream->codec;
113+ enc_ctx = out_stream->codec;
114+
115+ if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
116+ || dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
117+ /* in this example, we choose transcoding to same codec */
118+ encoder = avcodec_find_encoder(dec_ctx->codec_id);
119+
120+ /* In this example, we transcode to same properties (picture size,
121+ * sample rate etc.). These properties can be changed for output
122+ * streams easily using filters */
123+ if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
124+ enc_ctx->height = dec_ctx->height;
125+ enc_ctx->width = dec_ctx->width;
126+ enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;
127+ /* take first format from list of supported formats */
128+ enc_ctx->pix_fmt = encoder->pix_fmts[0];
129+ /* video time_base can be set to whatever is handy and supported by encoder */
130+ enc_ctx->time_base = dec_ctx->time_base;
131+ } else {
132+ enc_ctx->sample_rate = dec_ctx->sample_rate;
133+ enc_ctx->channel_layout = dec_ctx->channel_layout;
134+ enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
135+ /* take first format from list of supported formats */
136+ enc_ctx->sample_fmt = encoder->sample_fmts[0];
137+ enc_ctx->time_base = (AVRational){1, enc_ctx->sample_rate};
138+ }
139+
140+ /* Third parameter can be used to pass settings to encoder */
141+ ret = avcodec_open2(enc_ctx, encoder, NULL);
142+ if (ret < 0) {
143+ av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);
144+ return ret;
145+ }
146+ } else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) {
147+ av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);
148+ return AVERROR_INVALIDDATA;
149+ } else {
150+ /* if this stream must be remuxed */
151+ ret = avcodec_copy_context(ofmt_ctx->streams[i]->codec,
152+ ifmt_ctx->streams[i]->codec);
153+ if (ret < 0) {
154+ av_log(NULL, AV_LOG_ERROR, "Copying stream context failed\n");
155+ return ret;
156+ }
157+ }
158+
159+ if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
160+ enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
161+
162+ }
163+ av_dump_format(ofmt_ctx, 0, filename, 1);
164+
165+ if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {
166+ ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);
167+ if (ret < 0) {
168+ av_log(NULL, AV_LOG_ERROR, "Could not open output file '%s'", filename);
169+ return ret;
170+ }
171+ }
172+
173+ /* init muxer, write output file header */
174+ ret = avformat_write_header(ofmt_ctx, NULL);
175+ if (ret < 0) {
176+ av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n");
177+ return ret;
178+ }
179+
180+ return 0;
181+}
182+
183+static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
184+ AVCodecContext *enc_ctx, const char *filter_spec)
185+{
186+ char args[512];
187+ int ret = 0;
188+ AVFilter *buffersrc = NULL;
189+ AVFilter *buffersink = NULL;
190+ AVFilterContext *buffersrc_ctx = NULL;
191+ AVFilterContext *buffersink_ctx = NULL;
192+ AVFilterInOut *outputs = avfilter_inout_alloc();
193+ AVFilterInOut *inputs = avfilter_inout_alloc();
194+ AVFilterGraph *filter_graph = avfilter_graph_alloc();
195+
196+ if (!outputs || !inputs || !filter_graph) {
197+ ret = AVERROR(ENOMEM);
198+ goto end;
199+ }
200+
201+ if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
202+ buffersrc = avfilter_get_by_name("buffer");
203+ buffersink = avfilter_get_by_name("buffersink");
204+ if (!buffersrc || !buffersink) {
205+ av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
206+ ret = AVERROR_UNKNOWN;
207+ goto end;
208+ }
209+
210+ snprintf(args, sizeof(args),
211+ "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
212+ dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
213+ dec_ctx->time_base.num, dec_ctx->time_base.den,
214+ dec_ctx->sample_aspect_ratio.num,
215+ dec_ctx->sample_aspect_ratio.den);
216+
217+ ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
218+ args, NULL, filter_graph);
219+ if (ret < 0) {
220+ av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
221+ goto end;
222+ }
223+
224+ ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
225+ NULL, NULL, filter_graph);
226+ if (ret < 0) {
227+ av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
228+ goto end;
229+ }
230+
231+ ret = av_opt_set_bin(buffersink_ctx, "pix_fmts",
232+ (uint8_t*)&enc_ctx->pix_fmt, sizeof(enc_ctx->pix_fmt),
233+ AV_OPT_SEARCH_CHILDREN);
234+ if (ret < 0) {
235+ av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
236+ goto end;
237+ }
238+ } else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
239+ buffersrc = avfilter_get_by_name("abuffer");
240+ buffersink = avfilter_get_by_name("abuffersink");
241+ if (!buffersrc || !buffersink) {
242+ av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
243+ ret = AVERROR_UNKNOWN;
244+ goto end;
245+ }
246+
247+ if (!dec_ctx->channel_layout)
248+ dec_ctx->channel_layout =
249+ av_get_default_channel_layout(dec_ctx->channels);
250+ snprintf(args, sizeof(args),
251+ "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,
252+ dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate,
253+ av_get_sample_fmt_name(dec_ctx->sample_fmt),
254+ dec_ctx->channel_layout);
255+ ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
256+ args, NULL, filter_graph);
257+ if (ret < 0) {
258+ av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");
259+ goto end;
260+ }
261+
262+ ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
263+ NULL, NULL, filter_graph);
264+ if (ret < 0) {
265+ av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");
266+ goto end;
267+ }
268+
269+ ret = av_opt_set_bin(buffersink_ctx, "sample_fmts",
270+ (uint8_t*)&enc_ctx->sample_fmt, sizeof(enc_ctx->sample_fmt),
271+ AV_OPT_SEARCH_CHILDREN);
272+ if (ret < 0) {
273+ av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");
274+ goto end;
275+ }
276+
277+ ret = av_opt_set_bin(buffersink_ctx, "channel_layouts",
278+ (uint8_t*)&enc_ctx->channel_layout,
279+ sizeof(enc_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN);
280+ if (ret < 0) {
281+ av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");
282+ goto end;
283+ }
284+
285+ ret = av_opt_set_bin(buffersink_ctx, "sample_rates",
286+ (uint8_t*)&enc_ctx->sample_rate, sizeof(enc_ctx->sample_rate),
287+ AV_OPT_SEARCH_CHILDREN);
288+ if (ret < 0) {
289+ av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");
290+ goto end;
291+ }
292+ } else {
293+ ret = AVERROR_UNKNOWN;
294+ goto end;
295+ }
296+
297+ /* Endpoints for the filter graph. */
298+ outputs->name = av_strdup("in");
299+ outputs->filter_ctx = buffersrc_ctx;
300+ outputs->pad_idx = 0;
301+ outputs->next = NULL;
302+
303+ inputs->name = av_strdup("out");
304+ inputs->filter_ctx = buffersink_ctx;
305+ inputs->pad_idx = 0;
306+ inputs->next = NULL;
307+
308+ if (!outputs->name || !inputs->name) {
309+ ret = AVERROR(ENOMEM);
310+ goto end;
311+ }
312+
313+ if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_spec,
314+ &inputs, &outputs, NULL)) < 0)
315+ goto end;
316+
317+ if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
318+ goto end;
319+
320+ /* Fill FilteringContext */
321+ fctx->buffersrc_ctx = buffersrc_ctx;
322+ fctx->buffersink_ctx = buffersink_ctx;
323+ fctx->filter_graph = filter_graph;
324+
325+end:
326+ avfilter_inout_free(&inputs);
327+ avfilter_inout_free(&outputs);
328+
329+ return ret;
330+}
331+
332+static int init_filters(void)
333+{
334+ const char *filter_spec;
335+ unsigned int i;
336+ int ret;
337+ filter_ctx = av_malloc(sizeof(FilteringContext) * ifmt_ctx->nb_streams);
338+ if (!filter_ctx)
339+ return AVERROR(ENOMEM);
340+
341+ for (i = 0; i < ifmt_ctx->nb_streams; i++) {
342+ filter_ctx[i].buffersrc_ctx = NULL;
343+ filter_ctx[i].buffersink_ctx = NULL;
344+ filter_ctx[i].filter_graph = NULL;
345+ if (!(ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO
346+ || ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))
347+ continue;
348+
349+
350+ if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
351+ filter_spec = "null"; /* passthrough (dummy) filter for video */
352+ else
353+ filter_spec = "anull"; /* passthrough (dummy) filter for audio */
354+ ret = init_filter(&filter_ctx[i], ifmt_ctx->streams[i]->codec,
355+ ofmt_ctx->streams[i]->codec, filter_spec);
356+ if (ret)
357+ return ret;
358+ }
359+ return 0;
360+}
361+
362+static int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame) {
363+ int ret;
364+ int got_frame_local;
365+ AVPacket enc_pkt;
366+ int (*enc_func)(AVCodecContext *, AVPacket *, const AVFrame *, int *) =
367+ (ifmt_ctx->streams[stream_index]->codec->codec_type ==
368+ AVMEDIA_TYPE_VIDEO) ? avcodec_encode_video2 : avcodec_encode_audio2;
369+
370+ if (!got_frame)
371+ got_frame = &got_frame_local;
372+
373+ av_log(NULL, AV_LOG_INFO, "Encoding frame\n");
374+ /* encode filtered frame */
375+ enc_pkt.data = NULL;
376+ enc_pkt.size = 0;
377+ av_init_packet(&enc_pkt);
378+ ret = enc_func(ofmt_ctx->streams[stream_index]->codec, &enc_pkt,
379+ filt_frame, got_frame);
380+ av_frame_free(&filt_frame);
381+ if (ret < 0)
382+ return ret;
383+ if (!(*got_frame))
384+ return 0;
385+
386+ /* prepare packet for muxing */
387+ enc_pkt.stream_index = stream_index;
388+ enc_pkt.dts = av_rescale_q_rnd(enc_pkt.dts,
389+ ofmt_ctx->streams[stream_index]->codec->time_base,
390+ ofmt_ctx->streams[stream_index]->time_base,
391+ AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
392+ enc_pkt.pts = av_rescale_q_rnd(enc_pkt.pts,
393+ ofmt_ctx->streams[stream_index]->codec->time_base,
394+ ofmt_ctx->streams[stream_index]->time_base,
395+ AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
396+ enc_pkt.duration = av_rescale_q(enc_pkt.duration,
397+ ofmt_ctx->streams[stream_index]->codec->time_base,
398+ ofmt_ctx->streams[stream_index]->time_base);
399+
400+ av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");
401+ /* mux encoded frame */
402+ ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
403+ return ret;
404+}
405+
406+static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)
407+{
408+ int ret;
409+ AVFrame *filt_frame;
410+
411+ av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n");
412+ /* push the decoded frame into the filtergraph */
413+ ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx,
414+ frame, 0);
415+ if (ret < 0) {
416+ av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
417+ return ret;
418+ }
419+
420+ /* pull filtered frames from the filtergraph */
421+ while (1) {
422+ filt_frame = av_frame_alloc();
423+ if (!filt_frame) {
424+ ret = AVERROR(ENOMEM);
425+ break;
426+ }
427+ av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n");
428+ ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx,
429+ filt_frame);
430+ if (ret < 0) {
431+ /* if no more frames for output - returns AVERROR(EAGAIN)
432+ * if flushed and no more frames for output - returns AVERROR_EOF
433+ * rewrite retcode to 0 to show it as normal procedure completion
434+ */
435+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
436+ ret = 0;
437+ av_frame_free(&filt_frame);
438+ break;
439+ }
440+
441+ filt_frame->pict_type = AV_PICTURE_TYPE_NONE;
442+ ret = encode_write_frame(filt_frame, stream_index, NULL);
443+ if (ret < 0)
444+ break;
445+ }
446+
447+ return ret;
448+}
449+
450+static int flush_encoder(unsigned int stream_index)
451+{
452+ int ret;
453+ int got_frame;
454+
455+ if (!(ofmt_ctx->streams[stream_index]->codec->codec->capabilities &
456+ CODEC_CAP_DELAY))
457+ return 0;
458+
459+ while (1) {
460+ av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index);
461+ ret = encode_write_frame(NULL, stream_index, &got_frame);
462+ if (ret < 0)
463+ break;
464+ if (!got_frame)
465+ return 0;
466+ }
467+ return ret;
468+}
469+
470+int main(int argc, char **argv)
471+{
472+ int ret;
473+ AVPacket packet = { .data = NULL, .size = 0 };
474+ AVFrame *frame = NULL;
475+ enum AVMediaType type;
476+ unsigned int stream_index;
477+ unsigned int i;
478+ int got_frame;
479+ int (*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *);
480+
481+ if (argc != 3) {
482+ av_log(NULL, AV_LOG_ERROR, "Usage: %s <input file> <output file>\n", argv[0]);
483+ return 1;
484+ }
485+
486+ av_register_all();
487+ avfilter_register_all();
488+
489+ if ((ret = open_input_file(argv[1])) < 0)
490+ goto end;
491+ if ((ret = open_output_file(argv[2])) < 0)
492+ goto end;
493+ if ((ret = init_filters()) < 0)
494+ goto end;
495+
496+ /* read all packets */
497+ while (1) {
498+ if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)
499+ break;
500+ stream_index = packet.stream_index;
501+ type = ifmt_ctx->streams[packet.stream_index]->codec->codec_type;
502+ av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n",
503+ stream_index);
504+
505+ if (filter_ctx[stream_index].filter_graph) {
506+ av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n");
507+ frame = av_frame_alloc();
508+ if (!frame) {
509+ ret = AVERROR(ENOMEM);
510+ break;
511+ }
512+ packet.dts = av_rescale_q_rnd(packet.dts,
513+ ifmt_ctx->streams[stream_index]->time_base,
514+ ifmt_ctx->streams[stream_index]->codec->time_base,
515+ AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
516+ packet.pts = av_rescale_q_rnd(packet.pts,
517+ ifmt_ctx->streams[stream_index]->time_base,
518+ ifmt_ctx->streams[stream_index]->codec->time_base,
519+ AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
520+ dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 :
521+ avcodec_decode_audio4;
522+ ret = dec_func(ifmt_ctx->streams[stream_index]->codec, frame,
523+ &got_frame, &packet);
524+ if (ret < 0) {
525+ av_frame_free(&frame);
526+ av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");
527+ break;
528+ }
529+
530+ if (got_frame) {
531+ frame->pts = av_frame_get_best_effort_timestamp(frame);
532+ ret = filter_encode_write_frame(frame, stream_index);
533+ av_frame_free(&frame);
534+ if (ret < 0)
535+ goto end;
536+ } else {
537+ av_frame_free(&frame);
538+ }
539+ } else {
540+ /* remux this frame without reencoding */
541+ packet.dts = av_rescale_q_rnd(packet.dts,
542+ ifmt_ctx->streams[stream_index]->time_base,
543+ ofmt_ctx->streams[stream_index]->time_base,
544+ AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
545+ packet.pts = av_rescale_q_rnd(packet.pts,
546+ ifmt_ctx->streams[stream_index]->time_base,
547+ ofmt_ctx->streams[stream_index]->time_base,
548+ AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
549+
550+ ret = av_interleaved_write_frame(ofmt_ctx, &packet);
551+ if (ret < 0)
552+ goto end;
553+ }
554+ av_free_packet(&packet);
555+ }
556+
557+ /* flush filters and encoders */
558+ for (i = 0; i < ifmt_ctx->nb_streams; i++) {
559+ /* flush filter */
560+ if (!filter_ctx[i].filter_graph)
561+ continue;
562+ ret = filter_encode_write_frame(NULL, i);
563+ if (ret < 0) {
564+ av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n");
565+ goto end;
566+ }
567+
568+ /* flush encoder */
569+ ret = flush_encoder(i);
570+ if (ret < 0) {
571+ av_log(NULL, AV_LOG_ERROR, "Flushing encoder failed\n");
572+ goto end;
573+ }
574+ }
575+
576+ av_write_trailer(ofmt_ctx);
577+end:
578+ av_free_packet(&packet);
579+ av_frame_free(&frame);
580+ for (i = 0; i < ifmt_ctx->nb_streams; i++) {
581+ avcodec_close(ifmt_ctx->streams[i]->codec);
582+ if (ofmt_ctx && ofmt_ctx->nb_streams > i && ofmt_ctx->streams[i] && ofmt_ctx->streams[i]->codec)
583+ avcodec_close(ofmt_ctx->streams[i]->codec);
584+ if (filter_ctx && filter_ctx[i].filter_graph)
585+ avfilter_graph_free(&filter_ctx[i].filter_graph);
586+ }
587+ av_free(filter_ctx);
588+ avformat_close_input(&ifmt_ctx);
589+ if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
590+ avio_close(ofmt_ctx->pb);
591+ avformat_free_context(ofmt_ctx);
592+
593+ if (ret < 0)
594+ av_log(NULL, AV_LOG_ERROR, "Error occurred: %s\n", av_err2str(ret));
595+
596+ return ret ? 1 : 0;
597+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t