4 #include "libavutil/avassert.h"
5 #include "libavdevice/avdevice.h"
6 #include "libavfilter/avfilter.h"
7 #include "libavfilter/buffersink.h"
8 #include "libavformat/avformat.h"
9 #include "libavcodec/codec_id.h"
14 AVFilterContext
*sink
;
17 static int create_sink(Stream
*st
, AVFilterGraph
*graph
,
18 AVFilterContext
*f
, int idx
)
20 enum AVMediaType type
= avfilter_pad_get_type(f
->output_pads
, idx
);
21 const char *sink_name
;
25 case AVMEDIA_TYPE_VIDEO
: sink_name
= "buffersink"; break;
26 case AVMEDIA_TYPE_AUDIO
: sink_name
= "abuffersink"; break;
28 av_log(NULL
, AV_LOG_ERROR
, "Stream type not supported\n");
29 return AVERROR(EINVAL
);
31 ret
= avfilter_graph_create_filter(&st
->sink
,
32 avfilter_get_by_name(sink_name
),
33 NULL
, NULL
, NULL
, graph
);
36 ret
= avfilter_link(f
, idx
, st
->sink
, 0);
42 int main(int argc
, char **argv
)
44 char *in_graph_desc
, **out_dev_name
;
45 int nb_out_dev
= 0, nb_streams
= 0;
46 AVFilterGraph
*in_graph
= NULL
;
47 Stream
*streams
= NULL
, *st
;
48 AVFrame
*frame
= NULL
;
49 int i
, j
, run
= 1, ret
;
51 //av_log_set_level(AV_LOG_DEBUG);
54 av_log(NULL
, AV_LOG_ERROR
,
55 "Usage: %s filter_graph dev:out [dev2:out2...]\n\n"
57 "%s movie=file.nut:s=v+a xv:- alsa:default\n"
58 "%s movie=file.nut:s=v+a uncodedframecrc:pipe:0\n",
59 argv
[0], argv
[0], argv
[0]);
62 in_graph_desc
= argv
[1];
63 out_dev_name
= argv
+ 2;
64 nb_out_dev
= argc
- 2;
66 avdevice_register_all();
68 /* Create input graph */
69 if (!(in_graph
= avfilter_graph_alloc())) {
70 ret
= AVERROR(ENOMEM
);
71 av_log(NULL
, AV_LOG_ERROR
, "Unable to alloc graph graph: %s\n",
75 ret
= avfilter_graph_parse_ptr(in_graph
, in_graph_desc
, NULL
, NULL
, NULL
);
77 av_log(NULL
, AV_LOG_ERROR
, "Unable to parse graph: %s\n",
82 for (i
= 0; i
< in_graph
->nb_filters
; i
++) {
83 AVFilterContext
*f
= in_graph
->filters
[i
];
84 for (j
= 0; j
< f
->nb_inputs
; j
++) {
86 av_log(NULL
, AV_LOG_ERROR
, "Graph has unconnected inputs\n");
87 ret
= AVERROR(EINVAL
);
91 for (j
= 0; j
< f
->nb_outputs
; j
++)
96 av_log(NULL
, AV_LOG_ERROR
, "Graph has no output stream\n");
97 ret
= AVERROR(EINVAL
);
100 if (nb_out_dev
!= 1 && nb_out_dev
!= nb_streams
) {
101 av_log(NULL
, AV_LOG_ERROR
,
102 "Graph has %d output streams, %d devices given\n",
103 nb_streams
, nb_out_dev
);
104 ret
= AVERROR(EINVAL
);
108 if (!(streams
= av_calloc(nb_streams
, sizeof(*streams
)))) {
109 ret
= AVERROR(ENOMEM
);
110 av_log(NULL
, AV_LOG_ERROR
, "Could not allocate streams\n");
113 for (i
= 0; i
< in_graph
->nb_filters
; i
++) {
114 AVFilterContext
*f
= in_graph
->filters
[i
];
115 for (j
= 0; j
< f
->nb_outputs
; j
++) {
116 if (!f
->outputs
[j
]) {
117 if ((ret
= create_sink(st
++, in_graph
, f
, j
)) < 0)
122 av_assert0(st
- streams
== nb_streams
);
123 if ((ret
= avfilter_graph_config(in_graph
, NULL
)) < 0) {
124 av_log(NULL
, AV_LOG_ERROR
, "Failed to configure graph\n");
128 /* Create output devices */
129 for (i
= 0; i
< nb_out_dev
; i
++) {
130 char *fmt
= NULL
, *dev
= out_dev_name
[i
];
132 if ((dev
= strchr(dev
, ':'))) {
134 fmt
= out_dev_name
[i
];
136 ret
= avformat_alloc_output_context2(&st
->mux
, NULL
, fmt
, dev
);
138 av_log(NULL
, AV_LOG_ERROR
, "Failed to allocate output: %s\n",
142 if (!(st
->mux
->oformat
->flags
& AVFMT_NOFILE
)) {
143 ret
= avio_open2(&st
->mux
->pb
, st
->mux
->url
, AVIO_FLAG_WRITE
,
146 av_log(st
->mux
, AV_LOG_ERROR
, "Failed to init output: %s\n",
152 for (; i
< nb_streams
; i
++)
153 streams
[i
].mux
= streams
[0].mux
;
155 /* Create output device streams */
156 for (i
= 0; i
< nb_streams
; i
++) {
158 if (!(st
->stream
= avformat_new_stream(st
->mux
, NULL
))) {
159 ret
= AVERROR(ENOMEM
);
160 av_log(NULL
, AV_LOG_ERROR
, "Failed to create output stream\n");
163 st
->stream
->codecpar
->codec_type
= av_buffersink_get_type(st
->sink
);
164 st
->stream
->time_base
= av_buffersink_get_time_base(st
->sink
);
165 switch (av_buffersink_get_type(st
->sink
)) {
166 case AVMEDIA_TYPE_VIDEO
:
167 st
->stream
->codecpar
->codec_id
= AV_CODEC_ID_RAWVIDEO
;
168 st
->stream
->avg_frame_rate
=
169 st
->stream
-> r_frame_rate
= av_buffersink_get_frame_rate(st
->sink
);
170 st
->stream
->codecpar
->width
= av_buffersink_get_w(st
->sink
);
171 st
->stream
->codecpar
->height
= av_buffersink_get_h(st
->sink
);
172 st
->stream
->codecpar
->sample_aspect_ratio
= av_buffersink_get_sample_aspect_ratio(st
->sink
);
173 st
->stream
->codecpar
->format
= av_buffersink_get_format(st
->sink
);
175 case AVMEDIA_TYPE_AUDIO
:
176 ret
= av_buffersink_get_ch_layout(st
->sink
, &st
->stream
->codecpar
->ch_layout
);
179 st
->stream
->codecpar
->sample_rate
= av_buffersink_get_sample_rate(st
->sink
);
180 st
->stream
->codecpar
->format
= av_buffersink_get_format(st
->sink
);
181 st
->stream
->codecpar
->codec_id
= av_get_pcm_codec(st
->stream
->codecpar
->format
, -1);
184 av_assert0(!"reached");
188 /* Init output devices */
189 for (i
= 0; i
< nb_out_dev
; i
++) {
191 if ((ret
= avformat_write_header(st
->mux
, NULL
)) < 0) {
192 av_log(st
->mux
, AV_LOG_ERROR
, "Failed to init output: %s\n",
198 /* Check output devices */
199 for (i
= 0; i
< nb_streams
; i
++) {
201 ret
= av_write_uncoded_frame_query(st
->mux
, st
->stream
->index
);
203 av_log(st
->mux
, AV_LOG_ERROR
,
204 "Uncoded frames not supported on stream #%d: %s\n",
211 ret
= avfilter_graph_request_oldest(in_graph
);
213 if (ret
== AVERROR_EOF
) {
216 av_log(NULL
, AV_LOG_ERROR
, "Error filtering: %s\n",
221 for (i
= 0; i
< nb_streams
; i
++) {
224 if (!frame
&& !(frame
= av_frame_alloc())) {
225 ret
= AVERROR(ENOMEM
);
226 av_log(NULL
, AV_LOG_ERROR
, "Could not allocate frame\n");
229 ret
= av_buffersink_get_frame_flags(st
->sink
, frame
,
230 AV_BUFFERSINK_FLAG_NO_REQUEST
);
232 if (ret
!= AVERROR(EAGAIN
) && ret
!= AVERROR_EOF
)
233 av_log(NULL
, AV_LOG_WARNING
, "Error in sink: %s\n",
237 if (frame
->pts
!= AV_NOPTS_VALUE
)
238 frame
->pts
= av_rescale_q(frame
->pts
,
239 av_buffersink_get_time_base(st
->sink
),
240 st
->stream
->time_base
);
241 ret
= av_interleaved_write_uncoded_frame(st
->mux
,
246 av_log(st
->mux
, AV_LOG_ERROR
,
247 "Error writing frame: %s\n", av_err2str(ret
));
255 for (i
= 0; i
< nb_out_dev
; i
++) {
257 av_write_trailer(st
->mux
);
261 av_frame_free(&frame
);
262 avfilter_graph_free(&in_graph
);
264 for (i
= 0; i
< nb_out_dev
; i
++) {
268 avio_closep(&st
->mux
->pb
);
269 avformat_free_context(st
->mux
);