1 /* === S Y N F I G ========================================================= */
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
25 #define SYNFIG_NO_ANGLE
41 #include <synfig/general.h>
49 #define snprintf _snprintf
52 /* === U S I N G =========================================================== */
54 using namespace synfig;
58 /* === I N F O ============================================================= */
60 SYNFIG_TARGET_INIT(Target_LibAVCodec);
61 SYNFIG_TARGET_SET_NAME(Target_LibAVCodec,"libav");
62 SYNFIG_TARGET_SET_EXT(Target_LibAVCodec,"avi");
63 SYNFIG_TARGET_SET_VERSION(Target_LibAVCodec,"0.1");
64 SYNFIG_TARGET_SET_CVS_ID(Target_LibAVCodec,"$Id$");
66 /* === C L A S S E S & S T R U C T S ======================================= */
68 bool Target_LibAVCodec::registered = false;
71 //float STREAM_DURATION = 5.0f;
83 int samplerate; //in HZ
84 int samplesize; //in bytes
87 AVFrame *alloc_picture(int pix_fmt, int width, int height)
93 picture = avcodec_alloc_frame();
96 size = avpicture_get_size(pix_fmt, width, height);
97 picture_buf = (uint8_t *)malloc(size);
102 avpicture_fill((AVPicture *)picture, picture_buf,
103 pix_fmt, width, height);
107 void free_picture(AVFrame *pic)
109 av_free(pic->data[0]);
113 //the frame must be RGB24
114 static void convert_surface_frame(AVFrame *pic, const Surface &s, const Gamma &gamma)
117 Surface::const_pen p = s.begin();
128 stride = pic->linesize[0];
130 for(j = 0; j < h; j++, p.inc_y(), ptr += stride)
134 //use convert_color_format instead...
136 const int channels = 3;
138 for(int i = 0; i < w; i++, p.inc_x(), tptr += channels)
142 Color::value_type r = c.get_r();
143 Color::value_type g = c.get_g();
144 Color::value_type b = c.get_b();
145 Color::value_type a = c.get_a();
152 //essentially treats it as if it has a background color of black
154 //we must also clamp the rgb values [0,1]
163 //now scale to range of char [0,255]
164 tptr[0] = (int)(r*255);
165 tptr[1] = (int)(g*255);
166 tptr[2] = (int)(b*255);
172 convert_color_format((unsigned char *)tptr,&p.get_value(),w,PF_RGB,gamma);
178 //Audio Streamer (abstracts the open, write and close operations for audio streams)
186 vector<unsigned char>audiobuffer;
188 int audio_input_frame_size;
190 bool open(AVFormatContext *formatc, AVStream *stream)
192 AVCodecContext *context;
195 context = &stream->codec;
198 codec = avcodec_find_encoder(context->codec_id);
201 synfig::warning("audio-open: could not find codec");
206 if(avcodec_open(context, codec) < 0)
208 synfig::warning("audio-open: could not open codec");
212 /* hardcoded example for generating samples array*/
215 tincr = 2 * M_PI * 110.0 / c->sample_rate;
216 tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;*/
218 audiobuffer.resize(10000);
220 /* ugly hack for PCM codecs (will be removed ASAP with new PCM
221 support to compute the input frame size in samples */
222 if (context->frame_size <= 1) {
223 audio_input_frame_size = audiobuffer.size() / context->channels;
224 switch(stream->codec.codec_id) {
225 case CODEC_ID_PCM_S16LE:
226 case CODEC_ID_PCM_S16BE:
227 case CODEC_ID_PCM_U16LE:
228 case CODEC_ID_PCM_U16BE:
229 audio_input_frame_size >>= 1;
235 audio_input_frame_size = context->frame_size;
239 //samples = (int16_t *)malloc(audio_input_frame_size * 2 * c->channels);
244 bool write_frame(AVFormatContext *formatc, AVStream *stream, void *samples)
247 AVCodecContext *context;
249 context = &stream->codec;
251 //hardcoded in example
252 //must read in from somewhere...
253 //get_audio_frame(samples, audio_input_frame_size, c->channels);
256 const short int*samps=(const short int *)samples; //assuming it's set from somewhere right now
258 size = avcodec_encode_audio(context, &audiobuffer[0], audiobuffer.size(), samps);
260 //write the compressed audio to a file
261 if(av_write_frame(formatc, stream->index, &audiobuffer[0], size) != 0)
263 synfig::warning("audio-write_frame: unable to write the entire audio frame");
270 void close(AVFormatContext *formatc, AVStream *stream)
272 //we may also want to catch delayed frames from here (don't for now)
276 avcodec_close(&stream->codec);
279 //if(samples)av_free(samples);
280 audiobuffer.resize(0);
289 AVFrame *encodable; //for compressiong and output to a file (in compatible pixel format)
291 vector<unsigned char> videobuffer;
293 bool startedencoding;
295 //int stream_nb_frames;
297 bool open(AVFormatContext *formatc, AVStream *stream)
299 if(!formatc || !stream)
301 synfig::warning("Attempt to open a video codec with a bad format or stream");
307 AVCodecContext *context;
309 //get from inside stream
310 context = stream->codec;
312 //search for desired codec (contained in the stream)
313 codec = avcodec_find_encoder(context->codec_id);
316 synfig::warning("Open_video: could not find desired codec");
320 //try to open the codec
321 if(avcodec_open(context, codec) < 0)
323 synfig::warning("open_video: could not open desired codec");
327 videobuffer.resize(0);
328 if(!(formatc->oformat->flags & AVFMT_RAWPICTURE))
330 //resize buffer to desired buffersize
331 videobuffer.resize(200000); //TODO: need to figure out a good size
334 //allocate the base picture which will be used to encode
335 /*picture = alloc_picture(PIX_FMT_RGBA32, context->width, context->height);
338 synfig::warning("open_video: could not allocate the picture to be encoded");
342 //if our output (rgb) needs to be translated to a different coordinate system, need a temporary picture in that color space
344 /* Should use defaults of RGB
348 PIX_FMT_RGBA32 //stored in cpu endianness (!!!!)
350 (possibly translate directly to required coordinate systems later on... less error)
353 if(context->pix_fmt != PIX_FMT_RGB24)
355 encodable = alloc_picture(context->pix_fmt, context->width, context->height);
358 synfig::warning("open_video: could not allocate encodable picture");
366 //write a frame with the frame passed in
367 bool write_frame(AVFormatContext *formatc, AVStream *stream, AVFrame *pict)
369 if(!formatc || !stream)
371 synfig::warning("Attempt to open a video codec with a bad format or stream");
377 AVCodecContext *context = stream->codec;
380 If pict is invalid (NULL), then we are done compressing frames and we are trying to get
381 the buffer cleared out (or if it's already in the right format) so no transform necessary
385 startedencoding = true;
389 if ( pict && context->pix_fmt != PIX_FMT_RGB24 )
391 //We're using RGBA at the moment, write custom conversion code later (get less accuracy errors)
392 img_convert((AVPicture *)encodable, context->pix_fmt,
393 (AVPicture *)pict, PIX_FMT_RGB24,
394 context->width, context->height);
400 av_init_packet(&pkt);
401 pkt.stream_index = stream->index;
402 pkt.data = (uint8_t *)pict;
403 pkt.size = sizeof(AVPicture);
404 if( context->coded_frame )
405 pkt.pts = context->coded_frame->pts;
406 if( context->coded_frame && context->coded_frame->key_frame)
407 pkt.flags |= PKT_FLAG_KEY;
409 //cludge for raw picture format (they said they'd fix)
410 if (formatc->oformat->flags & AVFMT_RAWPICTURE)
412 ret = av_write_frame(formatc, &pkt);
416 //encode our given image
417 size = avcodec_encode_video(context, &videobuffer[0], videobuffer.size(), pict);
419 //if greater than zero we've got stuff to write
422 av_init_packet(&pkt);
423 pkt.stream_index = stream->index;
424 pkt.data = &videobuffer[0];
426 if( context->coded_frame )
427 pkt.pts = context->coded_frame->pts;
428 if( context->coded_frame && context->coded_frame->key_frame)
429 pkt.flags |= PKT_FLAG_KEY;
431 ret = av_write_frame(formatc, &pkt);
433 //error detect - possibly throw later...
436 synfig::warning("write_frame: error while writing video frame");
440 //if 0, it was buffered (if invalid picture we don't have ANY data left)
443 //if we're clearing the buffers and there was no stuff to be written, we're done (like in codec example)
447 startedencoding = false;
457 void close(AVFormatContext *formatc, AVStream *stream)
460 avcodec_close(stream->codec);
464 free_picture(encodable);
468 videobuffer.resize(0);
472 class Target_LibAVCodec::LibAVEncoder
478 AVOutputFormat *format; //reference to global, do not delete
480 AVFormatContext *formatc;
483 //AVStream *audio_st;
494 AVFrame *picture; //for encoding to RGB24 (perhaps RGBA later)
509 //vid.stream_nb_frames = 2; //reasonable default
527 bool Initialize(const char *filename, const char *typestring)
529 //guess if we have a type string, otherwise use filename
532 //formatptr guess_format(type, filename, MIME type)
533 format = guess_format(typestring,NULL,NULL);
537 format = guess_format(NULL, filename, NULL);
542 synfig::warning("Unable to Guess the output, defaulting to mpeg");
543 format = guess_format("mpeg", NULL, NULL);
548 synfig::warning("Unable to find output format");
552 //allocate the output context
553 formatc = (AVFormatContext *)av_mallocz(sizeof(AVFormatContext));
556 synfig::warning("Memory error\n");
559 //set the output format to the one we found
560 formatc->oformat = format;
562 //print the output filename
563 snprintf(formatc->filename, sizeof(formatc->filename), "%s", filename);
570 if(format->video_codec != CODEC_ID_NONE)
572 video_st = add_video_stream(format->video_codec,vInfo);
580 /*if(format->audio_codec != CODEC_ID_NONE)
582 audio_st = add_audio_stream(format->audio_codec,aInfo);
585 //set output parameters: required in ALL cases
587 video_st->codec->time_base= (AVRational){1,vInfo.fps};
588 video_st->codec->width = vInfo.w;
589 video_st->codec->height = vInfo.h;
590 video_st->codec->pix_fmt = PIX_FMT_YUV420P;
592 //dump the formatting information as the file header
593 dump_format(formatc, 0, filename, 1);
595 //open codecs and allocate buffers
598 if(!vid.open(formatc, video_st))
600 synfig::warning("Could not open video encoder");
606 if(!aud.open(formatc, audio_st))
608 synfig::warning("Could not open audio encoder");
614 if(!(format->flags & AVFMT_NOFILE))
616 //use libav's file open function (what does it do differently????)
617 if(url_fopen(&formatc->pb, filename, URL_WRONLY) < 0)
619 synfig::warning("Unable to open file: %s", filename);
624 //allocate the picture to render to
625 //may have to retrieve the width, height from the codec... for resizing...
626 picture = alloc_picture(PIX_FMT_RGB24,vInfo.w,vInfo.h);//video_st->codec.width, video_st->codec.height);
629 synfig::warning("Unable to allocate the temporary AVFrame surface");
634 //vInfo.w = video_st->codec.width;
635 //vInfo.h = video_st->codec.height;
637 //write the stream header
638 av_write_header(formatc);
647 if(picture) free_picture(picture);
649 //do all the clean up file rendering
650 if(formatc && video_st)
652 //want to scan in delayed frames until no longer needed (TODO)
653 if(vid.startedencoding) while( vid.write_frame(formatc, video_st, 0) );
655 //may want to move this... probably to the end of the last frame...
656 av_write_trailer(formatc);
661 vid.close(formatc,video_st);
663 aud.close(formatc,audio_st);*/
665 /* write the trailer, if any */
668 /* free the streams */
669 for(i = 0; i < formatc->nb_streams; i++)
671 av_freep(&formatc->streams[i]);
674 if(!(format->flags & AVFMT_NOFILE))
676 /* close the output file */
677 url_fclose(&formatc->pb);
680 /* free the stream */
694 //vid.stream_nb_frames = 2; //reasonable default
700 //create a video output stream
701 AVStream *add_video_stream(int codec_id, const VideoInfo &info)
703 AVCodecContext *context;
706 st = av_new_stream(formatc, 0);
709 synfig::warning("video-add_stream: Unable to allocate stream");
714 context->codec_id = (CodecID)codec_id;
715 context->codec_type = CODEC_TYPE_VIDEO;
717 //PARAMETERS MUST BE PASSED IN SOMEHOW (ANOTHER FUNCTION PARAMETER???)
719 /* resolution must be a multiple of two */
720 context->width = info.w;
721 context->height = info.h;
723 //have another way to input these
724 context->bit_rate = info.bitrate; //TODO: Make dependant on the quality
726 /* frames per second */
727 // FIXME: Port next two lines to recent libavcodec versions
728 //context->frame_rate = info.fps;
729 //context->frame_rate_base = 1;
732 context->mb_decision=FF_MB_DECISION_BITS;
734 context->gop_size = info.fps/4; /* emit one intra frame every twelve frames at most */
736 //HACK: MPEG requires b frames be set... any better way to do this?
737 if (context->codec_id == CODEC_ID_MPEG1VIDEO ||
738 context->codec_id == CODEC_ID_MPEG2VIDEO)
740 /* just for testing, we also add B frames */
741 context->max_b_frames = 2;
747 // add an audio output stream
748 AVStream *add_audio_stream(int codec_id,const AudioInfo &aInfo)
750 AVCodecContext *context;
753 stream = av_new_stream(formatc, 1);
756 synfig::warning("could not alloc stream");
760 context = stream->codec;
761 context->codec_id = (CodecID)codec_id;
762 context->codec_type = CODEC_TYPE_AUDIO;
764 /* put sample parameters */
765 context->bit_rate = 64000;
766 context->sample_rate = 44100;
767 context->channels = 2;
773 /* === M E T H O D S ======================================================= */
775 Target_LibAVCodec::Target_LibAVCodec(const char *Filename):
785 data = new LibAVEncoder;
788 Target_LibAVCodec::~Target_LibAVCodec()
794 Target_LibAVCodec::set_rend_desc(RendDesc *given_desc)
796 // This is where you can determine how you want stuff
797 // to be rendered! given_desc is the suggestion, and
798 // you need to modify it to suit the needs of the codec.
799 // ie: Making the pixel dimensions divisible by 8, etc...
803 //resize surface (round even)
804 int w = desc.get_w();
805 int h = desc.get_h();
806 Point tl = desc.get_tl();
807 Point br = desc.get_br();
808 Real pw = desc.get_pw();
809 Real ph = desc.get_ph();
811 //resize to the size it should be...
812 //desc.set_subwindow(-offx/2,-offy/2, desc.get_w() - offx?(offx + 8):0, desc.get_h() - offy?(offy + 8):0);
814 //if resolution is broken, change the size... or something
815 //budge to nearest pixel values
838 //may want to round frame rate
839 data->vInfo.fps = (int)floor(desc.get_frame_rate()+0.5);
840 #define MEGABYTES_PER_HOUR(x) (((x)*1024/3600*1024*8)/*/640*w/480*h*/)
841 data->vInfo.bitrate = MEGABYTES_PER_HOUR(400);
842 //data->vInfo.bitrate = 800000; //make customizable somehow
844 desc.set_frame_rate(data->vInfo.fps);
846 data->frame_count = desc.get_frame_start();
847 data->num_frames = desc.get_frame_end()+1; //number of frames should be 1 greater than the last one
849 surface.set_wh(data->vInfo.w,data->vInfo.h);
855 Target_LibAVCodec::end_frame()
857 //AVStream *audio_st = data->audio_st;
858 AVStream *video_st = data->video_st;
860 AVFormatContext *formatc = data->formatc;
862 //double &audio_pts = data->audio_pts;
863 //double &video_pts = data->video_pts;
865 //ignore audio for now
867 audio_pts = (double)audio_st->pts.val * formatc->pts_num / formatc->pts_den;
872 video_pts = (double)video_st->pts.val * formatc->pts_num / formatc->pts_den;
876 //hardcoded crappiness
877 /*if ((!audio_st || audio_pts >= STREAM_DURATION) &&
878 (!video_st || video_pts >= STREAM_DURATION))
881 if(data->frame_count >= data->num_frames) return;
883 //copy the current surface to the buffer
884 if(data->picture)convert_surface_frame(data->picture,surface,gamma());
886 //encode the frame and write it to the file
887 if(!data->vid.write_frame(formatc,video_st,data->picture))
889 synfig::warning("Unable to write a frame");
894 if(data->frame_count >= data->num_frames)
899 /* write interleaved audio and video frames */
900 /*if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
901 data->aud.write_frame(formatc,audio_st);
903 data->vid.write_frame(formatc,video_st);
908 Target_LibAVCodec::start_frame(synfig::ProgressCallback *callback)
910 //prepare all the color buffer stuff, etc.
916 Target_LibAVCodec::start_scanline(int scanline)
918 return surface[scanline];
920 return 0; // This should kill the render process
924 Target_LibAVCodec::end_scanline()
926 //don't need to do anything until the whole frame is done
930 bool Target_LibAVCodec::init()
932 //hardcode test for mpeg
933 if(!data->Initialize(filename.c_str(),NULL))
935 synfig::warning("Unable to Initialize the audio video encoders");