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