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"
13 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);
39 st
->link
= st
->sink
->inputs
[0];
43 int main(int argc
, char **argv
)
45 char *in_graph_desc
, **out_dev_name
;
46 int nb_out_dev
= 0, nb_streams
= 0;
47 AVFilterGraph
*in_graph
= NULL
;
48 Stream
*streams
= NULL
, *st
;
49 AVFrame
*frame
= NULL
;
50 int i
, j
, run
= 1, ret
;
52 //av_log_set_level(AV_LOG_DEBUG);
55 av_log(NULL
, AV_LOG_ERROR
,
56 "Usage: %s filter_graph dev:out [dev2:out2...]\n\n"
58 "%s movie=file.nut:s=v+a xv:- alsa:default\n"
59 "%s movie=file.nut:s=v+a uncodedframecrc:pipe:0\n",
60 argv
[0], argv
[0], argv
[0]);
63 in_graph_desc
= argv
[1];
64 out_dev_name
= argv
+ 2;
65 nb_out_dev
= argc
- 2;
68 avdevice_register_all();
69 avfilter_register_all();
71 /* Create input graph */
72 if (!(in_graph
= avfilter_graph_alloc())) {
73 ret
= AVERROR(ENOMEM
);
74 av_log(NULL
, AV_LOG_ERROR
, "Unable to alloc graph graph: %s\n",
78 ret
= avfilter_graph_parse_ptr(in_graph
, in_graph_desc
, NULL
, NULL
, NULL
);
80 av_log(NULL
, AV_LOG_ERROR
, "Unable to parse graph: %s\n",
85 for (i
= 0; i
< in_graph
->nb_filters
; i
++) {
86 AVFilterContext
*f
= in_graph
->filters
[i
];
87 for (j
= 0; j
< f
->nb_inputs
; j
++) {
89 av_log(NULL
, AV_LOG_ERROR
, "Graph has unconnected inputs\n");
90 ret
= AVERROR(EINVAL
);
94 for (j
= 0; j
< f
->nb_outputs
; j
++)
99 av_log(NULL
, AV_LOG_ERROR
, "Graph has no output stream\n");
100 ret
= AVERROR(EINVAL
);
103 if (nb_out_dev
!= 1 && nb_out_dev
!= nb_streams
) {
104 av_log(NULL
, AV_LOG_ERROR
,
105 "Graph has %d output streams, %d devices given\n",
106 nb_streams
, nb_out_dev
);
107 ret
= AVERROR(EINVAL
);
111 if (!(streams
= av_calloc(nb_streams
, sizeof(*streams
)))) {
112 ret
= AVERROR(ENOMEM
);
113 av_log(NULL
, AV_LOG_ERROR
, "Could not allocate streams\n");
116 for (i
= 0; i
< in_graph
->nb_filters
; i
++) {
117 AVFilterContext
*f
= in_graph
->filters
[i
];
118 for (j
= 0; j
< f
->nb_outputs
; j
++) {
119 if (!f
->outputs
[j
]) {
120 if ((ret
= create_sink(st
++, in_graph
, f
, j
)) < 0)
125 av_assert0(st
- streams
== nb_streams
);
126 if ((ret
= avfilter_graph_config(in_graph
, NULL
)) < 0) {
127 av_log(NULL
, AV_LOG_ERROR
, "Failed to configure graph\n");
131 /* Create output devices */
132 for (i
= 0; i
< nb_out_dev
; i
++) {
133 char *fmt
= NULL
, *dev
= out_dev_name
[i
];
135 if ((dev
= strchr(dev
, ':'))) {
137 fmt
= out_dev_name
[i
];
139 ret
= avformat_alloc_output_context2(&st
->mux
, NULL
, fmt
, dev
);
141 av_log(NULL
, AV_LOG_ERROR
, "Failed to allocate output: %s\n",
145 if (!(st
->mux
->oformat
->flags
& AVFMT_NOFILE
)) {
146 ret
= avio_open2(&st
->mux
->pb
, st
->mux
->filename
, AVIO_FLAG_WRITE
,
149 av_log(st
->mux
, AV_LOG_ERROR
, "Failed to init output: %s\n",
155 for (; i
< nb_streams
; i
++)
156 streams
[i
].mux
= streams
[0].mux
;
158 /* Create output device streams */
159 for (i
= 0; i
< nb_streams
; i
++) {
161 if (!(st
->stream
= avformat_new_stream(st
->mux
, NULL
))) {
162 ret
= AVERROR(ENOMEM
);
163 av_log(NULL
, AV_LOG_ERROR
, "Failed to create output stream\n");
166 st
->stream
->codec
->codec_type
= st
->link
->type
;
167 st
->stream
->time_base
= st
->stream
->codec
->time_base
=
169 switch (st
->link
->type
) {
170 case AVMEDIA_TYPE_VIDEO
:
171 st
->stream
->codec
->codec_id
= AV_CODEC_ID_RAWVIDEO
;
172 st
->stream
->avg_frame_rate
=
173 st
->stream
-> r_frame_rate
= av_buffersink_get_frame_rate(st
->sink
);
174 st
->stream
->codec
->width
= st
->link
->w
;
175 st
->stream
->codec
->height
= st
->link
->h
;
176 st
->stream
->codec
->sample_aspect_ratio
= st
->link
->sample_aspect_ratio
;
177 st
->stream
->codec
->pix_fmt
= st
->link
->format
;
179 case AVMEDIA_TYPE_AUDIO
:
180 st
->stream
->codec
->channel_layout
= st
->link
->channel_layout
;
181 st
->stream
->codec
->channels
= avfilter_link_get_channels(st
->link
);
182 st
->stream
->codec
->sample_rate
= st
->link
->sample_rate
;
183 st
->stream
->codec
->sample_fmt
= st
->link
->format
;
184 st
->stream
->codec
->codec_id
=
185 av_get_pcm_codec(st
->stream
->codec
->sample_fmt
, -1);
188 av_assert0(!"reached");
192 /* Init output devices */
193 for (i
= 0; i
< nb_out_dev
; i
++) {
195 if ((ret
= avformat_write_header(st
->mux
, NULL
)) < 0) {
196 av_log(st
->mux
, AV_LOG_ERROR
, "Failed to init output: %s\n",
202 /* Check output devices */
203 for (i
= 0; i
< nb_streams
; i
++) {
205 ret
= av_write_uncoded_frame_query(st
->mux
, st
->stream
->index
);
207 av_log(st
->mux
, AV_LOG_ERROR
,
208 "Uncoded frames not supported on stream #%d: %s\n",
215 ret
= avfilter_graph_request_oldest(in_graph
);
217 if (ret
== AVERROR_EOF
) {
220 av_log(NULL
, AV_LOG_ERROR
, "Error filtering: %s\n",
225 for (i
= 0; i
< nb_streams
; i
++) {
228 if (!frame
&& !(frame
= av_frame_alloc())) {
229 ret
= AVERROR(ENOMEM
);
230 av_log(NULL
, AV_LOG_ERROR
, "Could not allocate frame\n");
233 ret
= av_buffersink_get_frame_flags(st
->sink
, frame
,
234 AV_BUFFERSINK_FLAG_NO_REQUEST
);
236 if (ret
!= AVERROR(EAGAIN
) && ret
!= AVERROR_EOF
)
237 av_log(NULL
, AV_LOG_WARNING
, "Error in sink: %s\n",
241 if (frame
->pts
!= AV_NOPTS_VALUE
)
242 frame
->pts
= av_rescale_q(frame
->pts
,
243 st
->link
->time_base
,
244 st
->stream
->time_base
);
245 ret
= av_interleaved_write_uncoded_frame(st
->mux
,
250 av_log(st
->stream
->codec
, AV_LOG_ERROR
,
251 "Error writing frame: %s\n", av_err2str(ret
));
259 for (i
= 0; i
< nb_out_dev
; i
++) {
261 av_write_trailer(st
->mux
);
265 av_frame_free(&frame
);
266 avfilter_graph_free(&in_graph
);
268 for (i
= 0; i
< nb_out_dev
; i
++) {
272 avio_close(st
->mux
->pb
);
273 avformat_free_context(st
->mux
);