changeset 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
files src/impl/hoofbaby/codec/decoder.d src/impl/hoofbaby/codec/encoder.d src/impl/hoofbaby/codec/libav/swscale.d src/test/hoofbaby/test/adhoc/transcode.d
diffstat 4 files changed, 114 insertions(+), 166 deletions(-) [+]
line wrap: on
line diff
--- a/src/impl/hoofbaby/codec/decoder.d	Sun Jul 12 03:04:27 2009 -0700
+++ b/src/impl/hoofbaby/codec/decoder.d	Sun Jul 12 03:49:39 2009 -0700
@@ -15,6 +15,7 @@
 
 module hoofbaby.codec.decoder;
 
+import tango.io.Stdout;
 import tango.stdc.stringz;
 
 import hoofbaby.codec.libav.avutil;
@@ -23,136 +24,86 @@
 
 class Decoder
 {
+	private char[] file;
+	
 	private AVFormatContext* formatContext;
+	private bool fileOpen = false;
+	
+	private AVStream* videoStream;
+	private AVCodec* videoCodec;
+	private AVCodecContext* videoContext;
+	private bool videoOpen = false;
+	
+	private AVStream* audioStream;
+	private AVCodec* audioCodec;
+	private AVCodecContext* audioContext;
+	private bool audioOpen = false;
 	
 	public this(char[] inFilename)
 	{
 		int ret;
 		
 		// Open file & find stream info
+		file = inFilename;
 		char* filename = toStringz(inFilename);
 		ret = av_open_input_file(&formatContext, filename, null, 0, null);
 		assert(ret == 0, "Could not open input file");
+		fileOpen = true;
 		ret = av_find_stream_info(formatContext);
 		assert(ret >= 0, "Could not find stream info");
 		dump_format(formatContext, 0, filename, false);
+		
+		// Find the first video stream (don't worry about the rest until a much later version)
+		for(int i = 0; i < formatContext.nb_streams; i++)
+		{
+			AVStream* str = formatContext.streams[i];
+			if(str !is null && str.codec.codec_type == CODEC_TYPE_VIDEO)
+			{
+				videoStream = str;
+				break;
+			}
+		}
+		assert(videoStream !is null, "Could not find video stream");
+		videoContext = videoStream.codec;
+		assert(videoContext !is null, "Null codec context from non-null stream");
+		videoCodec = avcodec_find_decoder(videoContext.codec_id);
+		assert(videoCodec !is null, "Unsupported video format");
+		ret = avcodec_open(videoContext, videoCodec);
+		assert(ret >= 0, "Could not open video decoder");
+		videoOpen = true;
+		
+		// Find the first audio stream  (NEXTVERSION deal with multiple audio streams)
+		for(int i = 0; i < formatContext.nb_streams; i++)
+		{
+			AVStream* str = formatContext.streams[i];
+			if(str !is null && str.codec.codec_type == CODEC_TYPE_AUDIO)
+			{
+				audioStream = str;
+				break;
+			}
+		}
+		assert(audioStream !is null, "Could not find audio stream");
+		audioContext = audioStream.codec;
+		assert(audioContext !is null, "Null codec context from non-null stream");
+		audioCodec = avcodec_find_decoder(audioContext.codec_id);
+		assert(audioCodec !is null, "Unsupported audio format");
+		ret = avcodec_open(audioContext, audioCodec);
+		assert(ret >= 0, "Could not open audio decoder");
+		audioOpen = true;
+		
+		scope(failure) freeResources();
+	}
+	
+	public ~this()
+	{
+		freeResources();
+	}
+	
+	private void freeResources()
+	{
+		if(videoOpen)     avcodec_close(videoContext);
+		if(audioOpen)     avcodec_close(audioContext);
+		if(fileOpen)      av_close_input_file(formatContext);
+		if(formatContext) av_free(formatContext);
 	}
 }
-
-/* int main(int argc, char *argv[])
-{
-    AVFormatContext *pFormatCtx;
-    int             i, videoStream;
-    AVCodecContext  *pCodecCtx;
-    AVCodec         *pCodec;
-    AVFrame         *pFrame; 
-    AVFrame         *pFrameRGB;
-    AVPacket        packet;
-    int             frameFinished;
-    int             numBytes;
-    uint8_t         *buffer;
-
-    // Register all formats and codecs
-    av_register_all();
-
-    // Open video file
-    if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
-        return -1; // Couldn't open file
-
-    // Retrieve stream information
-    if(av_find_stream_info(pFormatCtx)<0)
-        return -1; // Couldn't find stream information
-
-    // Dump information about file onto standard error
-    dump_format(pFormatCtx, 0, argv[1], false);
-
-    // Find the first video stream
-    videoStream=-1;
-    for(i=0; i<pFormatCtx.nb_streams; i++)
-        if(pFormatCtx.streams[i].codec.codec_type==CODEC_TYPE_VIDEO)
-        {
-            videoStream=i;
-            break;
-        }
-    if(videoStream==-1)
-        return -1; // Didn't find a video stream
-
-    // Get a pointer to the codec context for the video stream
-    pCodecCtx=&pFormatCtx.streams[videoStream].codec;
-
-    // Find the decoder for the video stream
-    pCodec=avcodec_find_decoder(pCodecCtx.codec_id);
-    if(pCodec==NULL)
-        return -1; // Codec not found
-
-    // Open codec
-    if(avcodec_open(pCodecCtx, pCodec)<0)
-        return -1; // Could not open codec
-
-    // Hack to correct wrong frame rates that seem to be generated by some 
-    // codecs
-    if(pCodecCtx.frame_rate>1000 && pCodecCtx.frame_rate_base==1)
-        pCodecCtx.frame_rate_base=1000;
-
-    // Allocate video frame
-    pFrame=avcodec_alloc_frame();
-
-    // Allocate an AVFrame structure
-    pFrameRGB=avcodec_alloc_frame();
-    if(pFrameRGB==NULL)
-        return -1;
-
-    // Determine required buffer size and allocate buffer
-    numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx.width,
-        pCodecCtx.height);
-    buffer=new uint8_t[numBytes];
-
-    // Assign appropriate parts of buffer to image planes in pFrameRGB
-    avpicture_fill(cast(AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
-        pCodecCtx.width, pCodecCtx.height);
-
-    // Read frames and save first five frames to disk
-    i=0;
-    while(av_read_frame(pFormatCtx, &packet)>=0)
-    {
-        // Is this a packet from the video stream?
-        if(packet.stream_index==videoStream)
-        {
-            // Decode video frame
-            avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, 
-                packet.data, packet.size);
-
-            // Did we get a video frame?
-            if(frameFinished)
-            {
-                // Convert the image from its native format to RGB
-                img_convert(cast(AVPicture *)pFrameRGB, PIX_FMT_RGB24, 
-                    cast(AVPicture*)pFrame, pCodecCtx.pix_fmt, pCodecCtx.width, 
-                    pCodecCtx.height);
-
-                // Save the frame to disk
-                if(++i<=5)
-                    SaveFrame(pFrameRGB, pCodecCtx.width, pCodecCtx.height, 
-                        i);
-            }
-        }
-
-        // Free the packet that was allocated by av_read_frame
-        av_free_packet(&packet);
-    }
-
-    // Free the RGB image
-    delete buffer;
-    av_free(pFrameRGB);
-
-    // Free the YUV frame
-    av_free(pFrame);
-
-    // Close the codec
-    avcodec_close(pCodecCtx);
-
-    // Close the video file
-    av_close_input_file(pFormatCtx);
-
-    return 0;
-} */
\ No newline at end of file
--- a/src/impl/hoofbaby/codec/encoder.d	Sun Jul 12 03:04:27 2009 -0700
+++ b/src/impl/hoofbaby/codec/encoder.d	Sun Jul 12 03:49:39 2009 -0700
@@ -25,20 +25,23 @@
 {
 	// TODO convert asserts to exceptions
 	
-	public const int OUTBUF_SIZE = 100000;
+	private const int OUTBUF_SIZE  = 1 << 19; // 512 KB... Hopefully that should be enough for one packet
 	
-	public AVOutputFormat* format;
-	public AVFormatContext* formatContext;
+	private AVOutputFormat* format;
+	private AVFormatContext* formatContext;
+	private bool fileOpen;
 	
-	public AVCodec* audioCodec;
-	public AVCodecContext* audioContext;
-	public AVStream* audioStream;
-	public char* audioOutbuf;
+	private AVCodec* audioCodec;
+	private AVCodecContext* audioContext;
+	private AVStream* audioStream;
+	private char* audioOutbuf;
+	private bool audioOpen = false;
 	
-	public AVCodec* videoCodec;
-	public AVCodecContext* videoContext;
-	public AVStream* videoStream;
-	public char* videoOutbuf;
+	private AVCodec* videoCodec;
+	private AVCodecContext* videoContext;
+	private AVStream* videoStream;
+	private char* videoOutbuf;
+	private bool videoOpen = false;
 	
 	public this(char[] filename)
 	{
@@ -60,7 +63,8 @@
 		
 		// TODO remove
 		ret = url_fopen(&formatContext.pb, toStringz(filename), URL_WRONLY) < 0;
-		assert(ret >= 0);
+		assert(ret >= 0, "Could not open output file");
+		fileOpen = true;
 		
 		AVFormatParameters params;
 		params.prealloced_context = 1;
@@ -100,6 +104,7 @@
 		videoContext.flags |= CODEC_FLAG_GLOBAL_HEADER;
 		ret = avcodec_open(videoContext, videoCodec);
 		assert(ret >= 0, "Could not open video codec");
+		videoOpen = true;
 		
 		videoOutbuf = cast(char*) av_malloc(OUTBUF_SIZE);
 		assert(videoOutbuf !is null, "Could not allocate video output buffer");
@@ -123,6 +128,7 @@
 		audioContext.flags |= CODEC_FLAG_GLOBAL_HEADER;
 		ret = avcodec_open(audioContext, audioCodec);
 		assert(ret >= 0, "Could not open audio codec");
+		audioOpen = true;
 		
 		audioOutbuf = cast(char*) av_malloc(OUTBUF_SIZE);
 		assert(audioOutbuf !is null, "Could not allocate audio output buffer");
@@ -185,6 +191,9 @@
 	
 	private void freeResources()
 	{
+		if(videoOpen)     avcodec_close(videoContext);
+		if(audioOpen)     avcodec_close(audioContext);
+		if(fileOpen)      url_fclose(formatContext.pb);
 		if(formatContext) av_free(formatContext);
 		if(audioOutbuf)   av_free(audioOutbuf);
 		if(videoOutbuf)   av_free(videoOutbuf);
--- a/src/impl/hoofbaby/codec/libav/swscale.d	Sun Jul 12 03:04:27 2009 -0700
+++ b/src/impl/hoofbaby/codec/libav/swscale.d	Sun Jul 12 03:49:39 2009 -0700
@@ -65,7 +65,7 @@
 	void sws_freeFilter(SwsFilter*);
 	SwsFilter* sws_getDefaultFilter(float, float, float, float, float, float, int);
 	void sws_freeVec(SwsVector*);
-	void sws_printVec2(SwsVector*, AVCLASS*, int);
+	void sws_printVec2(SwsVector*, AVClass*, int);
 	void sws_printVec(SwsVector*);
 	SwsVector* sws_cloneVec(SwsVector*);
 	void sws_shiftVec(SwsVector*, int);
--- a/src/test/hoofbaby/test/adhoc/transcode.d	Sun Jul 12 03:04:27 2009 -0700
+++ b/src/test/hoofbaby/test/adhoc/transcode.d	Sun Jul 12 03:49:39 2009 -0700
@@ -20,9 +20,21 @@
 import NONE_3 = hoofbaby.codec.libav.mingw;
 import hoofbaby.app.libs;
 
-import Math = tango.math.Math;
 import hoofbaby.codec.decoder;
 import hoofbaby.codec.encoder;
+
+
+public int main(char[][] args)
+{
+	initLibs();
+	scope Decoder dec = new Decoder("../../ref/testv-h264-vorbis-ass.mkv");
+	delete dec;
+	return 0;
+}
+
+/+ 
+
+import Math = tango.math.Math;
 import hoofbaby.codec.libav.avutil;
 import hoofbaby.codec.libav.avcodec;
 import hoofbaby.codec.libav.avformat;
@@ -40,26 +52,6 @@
 private double audioIncr = 2 * Math.PI * 110.0 / SAMPLE_RATE;
 private double audioIncr2 = 2 * Math.PI * 110.0 / SAMPLE_RATE / SAMPLE_RATE;
 
-private AVFrame* allocFrame(int pix_fmt, int width, int height)
-{
-	AVFrame* picture;
-	char* buf;
-	int size;
-
-	picture = avcodec_alloc_frame();
-	if(!picture)
-		return null;
-	size = avpicture_get_size(pix_fmt, width, height);
-	buf = cast(char*) av_malloc(size);
-	if(!buf)
-	{
-		av_free(picture);
-		return null;
-	}
-	avpicture_fill(cast(AVPicture*) picture, buf, pix_fmt, width, height);
-	return picture;
-}
-
 private AVFrame* generatePicture(AVFrame* pict, int width, int height)
 {
 	int x, y, i;
@@ -108,16 +100,11 @@
 public int main(char[][] args)
 {
 	initLibs();
-	scope Decoder dec = new Decoder("../../ref/testv-h264-vorbis-ass.mkv");
-	return 0;
-	
-	/+ 
-	initLibs();
 	scope Encoder enc = new Encoder("biff_happy.wmv");
 	AUDIO_FRAME_SIZE = enc.audioContext.frame_size;
-
+	
 	// Allocate a video frame and audio buffer to store stuff
-	AVFrame* frame = allocFrame(PIX_FMT_YUV420P, WIDTH, HEIGHT);
+	AVFrame* frame = avpicture_alloc(PIX_FMT_YUV420P, WIDTH, HEIGHT);
 	assert(frame !is null, "Could not allocate frame");
 	scope(exit) if(frame) av_free(frame);
 	short* samples = cast(short*) av_malloc(AUDIO_FRAME_SIZE * 2 * 2); // AUDIO_FRAME_SIZE * 2 * number of channels
@@ -127,14 +114,14 @@
 	// Write header
 	enc.writeHeader();
 	
-    while(true)
+	while(true)
 	{
 		double audio_pts = cast(double) enc.audioStream.pts.val * enc.audioStream.time_base.num / enc.audioStream.time_base.den;
 		double video_pts = cast(double) enc.videoStream.pts.val * enc.videoStream.time_base.num / enc.videoStream.time_base.den;
-
+	
 		if(audio_pts >= STREAM_DURATION && video_pts >= STREAM_DURATION)
 			break;
-
+	
 		// Write interleaved audio & video
 		if(audio_pts < video_pts)
 		{
@@ -157,9 +144,10 @@
 			frameCount++;
 		}
 	}
-    
-    // Write trailer
+	
+	// Write trailer
 	enc.writeTrailer();
 	
-	return 0; +/
-}
\ No newline at end of file
+	return 0;
+}
++/
\ No newline at end of file