1 /* === S Y N F I G ========================================================= */
5 ** $Id: trgt_av.cpp,v 1.1.1.1 2005/01/04 01:23:11 darco Exp $
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: trgt_av.cpp,v 1.1.1.1 2005/01/04 01:23:11 darco Exp $");
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 transofrm 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 not 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 AVFormatParameters fmtparam,*ap = &fmtparam;
588 memset(ap, 0, sizeof(*ap));
589 // FIXME: Port next two lines to recent libavcodec versions
590 //ap->frame_rate = vInfo.fps;
591 //ap->frame_rate_base = 1;
593 ap->height = vInfo.h;
594 //ap->pix_fmt = frame_pix_fmt;
596 if(av_set_parameters(formatc, ap) < 0)
598 synfig::warning("Invalid output formatting parameters");
602 //dump the formatting information as the file header
603 dump_format(formatc, 0, filename, 1);
605 //open codecs and allocate buffers
608 if(!vid.open(formatc, video_st))
610 synfig::warning("Could not open video encoder");
616 if(!aud.open(formatc, audio_st))
618 synfig::warning("Could not open audio encoder");
624 if(!(format->flags & AVFMT_NOFILE))
626 //use libav's file open function (what does it do differently????)
627 if(url_fopen(&formatc->pb, filename, URL_WRONLY) < 0)
629 synfig::warning("Unable to open file: %s", filename);
634 //allocate the picture to render to
635 //may have to retrieve the width, height from the codec... for resizing...
636 picture = alloc_picture(PIX_FMT_RGB24,vInfo.w,vInfo.h);//video_st->codec.width, video_st->codec.height);
639 synfig::warning("Unable to allocate the temporary AVFrame surface");
644 //vInfo.w = video_st->codec.width;
645 //vInfo.h = video_st->codec.height;
647 //write the stream header
648 av_write_header(formatc);
657 if(picture) free_picture(picture);
659 //do all the clean up file rendering
660 if(formatc && video_st)
662 //want to scan in delayed frames until no longer needed (TODO)
663 if(vid.startedencoding) while( vid.write_frame(formatc, video_st, 0) );
665 //may want to move this... probably to the end of the last frame...
666 av_write_trailer(formatc);
671 vid.close(formatc,video_st);
673 aud.close(formatc,audio_st);*/
675 /* write the trailer, if any */
678 /* free the streams */
679 for(i = 0; i < formatc->nb_streams; i++)
681 av_freep(&formatc->streams[i]);
684 if(!(format->flags & AVFMT_NOFILE))
686 /* close the output file */
687 url_fclose(&formatc->pb);
690 /* free the stream */
704 //vid.stream_nb_frames = 2; //reasonable default
710 //create a video output stream
711 AVStream *add_video_stream(int codec_id, const VideoInfo &info)
713 AVCodecContext *context;
716 st = av_new_stream(formatc, 0);
719 synfig::warning("video-add_stream: Unable to allocate stream");
724 context->codec_id = (CodecID)codec_id;
725 context->codec_type = CODEC_TYPE_VIDEO;
727 //PARAMETERS MUST BE PASSED IN SOMEHOW (ANOTHER FUNCTION PARAMETER???)
729 /* resolution must be a multiple of two */
730 context->width = info.w;
731 context->height = info.h;
733 //have another way to input these
734 context->bit_rate = info.bitrate; //TODO: Make dependant on the quality
736 /* frames per second */
737 // FIXME: Port next two lines to recent libavcodec versions
738 //context->frame_rate = info.fps;
739 //context->frame_rate_base = 1;
742 context->mb_decision=FF_MB_DECISION_BITS;
744 context->gop_size = info.fps/4; /* emit one intra frame every twelve frames at most */
746 //HACK: MPEG requires b frames be set... any better way to do this?
747 if (context->codec_id == CODEC_ID_MPEG1VIDEO ||
748 context->codec_id == CODEC_ID_MPEG2VIDEO)
750 /* just for testing, we also add B frames */
751 context->max_b_frames = 2;
757 // add an audio output stream
758 AVStream *add_audio_stream(int codec_id,const AudioInfo &aInfo)
760 AVCodecContext *context;
763 stream = av_new_stream(formatc, 1);
766 synfig::warning("could not alloc stream");
770 context = stream->codec;
771 context->codec_id = (CodecID)codec_id;
772 context->codec_type = CODEC_TYPE_AUDIO;
774 /* put sample parameters */
775 context->bit_rate = 64000;
776 context->sample_rate = 44100;
777 context->channels = 2;
783 /* === M E T H O D S ======================================================= */
785 Target_LibAVCodec::Target_LibAVCodec(const char *Filename):
795 data = new LibAVEncoder;
798 Target_LibAVCodec::~Target_LibAVCodec()
804 Target_LibAVCodec::set_rend_desc(RendDesc *given_desc)
806 // This is where you can determine how you want stuff
807 // to be rendered! given_desc is the suggestion, and
808 // you need to modify it to suit the needs of the codec.
809 // ie: Making the pixel dimensions divisible by 8, etc...
813 //resize surface (round even)
814 int w = desc.get_w();
815 int h = desc.get_h();
816 Point tl = desc.get_tl();
817 Point br = desc.get_br();
818 Real pw = desc.get_pw();
819 Real ph = desc.get_ph();
821 //resize to the size it should be...
822 //desc.set_subwindow(-offx/2,-offy/2, desc.get_w() - offx?(offx + 8):0, desc.get_h() - offy?(offy + 8):0);
824 //if resolution is broken, change the size... or something
825 //budge to nearest pixel values
848 //may want to round frame rate
849 data->vInfo.fps = (int)floor(desc.get_frame_rate()+0.5);
850 #define MEGABYTES_PER_HOUR(x) (((x)*1024/3600*1024*8)/*/640*w/480*h*/)
851 data->vInfo.bitrate = MEGABYTES_PER_HOUR(400);
852 //data->vInfo.bitrate = 800000; //make customizable somehow
854 desc.set_frame_rate(data->vInfo.fps);
856 data->frame_count = desc.get_frame_start();
857 data->num_frames = desc.get_frame_end()+1; //number of frames should be 1 greater than the last one
859 surface.set_wh(data->vInfo.w,data->vInfo.h);
865 Target_LibAVCodec::end_frame()
867 //AVStream *audio_st = data->audio_st;
868 AVStream *video_st = data->video_st;
870 AVFormatContext *formatc = data->formatc;
872 //double &audio_pts = data->audio_pts;
873 //double &video_pts = data->video_pts;
875 //ignore audio for now
877 audio_pts = (double)audio_st->pts.val * formatc->pts_num / formatc->pts_den;
882 video_pts = (double)video_st->pts.val * formatc->pts_num / formatc->pts_den;
886 //hardcoded crappiness
887 /*if ((!audio_st || audio_pts >= STREAM_DURATION) &&
888 (!video_st || video_pts >= STREAM_DURATION))
891 if(data->frame_count >= data->num_frames) return;
893 //copy the current surface to the buffer
894 if(data->picture)convert_surface_frame(data->picture,surface,gamma());
896 //encode the frame and write it to the file
897 if(!data->vid.write_frame(formatc,video_st,data->picture))
899 synfig::warning("Unable to write a frame");
904 if(data->frame_count >= data->num_frames)
909 /* write interleaved audio and video frames */
910 /*if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
911 data->aud.write_frame(formatc,audio_st);
913 data->vid.write_frame(formatc,video_st);
918 Target_LibAVCodec::start_frame(synfig::ProgressCallback *callback)
920 //prepare all the color buffer stuff, etc.
926 Target_LibAVCodec::start_scanline(int scanline)
928 return surface[scanline];
930 return 0; // This should kill the render process
934 Target_LibAVCodec::end_scanline()
936 //don't need to do anything until the whole frame is done
940 bool Target_LibAVCodec::init()
942 //hardcode test for mpeg
943 if(!data->Initialize(filename.c_str(),NULL))
945 synfig::warning("Unable to Initialize the audio video encoders");