# HG changeset patch # User fraserofthenight # Date 1247395779 25200 # Node ID 71ebad05f542d2839049d25212e2fdd1a946181a # Parent 9fdfe4a64a130f66fad2ab8d1a3b9b4016021bac It seems to be successfully opening input files... Now to transcode! diff -r 9fdfe4a64a13 -r 71ebad05f542 src/impl/hoofbaby/codec/decoder.d --- 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; i1000 && 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 diff -r 9fdfe4a64a13 -r 71ebad05f542 src/impl/hoofbaby/codec/encoder.d --- 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); diff -r 9fdfe4a64a13 -r 71ebad05f542 src/impl/hoofbaby/codec/libav/swscale.d --- 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); diff -r 9fdfe4a64a13 -r 71ebad05f542 src/test/hoofbaby/test/adhoc/transcode.d --- 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