ffmpeg test does something.
[dcpomatic.git] / ffmpeg / test.c
1 #include <libavcodec/avcodec.h>
2 #include <libavformat/avformat.h>
3 #include <libswscale/swscale.h>
4
5 char const video[] = "/home/carl/Films/A town called panic.divx";//Ghostbusters.avi";
6
7 static void
8 save_frame (AVFrame *frame, int width, int height, int N)
9 {
10         char filename[32];
11         
12         sprintf (filename, "frame%d.ppm", N);
13         FILE* file = fopen (filename, "wb");
14         if (file == NULL) {
15                 return;
16         }
17
18         fprintf (file, "P6\n%d %d\n255\n", width, height);
19
20         for (int y = 0; y < height; y++) {
21                 fwrite (frame->data[0] + y * frame->linesize[0], 1, width * 3, file);
22         }
23
24         fclose (file);
25 }
26
27 int
28 main (int argc, char* argv[])
29 {
30         av_register_all ();
31
32         AVFormatContext* format_context = NULL;
33         if (avformat_open_input (&format_context, video, NULL, NULL) != 0) {
34                 fprintf (stderr, "avformat_open_input failed.\n");
35                 return -1;
36         }
37
38         if (avformat_find_stream_info (format_context, NULL) < 0) {
39                 fprintf (stderr, "av_find_stream_info failed.\n");
40                 return -1;
41         }
42
43         av_dump_format (format_context, 0, video, 0);
44
45         int video_stream = -1;
46         for (uint32_t i = 0; i < format_context->nb_streams; ++i) {
47                 if (format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
48                         video_stream = i;
49                         break;
50                 }
51         }
52
53         AVCodecContext* codec_context = format_context->streams[video_stream]->codec;
54
55         AVCodec* codec = avcodec_find_decoder (codec_context->codec_id);
56         if (codec == NULL) {
57                 fprintf (stderr, "avcodec_find_decoder failed.\n");
58                 return -1;
59         }
60
61         if (avcodec_open2 (codec_context, codec, NULL) < 0) {
62                 fprintf (stderr, "avcodec_open failed.\n");
63                 return -1;
64         }
65
66         if (codec_context->time_base.num > 1000 && codec_context->time_base.den == 1) {
67                 codec_context->time_base.den = 1000;
68         }
69                 
70         AVFrame* frame = avcodec_alloc_frame ();
71
72         AVFrame* frame_RGB = avcodec_alloc_frame ();
73         if (frame_RGB == NULL) {
74                 fprintf (stderr, "avcodec_alloc_frame failed.\n");
75                 return -1;
76         }
77
78         int num_bytes = avpicture_get_size (PIX_FMT_RGB24, codec_context->width, codec_context->height);
79         uint8_t* buffer = (uint8_t *) malloc (num_bytes);
80
81         avpicture_fill ((AVPicture *) frame_RGB, buffer, PIX_FMT_RGB24, codec_context->width, codec_context->height);
82
83         int i = 0;
84         AVPacket packet;
85         while (av_read_frame (format_context, &packet) >= 0) {
86
87                 int frame_finished;
88
89                 if (packet.stream_index == video_stream) {
90                         avcodec_decode_video2 (codec_context, frame, &frame_finished, &packet);
91
92                         if (frame_finished) {
93                                 static struct SwsContext *img_convert_context;
94
95                                 if (img_convert_context == NULL) {
96                                         int w = codec_context->width;
97                                         int h = codec_context->height;
98                                         
99                                         img_convert_context = sws_getContext (
100                                                 w, h, 
101                                                 codec_context->pix_fmt, 
102                                                 w, h, PIX_FMT_RGB24, SWS_BICUBIC,
103                                                 NULL, NULL, NULL
104                                                 );
105                                         
106                                         if (img_convert_context == NULL) {
107                                                 fprintf (stderr, "sws_getContext failed.\n");
108                                                 return -1;
109                                         }
110                                 }
111                                 
112                                 sws_scale (
113                                         img_convert_context, frame->data, frame->linesize, 0, 
114                                         codec_context->height, frame_RGB->data, frame_RGB->linesize
115                                         );
116
117                                 ++i;
118                                 if (i > 100 && i < 150) {
119                                         save_frame (frame_RGB, codec_context->width, codec_context->height, i);
120                                 }
121                         }
122                 }
123
124                 av_free_packet (&packet);
125         }
126         
127         free (buffer);
128         av_free (frame_RGB);
129         av_free (frame);
130         avcodec_close(codec_context);
131         avformat_close_input (&format_context);
132         
133         return 0;       
134 }