view src/impl/hoofbaby/codec/decoder.d @ 9:05c88622db6b default tip

- Adhoc transcoder now doesn't rely on Platinum - Moved the adhoc transcoder to the main source tree; it can be moved back into test once it's more stable
author fraserofthenight
date Tue, 14 Jul 2009 22:04:05 -0700
parents 71ebad05f542
children
line wrap: on
line source

/**
 * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
 * Copyright (C) 2009 Robert Fraser
 * 
 * This program is free software; you can redistribute it andor
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

module hoofbaby.codec.decoder;

import tango.io.Stdout;
import tango.stdc.stringz;

import hoofbaby.codec.libav.avutil;
import hoofbaby.codec.libav.avcodec;
import hoofbaby.codec.libav.avformat;

public final 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 video 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 audio 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);
	}
}