comparison src/impl/hoofbaby/codec/decoder.d @ 8:71ebad05f542

It seems to be successfully opening input files... Now to transcode!
author fraserofthenight
date Sun, 12 Jul 2009 03:49:39 -0700
parents 9fdfe4a64a13
children 05c88622db6b
comparison
equal deleted inserted replaced
7:9fdfe4a64a13 8:71ebad05f542
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 */ 14 */
15 15
16 module hoofbaby.codec.decoder; 16 module hoofbaby.codec.decoder;
17 17
18 import tango.io.Stdout;
18 import tango.stdc.stringz; 19 import tango.stdc.stringz;
19 20
20 import hoofbaby.codec.libav.avutil; 21 import hoofbaby.codec.libav.avutil;
21 import hoofbaby.codec.libav.avcodec; 22 import hoofbaby.codec.libav.avcodec;
22 import hoofbaby.codec.libav.avformat; 23 import hoofbaby.codec.libav.avformat;
23 24
24 class Decoder 25 class Decoder
25 { 26 {
27 private char[] file;
28
26 private AVFormatContext* formatContext; 29 private AVFormatContext* formatContext;
30 private bool fileOpen = false;
31
32 private AVStream* videoStream;
33 private AVCodec* videoCodec;
34 private AVCodecContext* videoContext;
35 private bool videoOpen = false;
36
37 private AVStream* audioStream;
38 private AVCodec* audioCodec;
39 private AVCodecContext* audioContext;
40 private bool audioOpen = false;
27 41
28 public this(char[] inFilename) 42 public this(char[] inFilename)
29 { 43 {
30 int ret; 44 int ret;
31 45
32 // Open file & find stream info 46 // Open file & find stream info
47 file = inFilename;
33 char* filename = toStringz(inFilename); 48 char* filename = toStringz(inFilename);
34 ret = av_open_input_file(&formatContext, filename, null, 0, null); 49 ret = av_open_input_file(&formatContext, filename, null, 0, null);
35 assert(ret == 0, "Could not open input file"); 50 assert(ret == 0, "Could not open input file");
51 fileOpen = true;
36 ret = av_find_stream_info(formatContext); 52 ret = av_find_stream_info(formatContext);
37 assert(ret >= 0, "Could not find stream info"); 53 assert(ret >= 0, "Could not find stream info");
38 dump_format(formatContext, 0, filename, false); 54 dump_format(formatContext, 0, filename, false);
55
56 // Find the first video stream (don't worry about the rest until a much later version)
57 for(int i = 0; i < formatContext.nb_streams; i++)
58 {
59 AVStream* str = formatContext.streams[i];
60 if(str !is null && str.codec.codec_type == CODEC_TYPE_VIDEO)
61 {
62 videoStream = str;
63 break;
64 }
65 }
66 assert(videoStream !is null, "Could not find video stream");
67 videoContext = videoStream.codec;
68 assert(videoContext !is null, "Null codec context from non-null stream");
69 videoCodec = avcodec_find_decoder(videoContext.codec_id);
70 assert(videoCodec !is null, "Unsupported video format");
71 ret = avcodec_open(videoContext, videoCodec);
72 assert(ret >= 0, "Could not open video decoder");
73 videoOpen = true;
74
75 // Find the first audio stream (NEXTVERSION deal with multiple audio streams)
76 for(int i = 0; i < formatContext.nb_streams; i++)
77 {
78 AVStream* str = formatContext.streams[i];
79 if(str !is null && str.codec.codec_type == CODEC_TYPE_AUDIO)
80 {
81 audioStream = str;
82 break;
83 }
84 }
85 assert(audioStream !is null, "Could not find audio stream");
86 audioContext = audioStream.codec;
87 assert(audioContext !is null, "Null codec context from non-null stream");
88 audioCodec = avcodec_find_decoder(audioContext.codec_id);
89 assert(audioCodec !is null, "Unsupported audio format");
90 ret = avcodec_open(audioContext, audioCodec);
91 assert(ret >= 0, "Could not open audio decoder");
92 audioOpen = true;
93
94 scope(failure) freeResources();
95 }
96
97 public ~this()
98 {
99 freeResources();
100 }
101
102 private void freeResources()
103 {
104 if(videoOpen) avcodec_close(videoContext);
105 if(audioOpen) avcodec_close(audioContext);
106 if(fileOpen) av_close_input_file(formatContext);
107 if(formatContext) av_free(formatContext);
39 } 108 }
40 } 109 }
41
42 /* int main(int argc, char *argv[])
43 {
44 AVFormatContext *pFormatCtx;
45 int i, videoStream;
46 AVCodecContext *pCodecCtx;
47 AVCodec *pCodec;
48 AVFrame *pFrame;
49 AVFrame *pFrameRGB;
50 AVPacket packet;
51 int frameFinished;
52 int numBytes;
53 uint8_t *buffer;
54
55 // Register all formats and codecs
56 av_register_all();
57
58 // Open video file
59 if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
60 return -1; // Couldn't open file
61
62 // Retrieve stream information
63 if(av_find_stream_info(pFormatCtx)<0)
64 return -1; // Couldn't find stream information
65
66 // Dump information about file onto standard error
67 dump_format(pFormatCtx, 0, argv[1], false);
68
69 // Find the first video stream
70 videoStream=-1;
71 for(i=0; i<pFormatCtx.nb_streams; i++)
72 if(pFormatCtx.streams[i].codec.codec_type==CODEC_TYPE_VIDEO)
73 {
74 videoStream=i;
75 break;
76 }
77 if(videoStream==-1)
78 return -1; // Didn't find a video stream
79
80 // Get a pointer to the codec context for the video stream
81 pCodecCtx=&pFormatCtx.streams[videoStream].codec;
82
83 // Find the decoder for the video stream
84 pCodec=avcodec_find_decoder(pCodecCtx.codec_id);
85 if(pCodec==NULL)
86 return -1; // Codec not found
87
88 // Open codec
89 if(avcodec_open(pCodecCtx, pCodec)<0)
90 return -1; // Could not open codec
91
92 // Hack to correct wrong frame rates that seem to be generated by some
93 // codecs
94 if(pCodecCtx.frame_rate>1000 && pCodecCtx.frame_rate_base==1)
95 pCodecCtx.frame_rate_base=1000;
96
97 // Allocate video frame
98 pFrame=avcodec_alloc_frame();
99
100 // Allocate an AVFrame structure
101 pFrameRGB=avcodec_alloc_frame();
102 if(pFrameRGB==NULL)
103 return -1;
104
105 // Determine required buffer size and allocate buffer
106 numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx.width,
107 pCodecCtx.height);
108 buffer=new uint8_t[numBytes];
109
110 // Assign appropriate parts of buffer to image planes in pFrameRGB
111 avpicture_fill(cast(AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
112 pCodecCtx.width, pCodecCtx.height);
113
114 // Read frames and save first five frames to disk
115 i=0;
116 while(av_read_frame(pFormatCtx, &packet)>=0)
117 {
118 // Is this a packet from the video stream?
119 if(packet.stream_index==videoStream)
120 {
121 // Decode video frame
122 avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
123 packet.data, packet.size);
124
125 // Did we get a video frame?
126 if(frameFinished)
127 {
128 // Convert the image from its native format to RGB
129 img_convert(cast(AVPicture *)pFrameRGB, PIX_FMT_RGB24,
130 cast(AVPicture*)pFrame, pCodecCtx.pix_fmt, pCodecCtx.width,
131 pCodecCtx.height);
132
133 // Save the frame to disk
134 if(++i<=5)
135 SaveFrame(pFrameRGB, pCodecCtx.width, pCodecCtx.height,
136 i);
137 }
138 }
139
140 // Free the packet that was allocated by av_read_frame
141 av_free_packet(&packet);
142 }
143
144 // Free the RGB image
145 delete buffer;
146 av_free(pFrameRGB);
147
148 // Free the YUV frame
149 av_free(pFrame);
150
151 // Close the codec
152 avcodec_close(pCodecCtx);
153
154 // Close the video file
155 av_close_input_file(pFormatCtx);
156
157 return 0;
158 } */