Don't ignore target init() failures, causes mod_libavcodec to crash synfig
[synfig.git] / synfig-core / trunk / src / modules / mod_libavcodec / trgt_av.cpp
index bb72d40..7ceec6e 100644 (file)
@@ -1,27 +1,28 @@
-/* === S I N F G =========================================================== */
+/* === S Y N F I G ========================================================= */
 /*!    \file trgt.cpp
 **     \brief \writeme
 **
 **     $Id: trgt_av.cpp,v 1.1.1.1 2005/01/04 01:23:11 darco Exp $
 **
 **     \legal
-**     Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
 **
-**     This software and associated documentation
-**     are CONFIDENTIAL and PROPRIETARY property of
-**     the above-mentioned copyright holder.
+**     This package is free software; you can redistribute it and/or
+**     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.
 **
-**     You may not copy, print, publish, or in any
-**     other way distribute this software without
-**     a prior written agreement with
-**     the copyright holder.
+**     This package 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.
 **     \endlegal
 */
 /* ========================================================================= */
 
 /* === H E A D E R S ======================================================= */
 
-#define SINFG_NO_ANGLE
+#define SYNFIG_NO_ANGLE
 
 #ifdef USING_PCH
 #      include "pch.h"
 
 extern "C"
 {
-#include "libavformat/avformat.h"
+#include <avformat.h>
 }
 
-#include <sinfg/general.h>
+#include <synfig/general.h>
 
 #include <cstdio>
 #include <algorithm>
@@ -50,17 +51,17 @@ extern "C"
 
 /* === U S I N G =========================================================== */
 
-using namespace sinfg;
+using namespace synfig;
 using namespace std;
 using namespace etl;
 
 /* === I N F O ============================================================= */
 
-SINFG_TARGET_INIT(Target_LibAVCodec);
-SINFG_TARGET_SET_NAME(Target_LibAVCodec,"libav");
-SINFG_TARGET_SET_EXT(Target_LibAVCodec,"avi");
-SINFG_TARGET_SET_VERSION(Target_LibAVCodec,"0.1");
-SINFG_TARGET_SET_CVS_ID(Target_LibAVCodec,"$Id: trgt_av.cpp,v 1.1.1.1 2005/01/04 01:23:11 darco Exp $");
+SYNFIG_TARGET_INIT(Target_LibAVCodec);
+SYNFIG_TARGET_SET_NAME(Target_LibAVCodec,"libav");
+SYNFIG_TARGET_SET_EXT(Target_LibAVCodec,"avi");
+SYNFIG_TARGET_SET_VERSION(Target_LibAVCodec,"0.1");
+SYNFIG_TARGET_SET_CVS_ID(Target_LibAVCodec,"$Id: trgt_av.cpp,v 1.1.1.1 2005/01/04 01:23:11 darco Exp $");
 
 /* === C L A S S E S & S T R U C T S ======================================= */
 
@@ -197,14 +198,14 @@ public:
                codec = avcodec_find_encoder(context->codec_id);
                if(!codec)
                {
-                       sinfg::warning("audio-open: could not find codec");
+                       synfig::warning("audio-open: could not find codec");
                        return 0;
                }
        
                //open the codec
                if(avcodec_open(context, codec) < 0)
                {
-                       sinfg::warning("audio-open: could not open codec");
+                       synfig::warning("audio-open: could not open codec");
                        return 0;
                }
        
@@ -259,7 +260,7 @@ public:
                //write the compressed audio to a file
                if(av_write_frame(formatc, stream->index, &audiobuffer[0], size) != 0)
                {
-                       sinfg::warning("audio-write_frame: unable to write the entire audio frame");
+                       synfig::warning("audio-write_frame: unable to write the entire audio frame");
                        return 0;
                }
                
@@ -297,7 +298,7 @@ public:
        {
                if(!formatc || !stream)
                {
-                       sinfg::warning("Attempt to open a video codec with a bad format or stream");
+                       synfig::warning("Attempt to open a video codec with a bad format or stream");
                        return false;
                }
                
@@ -306,20 +307,20 @@ public:
                AVCodecContext *context;
        
                //get from inside stream
-               context = &stream->codec;
+               context = stream->codec;
        
                //search for desired codec (contained in the stream)
                codec = avcodec_find_encoder(context->codec_id);
                if(!codec)
                {
-                       sinfg::warning("Open_video: could not find desired codec");
+                       synfig::warning("Open_video: could not find desired codec");
                        return 0;
                }
        
                //try to open the codec
                if(avcodec_open(context, codec) < 0) 
                {
-                       sinfg::warning("open_video: could not open desired codec");
+                       synfig::warning("open_video: could not open desired codec");
                        return 0;
                }
        
@@ -334,7 +335,7 @@ public:
                /*picture = alloc_picture(PIX_FMT_RGBA32, context->width, context->height);
                if(!picture)
                {
-                       sinfg::warning("open_video: could not allocate the picture to be encoded");
+                       synfig::warning("open_video: could not allocate the picture to be encoded");
                        return 0;
                }*/
        
@@ -354,7 +355,7 @@ public:
                        encodable = alloc_picture(context->pix_fmt, context->width, context->height);
                        if(!encodable) 
                        {
-                               sinfg::warning("open_video: could not allocate encodable picture");
+                               synfig::warning("open_video: could not allocate encodable picture");
                                return 0;
                        }
                }
@@ -367,13 +368,13 @@ public:
        {
                if(!formatc || !stream)
                {
-                       sinfg::warning("Attempt to open a video codec with a bad format or stream");
+                       synfig::warning("Attempt to open a video codec with a bad format or stream");
                        return false;
                }
                
                int                     size, 
                                                ret = 0;
-               AVCodecContext  *context = &stream->codec;
+               AVCodecContext  *context = stream->codec;
                
                /*
                If pict is invalid (NULL), then we are done compressing frames and we are trying to get
@@ -395,10 +396,20 @@ public:
                        pict = encodable;
                }
                
+               AVPacket pkt;
+               av_init_packet(&pkt);
+               pkt.stream_index = stream->index;
+               pkt.data = (uint8_t *)pict;
+               pkt.size = sizeof(AVPicture);
+               if( context->coded_frame )
+                       pkt.pts = context->coded_frame->pts;
+               if( context->coded_frame && context->coded_frame->key_frame)
+                       pkt.flags |= PKT_FLAG_KEY;
+               
                //cludge for raw picture format (they said they'd fix)
                if (formatc->oformat->flags & AVFMT_RAWPICTURE)
                {
-                       ret = av_write_frame(formatc, stream->index, (uint8_t *)pict, sizeof(AVPicture));
+                       ret = av_write_frame(formatc, &pkt);
                }
                else 
                {
@@ -408,12 +419,21 @@ public:
                        //if not zero we've got stuff to write
                        if (size != 0)
                        {
-                               ret = av_write_frame(formatc, stream->index, &videobuffer[0], size);
+                               av_init_packet(&pkt);
+                               pkt.stream_index = stream->index;
+                               pkt.data = &videobuffer[0];
+                               pkt.size = size;
+                               if( context->coded_frame )
+                                       pkt.pts = context->coded_frame->pts;
+                               if( context->coded_frame && context->coded_frame->key_frame)
+                                       pkt.flags |= PKT_FLAG_KEY;
+
+                               ret = av_write_frame(formatc, &pkt);
                                
                                //error detect - possibly throw later...
                                if(ret != 0)
                                {
-                                       sinfg::warning("write_frame: error while writing video frame");
+                                       synfig::warning("write_frame: error while writing video frame");
                                        return false;                                   
                                }
                        }
@@ -437,7 +457,7 @@ public:
        void close(AVFormatContext *formatc, AVStream *stream)
        {
                if(stream)
-                       avcodec_close(&stream->codec);
+                       avcodec_close(stream->codec);
                
                if (encodable) 
                {
@@ -519,13 +539,13 @@ public:
                
                if(!format)
                {
-                       sinfg::warning("Unable to Guess the output, defaulting to mpeg");
+                       synfig::warning("Unable to Guess the output, defaulting to mpeg");
                        format = guess_format("mpeg", NULL, NULL);
                }
                
                if(!format) 
                {
-                       sinfg::warning("Unable to find output format");
+                       synfig::warning("Unable to find output format");
                        return 0;
                }
                
@@ -533,7 +553,7 @@ public:
                formatc = (AVFormatContext *)av_mallocz(sizeof(AVFormatContext));
                if(!formatc)
                {
-                       sinfg::warning("Memory error\n");
+                       synfig::warning("Memory error\n");
                        return 0;
                }
                //set the output format to the one we found
@@ -566,15 +586,16 @@ public:
                
                AVFormatParameters      fmtparam,*ap = &fmtparam;
                memset(ap, 0, sizeof(*ap));
-               ap->frame_rate = vInfo.fps;
-               ap->frame_rate_base = 1;
+               // FIXME: Port next two lines to recent libavcodec versions
+               //ap->frame_rate = vInfo.fps;
+               //ap->frame_rate_base = 1;
                ap->width = vInfo.w;
                ap->height = vInfo.h;
                //ap->pix_fmt = frame_pix_fmt;
                
                if(av_set_parameters(formatc, ap) < 0)
                {
-                       sinfg::warning("Invalid output formatting parameters");
+                       synfig::warning("Invalid output formatting parameters");
                        return 0;
                }
        
@@ -586,7 +607,7 @@ public:
                {
                        if(!vid.open(formatc, video_st))
                        {
-                               sinfg::warning("Could not open video encoder");
+                               synfig::warning("Could not open video encoder");
                                return 0;
                        }
                }
@@ -594,7 +615,7 @@ public:
                {
                        if(!aud.open(formatc, audio_st))
                        {
-                               sinfg::warning("Could not open audio encoder");
+                               synfig::warning("Could not open audio encoder");
                                return 0;
                        }                       
                }*/
@@ -605,7 +626,7 @@ public:
                        //use libav's file open function (what does it do differently????)
                        if(url_fopen(&formatc->pb, filename, URL_WRONLY) < 0)
                        {
-                               sinfg::warning("Unable to open file: %s", filename);
+                               synfig::warning("Unable to open file: %s", filename);
                                return 0;
                        }
                }
@@ -615,7 +636,7 @@ public:
                picture = alloc_picture(PIX_FMT_RGB24,vInfo.w,vInfo.h);//video_st->codec.width, video_st->codec.height);
                if(!picture)
                {
-                       sinfg::warning("Unable to allocate the temporary AVFrame surface");
+                       synfig::warning("Unable to allocate the temporary AVFrame surface");
                        return 0;
                }
                
@@ -695,11 +716,11 @@ public:
                st = av_new_stream(formatc, 0);
                if(!st)
                {
-                       sinfg::warning("video-add_stream: Unable to allocate stream");
+                       synfig::warning("video-add_stream: Unable to allocate stream");
                        return 0;
                }
                
-               context = &st->codec;
+               context = st->codec;
                context->codec_id = (CodecID)codec_id;
                context->codec_type = CODEC_TYPE_VIDEO;
        
@@ -713,8 +734,9 @@ public:
                context->bit_rate = info.bitrate; //TODO: Make dependant on the quality
                
                /* frames per second */
-               context->frame_rate = info.fps;
-               context->frame_rate_base = 1;
+               // FIXME: Port next two lines to recent libavcodec versions
+               //context->frame_rate = info.fps;
+               //context->frame_rate_base = 1;
                
                /* "High Quality" */
                context->mb_decision=FF_MB_DECISION_BITS;
@@ -741,11 +763,11 @@ public:
                stream = av_new_stream(formatc, 1);
                if(!stream)
                {
-                       sinfg::warning("could not alloc stream");
+                       synfig::warning("could not alloc stream");
                        return 0;
                }
        
-               context = &stream->codec;
+               context = stream->codec;
                context->codec_id = (CodecID)codec_id;  
                context->codec_type = CODEC_TYPE_AUDIO;
        
@@ -874,7 +896,7 @@ Target_LibAVCodec::end_frame()
        //encode the frame and write it to the file
        if(!data->vid.write_frame(formatc,video_st,data->picture))
        {
-               sinfg::warning("Unable to write a frame");
+               synfig::warning("Unable to write a frame");
        }
        
        data->frame_count++;
@@ -893,7 +915,7 @@ Target_LibAVCodec::end_frame()
 }
 
 bool
-Target_LibAVCodec::start_frame(sinfg::ProgressCallback *callback)
+Target_LibAVCodec::start_frame(synfig::ProgressCallback *callback)
 {      
        //prepare all the color buffer stuff, etc.
        
@@ -920,7 +942,7 @@ bool Target_LibAVCodec::init()
        //hardcode test for mpeg
        if(!data->Initialize(filename.c_str(),NULL))
        {
-               sinfg::warning("Unable to Initialize the audio video encoders");
+               synfig::warning("Unable to Initialize the audio video encoders");
                return 0;
        }