00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00029 #define _XOPEN_SOURCE 600
00030 #include <unistd.h>
00031
00032 #include <libavcodec/avcodec.h>
00033 #include <libavformat/avformat.h>
00034 #include <libavfilter/avfiltergraph.h>
00035 #include <libavfilter/avcodec.h>
00036 #include <libavfilter/buffersink.h>
00037 #include <libavfilter/buffersrc.h>
00038
00039 const char *filter_descr = "scale=78:24";
00040
00041 static AVFormatContext *fmt_ctx;
00042 static AVCodecContext *dec_ctx;
00043 AVFilterContext *buffersink_ctx;
00044 AVFilterContext *buffersrc_ctx;
00045 AVFilterGraph *filter_graph;
00046 static int video_stream_index = -1;
00047 static int64_t last_pts = AV_NOPTS_VALUE;
00048
00049 static int open_input_file(const char *filename)
00050 {
00051 int ret;
00052 AVCodec *dec;
00053
00054 if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) {
00055 av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
00056 return ret;
00057 }
00058
00059 if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
00060 av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
00061 return ret;
00062 }
00063
00064
00065 ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);
00066 if (ret < 0) {
00067 av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file\n");
00068 return ret;
00069 }
00070 video_stream_index = ret;
00071 dec_ctx = fmt_ctx->streams[video_stream_index]->codec;
00072
00073
00074 if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
00075 av_log(NULL, AV_LOG_ERROR, "Cannot open video decoder\n");
00076 return ret;
00077 }
00078
00079 return 0;
00080 }
00081
00082 static int init_filters(const char *filters_descr)
00083 {
00084 char args[512];
00085 int ret;
00086 AVFilter *buffersrc = avfilter_get_by_name("buffer");
00087 AVFilter *buffersink = avfilter_get_by_name("ffbuffersink");
00088 AVFilterInOut *outputs = avfilter_inout_alloc();
00089 AVFilterInOut *inputs = avfilter_inout_alloc();
00090 enum PixelFormat pix_fmts[] = { PIX_FMT_GRAY8, PIX_FMT_NONE };
00091 AVBufferSinkParams *buffersink_params;
00092
00093 filter_graph = avfilter_graph_alloc();
00094
00095
00096 snprintf(args, sizeof(args),
00097 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
00098 dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
00099 dec_ctx->time_base.num, dec_ctx->time_base.den,
00100 dec_ctx->sample_aspect_ratio.num, dec_ctx->sample_aspect_ratio.den);
00101
00102 ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
00103 args, NULL, filter_graph);
00104 if (ret < 0) {
00105 av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
00106 return ret;
00107 }
00108
00109
00110 buffersink_params = av_buffersink_params_alloc();
00111 buffersink_params->pixel_fmts = pix_fmts;
00112 ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
00113 NULL, buffersink_params, filter_graph);
00114 av_free(buffersink_params);
00115 if (ret < 0) {
00116 av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
00117 return ret;
00118 }
00119
00120
00121 outputs->name = av_strdup("in");
00122 outputs->filter_ctx = buffersrc_ctx;
00123 outputs->pad_idx = 0;
00124 outputs->next = NULL;
00125
00126 inputs->name = av_strdup("out");
00127 inputs->filter_ctx = buffersink_ctx;
00128 inputs->pad_idx = 0;
00129 inputs->next = NULL;
00130
00131 if ((ret = avfilter_graph_parse(filter_graph, filters_descr,
00132 &inputs, &outputs, NULL)) < 0)
00133 return ret;
00134
00135 if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
00136 return ret;
00137 return 0;
00138 }
00139
00140 static void display_picref(AVFilterBufferRef *picref, AVRational time_base)
00141 {
00142 int x, y;
00143 uint8_t *p0, *p;
00144 int64_t delay;
00145
00146 if (picref->pts != AV_NOPTS_VALUE) {
00147 if (last_pts != AV_NOPTS_VALUE) {
00148
00149
00150 delay = av_rescale_q(picref->pts - last_pts,
00151 time_base, AV_TIME_BASE_Q);
00152 if (delay > 0 && delay < 1000000)
00153 usleep(delay);
00154 }
00155 last_pts = picref->pts;
00156 }
00157
00158
00159 p0 = picref->data[0];
00160 puts("\033c");
00161 for (y = 0; y < picref->video->h; y++) {
00162 p = p0;
00163 for (x = 0; x < picref->video->w; x++)
00164 putchar(" .-+#"[*(p++) / 52]);
00165 putchar('\n');
00166 p0 += picref->linesize[0];
00167 }
00168 fflush(stdout);
00169 }
00170
00171 int main(int argc, char **argv)
00172 {
00173 int ret;
00174 AVPacket packet;
00175 AVFrame frame;
00176 int got_frame;
00177
00178 if (argc != 2) {
00179 fprintf(stderr, "Usage: %s file\n", argv[0]);
00180 exit(1);
00181 }
00182
00183 avcodec_register_all();
00184 av_register_all();
00185 avfilter_register_all();
00186
00187 if ((ret = open_input_file(argv[1])) < 0)
00188 goto end;
00189 if ((ret = init_filters(filter_descr)) < 0)
00190 goto end;
00191
00192
00193 while (1) {
00194 AVFilterBufferRef *picref;
00195 if ((ret = av_read_frame(fmt_ctx, &packet)) < 0)
00196 break;
00197
00198 if (packet.stream_index == video_stream_index) {
00199 avcodec_get_frame_defaults(&frame);
00200 got_frame = 0;
00201 ret = avcodec_decode_video2(dec_ctx, &frame, &got_frame, &packet);
00202 if (ret < 0) {
00203 av_log(NULL, AV_LOG_ERROR, "Error decoding video\n");
00204 break;
00205 }
00206
00207 if (got_frame) {
00208 frame.pts = av_frame_get_best_effort_timestamp(&frame);
00209
00210
00211 if (av_buffersrc_add_frame(buffersrc_ctx, &frame, 0) < 0) {
00212 av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
00213 break;
00214 }
00215
00216
00217 while (1) {
00218 ret = av_buffersink_get_buffer_ref(buffersink_ctx, &picref, 0);
00219 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
00220 break;
00221 if (ret < 0)
00222 goto end;
00223
00224 if (picref) {
00225 display_picref(picref, buffersink_ctx->inputs[0]->time_base);
00226 avfilter_unref_bufferp(&picref);
00227 }
00228 }
00229 }
00230 }
00231 av_free_packet(&packet);
00232 }
00233 end:
00234 avfilter_graph_free(&filter_graph);
00235 if (dec_ctx)
00236 avcodec_close(dec_ctx);
00237 avformat_close_input(&fmt_ctx);
00238
00239 if (ret < 0 && ret != AVERROR_EOF) {
00240 char buf[1024];
00241 av_strerror(ret, buf, sizeof(buf));
00242 fprintf(stderr, "Error occurred: %s\n", buf);
00243 exit(1);
00244 }
00245
00246 exit(0);
00247 }