--- /dev/null
+/* === S Y N F I G ========================================================= */
+/*! \file trgt_av.cpp
+** \brief \writeme
+**
+** $Id$
+**
+** \legal
+** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**
+** 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.
+**
+** 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 SYNFIG_NO_ANGLE
+
+#ifdef USING_PCH
+# include "pch.h"
+#else
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "trgt_av.h"
+
+extern "C"
+{
+#include <avformat.h>
+}
+
+#include <synfig/general.h>
+
+#include <cstdio>
+#include <algorithm>
+#include <functional>
+#endif
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+/* === U S I N G =========================================================== */
+
+using namespace synfig;
+using namespace std;
+using namespace etl;
+
+/* === I N F O ============================================================= */
+
+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$");
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+bool Target_LibAVCodec::registered = false;
+
+//for now compilation
+//float STREAM_DURATION = 5.0f;
+
+struct VideoInfo
+{
+ int w,h;
+ int fps;
+
+ int bitrate;
+};
+
+struct AudioInfo
+{
+ int samplerate; //in HZ
+ int samplesize; //in bytes
+};
+
+AVFrame *alloc_picture(int pix_fmt, int width, int height)
+{
+ AVFrame *picture;
+ uint8_t *picture_buf;
+ int size;
+
+ picture = avcodec_alloc_frame();
+ if (!picture)
+ return NULL;
+ size = avpicture_get_size(pix_fmt, width, height);
+ picture_buf = (uint8_t *)malloc(size);
+ if (!picture_buf) {
+ av_free(picture);
+ return NULL;
+ }
+ avpicture_fill((AVPicture *)picture, picture_buf,
+ pix_fmt, width, height);
+ return picture;
+}
+
+void free_picture(AVFrame *pic)
+{
+ av_free(pic->data[0]);
+ av_free(pic);
+}
+
+//the frame must be RGB24
+static void convert_surface_frame(AVFrame *pic, const Surface &s, const Gamma &gamma)
+{
+ unsigned int j;
+ Surface::const_pen p = s.begin();
+ unsigned int w,h;
+ Color c;
+
+ uint8_t *ptr;
+ int stride;
+
+ w = s.size().x;
+ h = s.size().y;
+
+ ptr = pic->data[0];
+ stride = pic->linesize[0];
+
+ for(j = 0; j < h; j++, p.inc_y(), ptr += stride)
+ {
+ uint8_t *tptr = ptr;
+
+ //use convert_color_format instead...
+ #if 0
+ const int channels = 3;
+
+ for(int i = 0; i < w; i++, p.inc_x(), tptr += channels)
+ {
+ c = p.get_value();
+
+ Color::value_type r = c.get_r();
+ Color::value_type g = c.get_g();
+ Color::value_type b = c.get_b();
+ Color::value_type a = c.get_a();
+
+ //premultiply alpha
+ r *= a;
+ g *= a;
+ b *= a;
+
+ //essentially treats it as if it has a background color of black
+
+ //we must also clamp the rgb values [0,1]
+ r = min(1.0f,r);
+ g = min(1.0f,g);
+ b = min(1.0f,b);
+
+ r = max(0.0f,r);
+ g = max(0.0f,g);
+ b = max(0.0f,b);
+
+ //now scale to range of char [0,255]
+ tptr[0] = (int)(r*255);
+ tptr[1] = (int)(g*255);
+ tptr[2] = (int)(b*255);
+ }
+
+ p.dec_x(w);
+ #else
+
+ convert_color_format((unsigned char *)tptr,&p.get_value(),w,PF_RGB,gamma);
+
+ #endif
+ }
+}
+
+//Audio Streamer (abstracts the open, write and close operations for audio streams)
+#if 0
+class AudioEncoder
+{
+public:
+
+ void *samples;
+
+ vector<unsigned char>audiobuffer;
+
+ int audio_input_frame_size;
+
+ bool open(AVFormatContext *formatc, AVStream *stream)
+ {
+ AVCodecContext *context;
+ AVCodec *codec;
+
+ context = &stream->codec;
+
+ //find audio encoder
+ codec = avcodec_find_encoder(context->codec_id);
+ if(!codec)
+ {
+ synfig::warning("audio-open: could not find codec");
+ return 0;
+ }
+
+ //open the codec
+ if(avcodec_open(context, codec) < 0)
+ {
+ synfig::warning("audio-open: could not open codec");
+ return 0;
+ }
+
+ /* hardcoded example for generating samples array*/
+ /*
+ t = 0;
+ tincr = 2 * M_PI * 110.0 / c->sample_rate;
+ tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;*/
+
+ audiobuffer.resize(10000);
+
+ /* ugly hack for PCM codecs (will be removed ASAP with new PCM
+ support to compute the input frame size in samples */
+ if (context->frame_size <= 1) {
+ audio_input_frame_size = audiobuffer.size() / context->channels;
+ switch(stream->codec.codec_id) {
+ case CODEC_ID_PCM_S16LE:
+ case CODEC_ID_PCM_S16BE:
+ case CODEC_ID_PCM_U16LE:
+ case CODEC_ID_PCM_U16BE:
+ audio_input_frame_size >>= 1;
+ break;
+ default:
+ break;
+ }
+ } else {
+ audio_input_frame_size = context->frame_size;
+ }
+
+ //hardcoded array
+ //samples = (int16_t *)malloc(audio_input_frame_size * 2 * c->channels);
+
+ return true;
+ }
+
+ bool write_frame(AVFormatContext *formatc, AVStream *stream, void *samples)
+ {
+ int size;
+ AVCodecContext *context;
+
+ context = &stream->codec;
+
+ //hardcoded in example
+ //must read in from somewhere...
+ //get_audio_frame(samples, audio_input_frame_size, c->channels);
+
+ //encode the audio
+ const short int*samps=(const short int *)samples; //assuming it's set from somewhere right now
+
+ size = avcodec_encode_audio(context, &audiobuffer[0], audiobuffer.size(), samps);
+
+ //write the compressed audio to a file
+ if(av_write_frame(formatc, stream->index, &audiobuffer[0], size) != 0)
+ {
+ synfig::warning("audio-write_frame: unable to write the entire audio frame");
+ return 0;
+ }
+
+ return true;
+ }
+
+ void close(AVFormatContext *formatc, AVStream *stream)
+ {
+ //we may also want to catch delayed frames from here (don't for now)
+
+ if(stream)
+ {
+ avcodec_close(&stream->codec);
+ }
+
+ //if(samples)av_free(samples);
+ audiobuffer.resize(0);
+ }
+};
+
+#endif
+
+class VideoEncoder
+{
+public:
+ AVFrame *encodable; //for compression and output to a file (in compatible pixel format)
+
+ vector<unsigned char> videobuffer;
+
+ bool startedencoding;
+
+ //int stream_nb_frames;
+
+ bool open(AVFormatContext *formatc, AVStream *stream)
+ {
+ if(!formatc || !stream)
+ {
+ synfig::warning("Attempt to open a video codec with a bad format or stream");
+ return false;
+ }
+
+ //codec and context
+ AVCodec *codec;
+ AVCodecContext *context;
+
+ //get from inside stream
+ context = stream->codec;
+
+ //search for desired codec (contained in the stream)
+ codec = avcodec_find_encoder(context->codec_id);
+ if(!codec)
+ {
+ synfig::warning("Open_video: could not find desired codec");
+ return 0;
+ }
+
+ //try to open the codec
+ if(avcodec_open(context, codec) < 0)
+ {
+ synfig::warning("open_video: could not open desired codec");
+ return 0;
+ }
+
+ videobuffer.resize(0);
+ if(!(formatc->oformat->flags & AVFMT_RAWPICTURE))
+ {
+ //resize buffer to desired buffersize
+ videobuffer.resize(200000); //TODO: need to figure out a good size
+ }
+
+ //allocate the base picture which will be used to encode
+ /*picture = alloc_picture(PIX_FMT_RGBA32, context->width, context->height);
+ if(!picture)
+ {
+ synfig::warning("open_video: could not allocate the picture to be encoded");
+ return 0;
+ }*/
+
+ //if our output (rgb) needs to be translated to a different coordinate system, need a temporary picture in that color space
+
+ /* Should use defaults of RGB
+ Possible formats:
+ PIX_FMT_RGB24
+ PIX_FMT_BGR24
+ PIX_FMT_RGBA32 //stored in cpu endianness (!!!!)
+
+ (possibly translate directly to required coordinate systems later on... less error)
+ */
+ encodable = NULL;
+ if(context->pix_fmt != PIX_FMT_RGB24)
+ {
+ encodable = alloc_picture(context->pix_fmt, context->width, context->height);
+ if(!encodable)
+ {
+ synfig::warning("open_video: could not allocate encodable picture");
+ return 0;
+ }
+ }
+
+ return true;
+ }
+
+ //write a frame with the frame passed in
+ bool write_frame(AVFormatContext *formatc, AVStream *stream, AVFrame *pict)
+ {
+ if(!formatc || !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;
+
+ /*
+ If pict is invalid (NULL), then we are done compressing frames and we are trying to get
+ the buffer cleared out (or if it's already in the right format) so no transform necessary
+ */
+ if ( pict )
+ {
+ startedencoding = true;
+ }
+
+
+ if ( pict && context->pix_fmt != PIX_FMT_RGB24 )
+ {
+ //We're using RGBA at the moment, write custom conversion code later (get less accuracy errors)
+ img_convert((AVPicture *)encodable, context->pix_fmt,
+ (AVPicture *)pict, PIX_FMT_RGB24,
+ context->width, context->height);
+
+ 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;
+
+ //kluge for raw picture format (they said they'd fix)
+ if (formatc->oformat->flags & AVFMT_RAWPICTURE)
+ {
+ ret = av_write_frame(formatc, &pkt);
+ }
+ else
+ {
+ //encode our given image
+ size = avcodec_encode_video(context, &videobuffer[0], videobuffer.size(), pict);
+
+ //if greater than zero we've got stuff to write
+ if (size > 0)
+ {
+ 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)
+ {
+ synfig::warning("write_frame: error while writing video frame");
+ return false;
+ }
+ }
+ //if 0, it was buffered (if invalid picture we don't have ANY data left)
+ else
+ {
+ //if we're clearing the buffers and there was no stuff to be written, we're done (like in codec example)
+ if(pict == NULL)
+ {
+ return false;
+ startedencoding = false;
+ }
+
+ //buffered picture
+ }
+ }
+
+ return true;
+ }
+
+ void close(AVFormatContext */*formatc*/, AVStream *stream)
+ {
+ if(stream)
+ avcodec_close(stream->codec);
+
+ if (encodable)
+ {
+ free_picture(encodable);
+ encodable = 0;
+ }
+
+ videobuffer.resize(0);
+ }
+};
+
+class Target_LibAVCodec::LibAVEncoder
+{
+public:
+
+ bool initialized;
+
+ AVOutputFormat *format; //reference to global, do not delete
+
+ AVFormatContext *formatc;
+
+ AVStream *video_st;
+ //AVStream *audio_st;
+
+ double video_pts;
+ //double audio_pts;
+
+ VideoEncoder vid;
+ VideoInfo vInfo;
+
+ /*AudioEncoder aud;
+ AudioInfo aInfo;*/
+
+ AVFrame *picture; //for encoding to RGB24 (perhaps RGBA later)
+
+ int frame_count;
+ int num_frames;
+
+ LibAVEncoder()
+ {
+ format = 0;
+ formatc = 0;
+
+ //video settings
+ video_st = 0;
+ video_pts = 0;
+
+ vid.encodable = 0;
+ //vid.stream_nb_frames = 2; //reasonable default
+
+ initialized = false;
+ picture = 0;
+
+ frame_count = 0;
+ num_frames = 0;
+
+ //aud.samples = 0;
+ //audio_st = 0;
+ //audio_pts = 0;
+ }
+
+ ~LibAVEncoder()
+ {
+ CleanUp();
+ }
+
+ bool Initialize(const char *filename, const char *typestring)
+ {
+ //guess if we have a type string, otherwise use filename
+ if (typestring)
+ {
+ //formatptr guess_format(type, filename, MIME type)
+ format = guess_format(typestring,NULL,NULL);
+ }
+ else
+ {
+ format = guess_format(NULL, filename, NULL);
+ }
+
+ if(!format)
+ {
+ synfig::warning("Unable to Guess the output, defaulting to mpeg");
+ format = guess_format("mpeg", NULL, NULL);
+ }
+
+ if(!format)
+ {
+ synfig::warning("Unable to find output format");
+ return 0;
+ }
+
+ //allocate the output context
+ formatc = (AVFormatContext *)av_mallocz(sizeof(AVFormatContext));
+ if(!formatc)
+ {
+ synfig::warning("Memory error\n");
+ return 0;
+ }
+ //set the output format to the one we found
+ formatc->oformat = format;
+
+ //print the output filename
+ snprintf(formatc->filename, sizeof(formatc->filename), "%s", filename);
+
+ //initial
+ video_st = NULL;
+ //audio_st = NULL;
+
+ //video stream
+ if(format->video_codec != CODEC_ID_NONE)
+ {
+ video_st = add_video_stream(format->video_codec,vInfo);
+ if(!video_st)
+ {
+ av_free(formatc);
+ }
+ }
+
+ //audio stream
+ /*if(format->audio_codec != CODEC_ID_NONE)
+ {
+ audio_st = add_audio_stream(format->audio_codec,aInfo);
+ }*/
+
+ //set output parameters: required in ALL cases
+
+ video_st->codec->time_base= (AVRational){1,vInfo.fps};
+ video_st->codec->width = vInfo.w;
+ video_st->codec->height = vInfo.h;
+ video_st->codec->pix_fmt = PIX_FMT_YUV420P;
+
+ //dump the formatting information as the file header
+ dump_format(formatc, 0, filename, 1);
+
+ //open codecs and allocate buffers
+ if(video_st)
+ {
+ if(!vid.open(formatc, video_st))
+ {
+ synfig::warning("Could not open video encoder");
+ return 0;
+ }
+ }
+ /*if(audio_st)
+ {
+ if(!aud.open(formatc, audio_st))
+ {
+ synfig::warning("Could not open audio encoder");
+ return 0;
+ }
+ }*/
+
+ //open output file
+ if(!(format->flags & AVFMT_NOFILE))
+ {
+ //use libav's file open function (what does it do differently????)
+ if(url_fopen(&formatc->pb, filename, URL_WRONLY) < 0)
+ {
+ synfig::warning("Unable to open file: %s", filename);
+ return 0;
+ }
+ }
+
+ //allocate the picture to render to
+ //may have to retrieve the width, height from the codec... for resizing...
+ picture = alloc_picture(PIX_FMT_RGB24,vInfo.w,vInfo.h);//video_st->codec.width, video_st->codec.height);
+ if(!picture)
+ {
+ synfig::warning("Unable to allocate the temporary AVFrame surface");
+ return 0;
+ }
+
+ initialized = true;
+ //vInfo.w = video_st->codec.width;
+ //vInfo.h = video_st->codec.height;
+
+ //write the stream header
+ av_write_header(formatc);
+
+ return true;
+ }
+
+ void CleanUp()
+ {
+ unsigned int i;
+
+ if(picture) free_picture(picture);
+
+ //do all the clean up file rendering
+ if(formatc && video_st)
+ {
+ //want to scan in delayed frames until no longer needed (TODO)
+ if(vid.startedencoding) while( vid.write_frame(formatc, video_st, 0) );
+
+ //may want to move this... probably to the end of the last frame...
+ av_write_trailer(formatc);
+ }
+
+ //close codecs
+ if (video_st)
+ vid.close(formatc,video_st);
+ /*if (audio_st)
+ aud.close(formatc,audio_st);*/
+
+ /* write the trailer, if any */
+ if(formatc)
+ {
+ /* free the streams */
+ for(i = 0; i < formatc->nb_streams; i++)
+ {
+ av_freep(&formatc->streams[i]);
+ }
+
+ if(!(format->flags & AVFMT_NOFILE))
+ {
+ /* close the output file */
+ url_fclose(&formatc->pb);
+ }
+
+ /* free the stream */
+ av_free(formatc);
+ }
+
+ initialized = false;
+
+ format = 0;
+ formatc = 0;
+
+ //video settings
+ video_st = 0;
+ video_pts = 0;
+
+ vid.encodable = 0;
+ //vid.stream_nb_frames = 2; //reasonable default
+
+ initialized = false;
+ picture = 0;
+ }
+
+ //create a video output stream
+ AVStream *add_video_stream(int codec_id, const VideoInfo &info)
+ {
+ AVCodecContext *context;
+ AVStream *st;
+
+ st = av_new_stream(formatc, 0);
+ if(!st)
+ {
+ synfig::warning("video-add_stream: Unable to allocate stream");
+ return 0;
+ }
+
+ context = st->codec;
+ context->codec_id = (CodecID)codec_id;
+ context->codec_type = CODEC_TYPE_VIDEO;
+
+ //PARAMETERS MUST BE PASSED IN SOMEHOW (ANOTHER FUNCTION PARAMETER???)
+
+ /* resolution must be a multiple of two */
+ context->width = info.w;
+ context->height = info.h;
+
+ //have another way to input these
+ context->bit_rate = info.bitrate; //TODO: Make dependant on the quality
+
+ /* frames per second */
+ // 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;
+
+ context->gop_size = info.fps/4; /* emit one intra frame every twelve frames at most */
+
+ //HACK: MPEG requires b frames be set... any better way to do this?
+ if (context->codec_id == CODEC_ID_MPEG1VIDEO ||
+ context->codec_id == CODEC_ID_MPEG2VIDEO)
+ {
+ /* just for testing, we also add B frames */
+ context->max_b_frames = 2;
+ }
+
+ return st;
+ }
+
+ // add an audio output stream
+ AVStream *add_audio_stream(int codec_id,const AudioInfo &/*aInfo*/)
+ {
+ AVCodecContext *context;
+ AVStream *stream;
+
+ stream = av_new_stream(formatc, 1);
+ if(!stream)
+ {
+ synfig::warning("could not alloc stream");
+ return 0;
+ }
+
+ context = stream->codec;
+ context->codec_id = (CodecID)codec_id;
+ context->codec_type = CODEC_TYPE_AUDIO;
+
+ /* put sample parameters */
+ context->bit_rate = 64000;
+ context->sample_rate = 44100;
+ context->channels = 2;
+
+ return stream;
+ }
+};
+
+/* === M E T H O D S ======================================================= */
+
+Target_LibAVCodec::Target_LibAVCodec(const char *Filename):
+ filename(Filename)
+{
+ if(!registered)
+ {
+ registered = true;
+ av_register_all();
+ }
+ set_remove_alpha();
+
+ data = new LibAVEncoder;
+}
+
+Target_LibAVCodec::~Target_LibAVCodec()
+{
+ data->CleanUp();
+}
+
+bool
+Target_LibAVCodec::set_rend_desc(RendDesc *given_desc)
+{
+ // This is where you can determine how you want stuff
+ // to be rendered! given_desc is the suggestion, and
+ // you need to modify it to suit the needs of the codec.
+ // ie: Making the pixel dimensions divisible by 8, etc...
+
+ desc=*given_desc;
+
+ //resize surface (round even)
+ int w = desc.get_w();
+ int h = desc.get_h();
+ Point tl = desc.get_tl();
+ Point br = desc.get_br();
+ Real pw = desc.get_pw();
+ Real ph = desc.get_ph();
+
+ //resize to the size it should be...
+ //desc.set_subwindow(-offx/2,-offy/2, desc.get_w() - offx?(offx + 8):0, desc.get_h() - offy?(offy + 8):0);
+
+ //if resolution is broken, change the size... or something
+ //budge to nearest pixel values
+ if(w&1)
+ {
+ w += 1;
+ tl[0] -= pw/2;
+ br[0] += pw/2;
+ }
+
+ if(h&1)
+ {
+ h += 1;
+ tl[1] -= ph/2;
+ br[1] += ph/2;
+ }
+
+ desc.set_w(w);
+ desc.set_h(h);
+ desc.set_tl(tl);
+ desc.set_br(br);
+
+ data->vInfo.w = w;
+ data->vInfo.h = h;
+
+ //may want to round frame rate
+ data->vInfo.fps = (int)floor(desc.get_frame_rate()+0.5);
+#define MEGABYTES_PER_HOUR(x) (((x)*1024/3600*1024*8)/*/640*w/480*h*/)
+ data->vInfo.bitrate = MEGABYTES_PER_HOUR(400);
+ //data->vInfo.bitrate = 800000; //make customizable somehow
+
+ desc.set_frame_rate(data->vInfo.fps);
+
+ data->frame_count = desc.get_frame_start();
+ data->num_frames = desc.get_frame_end()+1; //number of frames should be 1 greater than the last one
+
+ surface.set_wh(data->vInfo.w,data->vInfo.h);
+
+ return true;
+}
+
+void
+Target_LibAVCodec::end_frame()
+{
+ //AVStream *audio_st = data->audio_st;
+ AVStream *video_st = data->video_st;
+
+ AVFormatContext *formatc = data->formatc;
+
+ //double &audio_pts = data->audio_pts;
+ //double &video_pts = data->video_pts;
+
+ //ignore audio for now
+ /*if (audio_st)
+ audio_pts = (double)audio_st->pts.val * formatc->pts_num / formatc->pts_den;
+ else
+ audio_pts = 0.0;
+
+ if (video_st)
+ video_pts = (double)video_st->pts.val * formatc->pts_num / formatc->pts_den;
+ else
+ video_pts = 0.0;*/
+
+ //hardcoded crappiness
+ /*if ((!audio_st || audio_pts >= STREAM_DURATION) &&
+ (!video_st || video_pts >= STREAM_DURATION))
+ break;*/
+
+ if(data->frame_count >= data->num_frames) return;
+
+ //copy the current surface to the buffer
+ if(data->picture)convert_surface_frame(data->picture,surface,gamma());
+
+ //encode the frame and write it to the file
+ if(!data->vid.write_frame(formatc,video_st,data->picture))
+ {
+ synfig::warning("Unable to write a frame");
+ }
+
+ data->frame_count++;
+
+ if(data->frame_count >= data->num_frames)
+ {
+ data->CleanUp();
+ }
+
+ /* write interleaved audio and video frames */
+ /*if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
+ data->aud.write_frame(formatc,audio_st);
+ } else {
+ data->vid.write_frame(formatc,video_st);
+ }*/
+}
+
+bool
+Target_LibAVCodec::start_frame(synfig::ProgressCallback */*callback*/)
+{
+ //prepare all the color buffer stuff, etc.
+
+ return true;
+}
+
+Color *
+Target_LibAVCodec::start_scanline(int scanline)
+{
+ return surface[scanline];
+
+ return 0; // This should kill the render process
+}
+
+bool
+Target_LibAVCodec::end_scanline()
+{
+ //don't need to do anything until the whole frame is done
+ return true;
+}
+
+bool Target_LibAVCodec::init()
+{
+ //hardcoded test for mpeg
+ if(!data->Initialize(filename.c_str(),NULL))
+ {
+ synfig::warning("Unable to Initialize the audio video encoders");
+ return 0;
+ }
+
+ return true;
+}