#include #include #include #include #include #include #include static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, char *filename) { FILE *f; int i; f = fopen(filename, "w"); fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); for(i=0; i < ysize; i++) fwrite(buf + i * wrap, 1, xsize, f); fclose(f); } static void ppm_save(unsigned char *buf, int wrap, int xsize, int ysize, char *filename) { FILE *f; int i; f = fopen(filename, "w"); fprintf(f,"P6\n%d %d\n%d\n", xsize, ysize, 255); for(i=0; i < ysize; i++) fwrite(buf + i * wrap, 3, xsize, f); fclose(f); } int main(int argc, char *argv[]) { const char *filename = argv[1]; AVFormatContext *fmt_ctx = NULL; int vid_stream = -1; AVCodecContext *codec_ctx = NULL; AVCodec *codec; AVFrame *frame; AVPacket packet; int bytes_decoded, got_picture; AVFrame *frame_rgb; int nbytes; uint8_t *buffer; struct SwsContext *sws_ctx; int timestamp = 0; av_register_all(); #if DEBUG av_log_set_level(AV_LOG_DEBUG); printf("file: %s\n", filename); #endif if (argc < 2) { fprintf(stderr, "usage: %s filename [timestamp]\n", argv[0]); exit(1); } if (avformat_open_input(&fmt_ctx, filename, NULL, NULL) != 0) exit(2); if (avformat_find_stream_info(fmt_ctx, NULL) < 0) exit(3); #if DEBUG av_dump_format(fmt_ctx, 0, filename, 0); #endif vid_stream = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if (vid_stream == -1) exit(4); codec_ctx = fmt_ctx->streams[vid_stream]->codec; timestamp = fmt_ctx->start_time==AV_NOPTS_VALUE ? 0:fmt_ctx->start_time; #if 1 if (argc == 3 && atoi(argv[2]) > 0) timestamp += atoi(argv[2]); #endif avformat_seek_file(fmt_ctx, -1, INT64_MIN, timestamp, INT64_MAX, 0); codec = avcodec_find_decoder(codec_ctx->codec_id); if (codec == NULL) { fprintf(stderr, "Failed to find decoder!\n"); exit(5); } #if DEBUG printf("has cap truncated: %d\n", codec->capabilities & CODEC_CAP_TRUNCATED); #endif #if 0 if (codec->capabilities & CODEC_CAP_TRUNCATED) codec_ctx->flags |= CODEC_FLAG_TRUNCATED; #endif if (avcodec_open2(codec_ctx, codec, NULL) < 0) { fprintf(stderr, "Failed to open codec!\n"); exit(6); } packet.data = NULL; do { if (packet.data != NULL) av_free_packet(&packet); if (av_read_frame(fmt_ctx, &packet) < 0) { fprintf(stderr, "Found no video stream packet!\n"); exit(30); } } while (packet.stream_index != vid_stream); frame = avcodec_alloc_frame(); do { #if DEBUG printf("packet.data: %p, packet.size: %d, packet.stream_index: %d\n", packet.data, packet.size, packet.stream_index); #endif bytes_decoded = avcodec_decode_video2(codec_ctx, frame, &got_picture, &packet); if (bytes_decoded < 0) { fprintf(stderr, "Error while decoding frame!\n"); exit(12); } #if DEBUG printf("bytes_decoded: %d, got_picture: %d\n", bytes_decoded, got_picture); #endif } while (got_picture == 0 && packet.size > 0); av_free_packet(&packet); if (got_picture == 0) exit(9); pgm_save(frame->data[0], frame->linesize[0], codec_ctx->width, codec_ctx->height, "foo.pgm"); #define CONVERT_TO_RGB 1 #if CONVERT_TO_RGB frame_rgb = avcodec_alloc_frame(); if (!frame_rgb) exit(9); nbytes = avpicture_get_size(PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height); buffer = calloc(nbytes, sizeof(uint8_t)); if (!buffer) exit(10); avpicture_fill((AVPicture *) frame_rgb, buffer, PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height); sws_ctx = sws_getCachedContext(NULL, codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL); sws_scale(sws_ctx, (const uint8_t *const *) frame->data, frame->linesize, 0, codec_ctx->height, frame_rgb->data, frame_rgb->linesize); ppm_save(frame_rgb->data[0], frame_rgb->linesize[0], codec_ctx->width, codec_ctx->height, "foo.ppm"); #endif free(buffer); av_free(frame_rgb); av_free(frame); avcodec_close(codec_ctx); #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0) avformat_close_input(&fmt_ctx); #else av_close_input_file(fmt_ctx); #endif return 0; }