summaryrefslogtreecommitdiff
path: root/NT/src/libavwrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NT/src/libavwrapper.cpp')
-rw-r--r--NT/src/libavwrapper.cpp724
1 files changed, 724 insertions, 0 deletions
diff --git a/NT/src/libavwrapper.cpp b/NT/src/libavwrapper.cpp
new file mode 100644
index 0000000..4a8315f
--- /dev/null
+++ b/NT/src/libavwrapper.cpp
@@ -0,0 +1,724 @@
+#include "libavwrapper.h"
+
+Poco::Mutex mutex;
+
+#include <stdexcept>
+#include <iostream>
+#include <cassert>
+
+using namespace std;
+using namespace Poco;
+
+static bool b_is_one_time_inited=false;
+static int sws_flags = SWS_BICUBIC;
+
+void libav::maybeInitFFMpegLib()
+{
+ if (b_is_one_time_inited)
+ return;
+ FFMS_Init(0, 0); //should do for all
+ //av_register_all();
+ //avcodec_register_all();
+ avformat_network_init();
+ b_is_one_time_inited = true;
+}
+
+ void libav::video_decoder::cleanup(){
+ if (loaded) {
+ Mutex::ScopedLock lock(mutex);
+ FFMS_DestroyVideoSource(source);
+ loaded=false;
+ }
+}
+
+bool libav::video_decoder::open(const std::string& filename){
+ cleanup();
+ Mutex::ScopedLock lock(mutex);
+ Poco::File f=Poco::File(filename);
+ if (!f.exists()) {
+ cerr<<"ERROR: "<<filename<<" does not exist"<<endl;
+ return false;
+ }
+
+ //first check if an index object exists
+ Poco::StringTokenizer tokens(filename,".");
+ string idxfile="";
+ if (tokens.count()>1){
+ for (uint32_t i=0;i<tokens.count()-1;i++){
+ idxfile+=tokens[i];
+ idxfile+=".";
+ }
+ idxfile+="idx";
+ }
+ else idxfile=filename+".idx";
+
+ f=Poco::File(idxfile);
+ bool makeindex=true;
+ FFMS_Index *index;
+ if (f.exists()) {
+ index=FFMS_ReadIndex(idxfile.c_str(),&err);
+ if (index) {
+ cerr<<"FFMS2: loaded index "<<idxfile<<endl;
+ if (FFMS_IndexBelongsToFile(index,filename.c_str(),&err)==0){
+ makeindex=false;
+ }
+ }
+ }
+ if (makeindex) {
+ index = FFMS_MakeIndex(filename.c_str(), 0, 0, NULL, NULL, FFMS_IEH_IGNORE, NULL, NULL, &err);
+ if (index) {
+ FFMS_WriteIndex(idxfile.c_str(),index,&err);
+ cerr<<"FFMS2: created index "<<idxfile<<endl;
+ }
+ cerr<<"FFMS2: "<<filename<<" cannot be indexed "<<endl;
+ }
+ if (index == NULL) {
+ std::cerr<<"ffmpegsource: "<<err.Buffer<<std::endl;
+ return false;
+ }
+ int trackno = FFMS_GetFirstTrackOfType(index, FFMS_TYPE_VIDEO, &err);
+ if (trackno < 0) {
+ std::cerr<<"ffmpegsource: "<<err.Buffer<<std::endl;
+ return false;
+ }
+ source = FFMS_CreateVideoSource(filename.c_str(), trackno, index, 1, FFMS_SEEK_NORMAL, &err);
+ if (source == NULL) {
+ std::cerr<<"ffmpegsource: "<<err.Buffer<<std::endl;
+ return false;
+ }
+ FFMS_DestroyIndex(index);
+ props = FFMS_GetVideoProperties(source);
+ const FFMS_Frame *propframe = FFMS_GetFrame(source, 0, &err);
+ w=propframe->EncodedWidth;
+ h=propframe->EncodedHeight;
+ //propframe->EncodedPixelFormat;
+
+ if (FFMS_SetOutputFormatV2(source, pixfmts, propframe->EncodedWidth, propframe->EncodedHeight, FFMS_RESIZER_BICUBIC, &err)) {
+ std::cerr<<"ffmpegsource: "<<err.Buffer<<std::endl;
+ return false;
+ }
+
+ //std::cerr<<"ffmpegsource: successfully opened "<<filename<<std::endl;
+ loaded=true;
+ return loaded;
+}
+
+bool libav::audio_decoder::open(const std::string& filename){
+ Mutex::ScopedLock lock(mutex);
+ loaded=false;
+ FFMS_Index *index = FFMS_MakeIndex(filename.c_str(),-1, 0, NULL, NULL, FFMS_IEH_IGNORE, NULL, NULL, &err);
+ if (index == NULL) {
+ std::cerr<<"ffmpegsource error making index for "<<filename<<":"<<err.Buffer<<std::endl;
+ return false;
+ }
+ int trackno = FFMS_GetFirstTrackOfType(index, FFMS_TYPE_AUDIO, &err);
+ if (trackno < 0) {
+ std::cerr<<"ffmpegsource error finding audio track in "<<filename<<":"<<err.Buffer<<std::endl;
+ return false;
+ }
+ std::cerr<<"ffmpegsource found audio track "<<trackno<<" in "<<filename<<":"<<err.Buffer<<std::endl;
+ source = FFMS_CreateAudioSource(filename.c_str(), trackno, index, FFMS_DELAY_TIME_ZERO, &err);
+ if (source == NULL) {
+ std::cerr<<"ffmpegsource error creating audio source from "<<filename<<":"<<err.Buffer<<std::endl;
+ return false;
+ }
+ FFMS_DestroyIndex(index);
+ props = FFMS_GetAudioProperties(source);
+
+ std::cerr<<"ffmpegsource: successfully opened "<<filename<<std::endl;
+ loaded=true;
+ return loaded;
+}
+ void libav::audio_decoder::cleanup(){
+ if (loaded) {
+ Mutex::ScopedLock lock(mutex);
+ FFMS_DestroyAudioSource(source);
+ loaded=false;
+ }
+}
+
+bool libav::exporter::setup(int w,int h, int bitRate, int frameRate, std::string container, bool _fragmentation){
+
+ maybeInitFFMpegLib();
+
+ fragmentation=_fragmentation;
+
+ this->w=w;
+ this->h=h;
+ this->bitRate=bitRate;
+ this->frameRate=frameRate;
+ this->container=container;
+
+ if (NULL != sws_ctx) {
+ sws_freeContext(sws_ctx);
+ sws_ctx = NULL;
+ }
+
+ sws_ctx = sws_getContext(w, h, AV_PIX_FMT_RGB24,
+ w, h, AV_PIX_FMT_YUV420P,
+ sws_flags, NULL, NULL, NULL);
+
+ return true;
+}
+
+bool libav::exporter::record(std::string filename){
+
+
+ // allocate the output media context //
+ avformat_alloc_output_context2(&oc, NULL, NULL, filename.c_str());
+
+
+ if (!oc) {
+ printf("Could not deduce output format from file extension: using MPEG.\n");
+ avformat_alloc_output_context2(&oc, NULL, "mpeg", filename.c_str());
+ }
+ if (!oc) {
+ return false;
+ }
+ fmt = oc->oformat;
+
+ av_opt_set(oc->priv_data, "profile", "baseline", AV_OPT_SEARCH_CHILDREN);
+
+
+ // Add the audio and video streams using the default format codecs
+ // * and initialize the codecs. //
+ video_st = NULL;
+ audio_st = NULL;
+
+ fmt->video_codec=AV_CODEC_ID_H264; //AV_CODEC_ID_MPEG4
+ fmt->audio_codec=AV_CODEC_ID_AAC; //guessing, 011013
+
+
+ if (fmt->video_codec != AV_CODEC_ID_NONE) {
+ video_st = add_stream(oc, &video_codec, fmt->video_codec);
+ }
+ if (fmt->audio_codec != AV_CODEC_ID_NONE) {
+ //audio_st = add_stream(oc, &audio_codec, fmt->audio_codec);
+ audio_st = add_stream(oc, &audio_codec, fmt->audio_codec);
+ }
+
+
+
+ //set initial video params
+ video_st->codec->width=w;
+ video_st->codec->height=h;
+ video_st->codec->time_base.num = 1;//codecCtx->ticks_per_frame;
+ video_st->codec->time_base.den = frameRate;
+ video_st->time_base = video_st->codec->time_base;
+ //audioStream->time_base = codecCtx->time_base; //???has the capability of crashing
+
+ video_st->codec->gop_size = 75; /* emit one intra frame every 75 frames */
+ video_st->codec->pix_fmt = PIX_FMT_YUV420P;
+
+ if (bitRate){
+ cerr<<"Libav::exporter setting bitrate to "<<bitRate<<endl;
+
+ video_st->codec->bit_rate = bitRate; //need to deal with resolution etc
+ video_st->codec->rc_max_rate = bitRate;
+ video_st->codec->rc_min_rate = 0;
+
+ //added 131113
+ video_st->codec->rc_buffer_size = bitRate * 2;
+ }
+
+ //av_dict_set(&options, "profile", "baseline", 0);
+ //video_st->codec->flags2 = CODEC_FLAG2_FASTPSKIP;
+ video_st->codec->profile = FF_PROFILE_H264_BASELINE;
+ video_st->codec->level = 13;
+
+
+ //how to set profile????? 190913
+ //this causes a crash
+ //av_opt_set(video_st->codec->priv_data,"profile",FF_PROFILE_H264_CONSTRAINED_BASELINE, 0);
+ //
+ // http://libav-users.943685.n4.nabble.com/Libav-user-encoding-bitrate-wrong-td4433740.html
+ // http://libav-users.943685.n4.nabble.com/Libav-user-H264-encoding-set-target-average-bitrate-td3912529.html
+ // http://trac.ffmpeg.org/wiki/x264EncodingGuide
+
+
+
+ // Now that all the parameters are set, we can open the audio and
+ // * video codecs and allocate the necessary encode buffers. //
+
+ if (video_st) {
+ if (!open_video(oc, video_codec, video_st)){
+ return false;
+ }
+ }
+ if (audio_st) {
+ audioframesize=open_audio(oc, audio_codec, audio_st);
+ audiostep=((double)audioframesize)/(audio_st->codec->sample_rate);
+ std::cerr << "opened audio codec with "<<audioframesize<<" frame size and "<<audiostep<<" seconds per frame"<<std::endl;
+ }
+
+
+
+ av_dump_format(oc, 0, filename.c_str(), 1);
+
+ // open the output file, if needed //
+ if (!(fmt->flags & AVFMT_NOFILE)) {
+ Mutex::ScopedLock lock(mutex);
+ int ret = avio_open(&oc->pb, filename.c_str(), AVIO_FLAG_WRITE);
+ if (ret < 0) {
+ std::cerr <<"Could not open " << filename.c_str() << std::endl;
+ return false;
+ }
+ }
+
+ AVDictionary *opts = NULL; // "create" an empty dictionary
+
+ // https://libav.org/avprobe.html#MOV_002fMP4_002fISMV
+
+ //THIS DOES SEEM TO SET CONTAINER OPTS= AS MOOV_SIZE MAKES THE MOVIE BANJAXED
+ //av_dict_set(&opts, "moov_size", "20000", 0);
+ if (fragmentation) {
+ av_dict_set(&opts, "movflags","frag_keyframe", 0); //makes a video watchable in chrome, quicktime & mplayer
+ //av_dict_set(&opts, "movflags","empty_moov",1);
+ }
+
+
+ // Write the stream header, if any. //
+ int ret = avformat_write_header(oc, &opts);
+ if (ret < 0) {
+ std::cerr <<"Error occurred when opening output file:" <<endl; // av_err2str(ret) << std::endl;
+ return false;
+ }
+ //#include <libavformat/movenc.h>
+ //mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s)
+ /*ret = mov_write_moov_tag(oc, NULL,NULL);
+ if (ret < 0) {
+ std::cerr <<"Error occurred when writing moov atom " <<endl; // << av_err2str(ret) << std::endl;
+ return false;
+ }*/
+
+ if (frame)
+ frame->pts = 0;
+
+ outputframe=0;
+
+ return true;
+}
+bool libav::exporter::encodeFrame(unsigned char *pixels,uint16_t *samples){
+ // Compute current audio and video time. //
+ if (audio_st)
+ audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
+ else
+ audio_pts = 0.0;
+
+ if (video_st)
+ video_pts = (double)video_st->pts.val * video_st->time_base.num /
+ video_st->time_base.den;
+ else
+ video_pts = 0.0;
+
+ // write interleaved audio and video frames //
+ if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
+ write_audio_frame(oc, audio_st, samples);
+ } else {
+ write_video_frame(oc, video_st, pixels);
+
+ frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
+ }
+
+ //std::cerr << "encoded frame " << outputframe << std::endl;
+ outputframe++;
+
+ return true;
+}
+bool libav::exporter::encodeFrame(unsigned char *pixels,AVPacket *audio){
+ // Compute current audio and video time. //
+ if (audio_st)
+ audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
+ else
+ audio_pts = 0.0;
+
+ if (video_st)
+ video_pts = (double)video_st->pts.val * video_st->time_base.num /
+ video_st->time_base.den;
+ else
+ video_pts = 0.0;
+
+ // write interleaved audio and video frames //
+ if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
+ write_audio_frame(oc, audio_st, audio);
+ } else {
+ write_video_frame(oc, video_st, pixels);
+
+ frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
+ }
+
+ //std::cerr << "encoded frame " << outputframe << std::endl;
+ outputframe++;
+
+ return true;
+}
+bool libav::exporter::encodeFrame(unsigned char *pixels,bool keyframe){
+ video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
+ write_video_frame(oc, video_st, pixels,keyframe);
+ frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
+ outputframe++;
+ return true;
+}
+bool libav::exporter::encodeFrame(uint16_t *samples){
+ audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
+ write_audio_frame(oc, audio_st, samples);
+ return true;
+}
+void libav::exporter::finishRecord(){
+
+ av_write_trailer(oc);
+ // Close each codec. //
+ if (video_st)
+ close_video(oc, video_st);
+ if (audio_st)
+ close_audio(oc, audio_st);
+
+ if (!(fmt->flags & AVFMT_NOFILE)) {
+ // Close the output file. //
+ Mutex::ScopedLock lock(mutex);
+ avio_close(oc->pb);
+ }
+
+ // free the stream //
+ avformat_free_context(oc);
+}
+
+AVStream* libav::exporter::add_stream(AVFormatContext *oc, AVCodec **codec,enum AVCodecID codec_id)
+ {
+ //removed some of the repeats from record() 141113
+ AVCodecContext *c;
+ AVStream *st;
+
+ // find the encoder //
+ *codec = avcodec_find_encoder(codec_id);
+ if (!(*codec)) {
+ //fprintf(stderr, "Could not find encoder for '%s'\n",
+ // avcodec_get_name(codec_id));
+ exit(1);
+ }
+
+ st = avformat_new_stream(oc, *codec);
+ if (!st) {
+ //fprintf(stderr, "Could not allocate stream\n");
+ exit(1);
+ }
+ st->id = oc->nb_streams-1;
+ c = st->codec;
+
+ switch ((*codec)->type) {
+ case AVMEDIA_TYPE_AUDIO:
+ st->id = 1;
+ c->sample_fmt = AV_SAMPLE_FMT_S16;
+ c->bit_rate = 160000;
+ c->sample_rate = 44100;
+ c->channels = 2;
+ c->channel_layout=AV_CH_LAYOUT_STEREO;
+ break;
+
+ case AVMEDIA_TYPE_VIDEO:
+ c->codec_id = codec_id;
+
+ //c->bit_rate = bitRate; //need to deal with resolution etc
+
+ // c->rc_max_rate = bitRate;
+ //c->rc_min_rate = 0;
+ //c->rc_buffer_size = Profile()->m_videoMaxVopSize; //??
+
+ /*
+ all taken out 091113 to try to stop making incompatible movies
+ */
+
+
+ // Resolution must be a multiple of two. //
+ //c->width = 352;
+ //c->height = 288;
+
+
+ // timebase: This is the fundamental unit of time (in seconds) in terms
+ // * of which frame timestamps are represented. For fixed-fps content,
+ // * timebase should be 1/framerate and timestamp increments should be
+ // * identical to 1. //
+ c->time_base.den = frameRate;
+ c->time_base.num = 1;
+ // c->gop_size = 12; // emit one intra frame every twelve frames at most //
+ c->pix_fmt = AV_PIX_FMT_YUV420P; //ADDED HARDCODED TJR 280513
+ if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
+ // just for testing, we also add B frames //
+ c->max_b_frames = 2;
+ }
+ if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
+ // Needed to avoid using macroblocks in which some coeffs overflow.
+ // * This does not happen with normal video, it just happens here as
+ // * the motion of the chroma plane does not match the luma plane. //
+ c->mb_decision = 2;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ // Some formats want stream headers to be separate. //
+ if (oc->oformat->flags & AVFMT_GLOBALHEADER)
+ c->flags |= CODEC_FLAG_GLOBAL_HEADER;
+
+ return st;
+ }
+
+bool libav::exporter::open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st)
+ {
+
+ int ret;
+ AVCodecContext *c = st->codec;
+
+
+ // open the codec //
+ {
+ Mutex::ScopedLock lock(mutex);
+ ret = avcodec_open2(c, codec, NULL); //OPTIONS CAN GO HERE
+
+ }
+ if (ret < 0) {
+ //string e=av_err2str(ret);
+ cerr<<"Could not open video codec, avcodec_open2 returned "<<ret<<endl;
+ return false;
+ }
+
+ // allocate and init a re-usable frame //
+ frame = avcodec_alloc_frame();
+
+ // moved to constructor and freeing in destructor -- stills crashes the same
+ if (!frame) {
+ cerr<<"Could not allocate video frame "<<endl;
+ return false;
+ }
+
+ // Allocate the encoded raw picture. //
+ ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height);
+ if (ret < 0) {
+ //av_err2str(ret)<<
+ cerr<<"Could not allocate picture"<<endl;
+ return false;
+ }
+
+ // If the output format is not YUV420P, then a temporary YUV420P
+ // * picture is needed too. It is then converted to the required
+ // * output format. //
+ if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
+ ret = avpicture_alloc(&src_picture, AV_PIX_FMT_RGB24, c->width, c->height);
+ if (ret < 0) {
+ //<<av_err2str(ret)
+ cerr<<"Could not allocate temporary picture"<<endl;
+ return false;
+ }
+ }
+
+ // copy data and linesize picture pointers to frame //
+ *((AVPicture *)frame) = dst_picture;
+
+ outPixels = (uint8_t*)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, st->codec->width,st->codec->height));
+ return true;
+ }
+
+ int libav::exporter::open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st)
+ {
+ AVCodecContext *c;
+ int ret;
+
+ c = st->codec;
+
+ // open it //
+ mutex.lock();
+ ret = avcodec_open2(c, codec, NULL);
+ mutex.unlock();
+ if (ret < 0) {
+ //fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret));
+ exit(1);
+ }
+
+ // init signal generator //
+ t = 0;
+ tincr = 2 * M_PI * 110.0 / c->sample_rate;
+ // increment frequency by 110 Hz per second //
+ tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
+
+ if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
+ audio_input_frame_size = 10000;
+ else
+ audio_input_frame_size = c->frame_size;
+
+ /*
+ samples = av_malloc(audio_input_frame_size *
+ av_get_bytes_per_sample(c->sample_fmt) *
+ c->channels);
+ if (!samples) {
+ //fprintf(stderr, "Could not allocate audio samples buffer\n");
+ exit(1);
+ }
+ */
+ return audio_input_frame_size;
+ }
+
+ void libav::exporter::write_audio_frame(AVFormatContext *oc, AVStream *st,uint16_t *samples)
+ {
+ AVCodecContext *c;
+ AVPacket pkt = { 0 }; // data and size must be 0;
+ AVFrame *frame = avcodec_alloc_frame();
+ int got_packet, ret;
+
+ //av_init_packet(&pkt); 111013 NOT NECESSARY
+ c = st->codec;
+
+ //get_audio_frame(samples, audio_input_frame_size, c->channels);
+ frame->nb_samples = audio_input_frame_size;
+ uint8_t *sampleptr;
+ int bufsize=audio_input_frame_size * av_get_bytes_per_sample(c->sample_fmt) *c->channels;
+ if (samples) {
+ sampleptr=(uint8_t*)samples;
+ }
+ else {
+ sampleptr=new uint8_t[bufsize];
+ memset(sampleptr,0,bufsize);
+ }
+
+ avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,
+ sampleptr,
+ audio_input_frame_size *
+ av_get_bytes_per_sample(c->sample_fmt) *
+ c->channels, 0); //;
+ //frame->sample_rate=44100; //hard coded input rate- nope, this doesn't help
+ //frame->format=AV_SAMPLE_FMT_S16P;
+ //?? why is ffmpeg reporting fltp as the sample format??? doesn't seem to have an effect to change this though
+ ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
+ if (!samples) {
+ delete[] sampleptr;
+ }
+ if (ret < 0) {
+ //fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
+ exit(1);
+ }
+
+ if (!got_packet)
+ return;
+
+ pkt.stream_index = st->index;
+
+ //avcodec_free_frame(&frame); ///removed 091013
+
+
+ // Write the compressed frame to the media file. //
+ ret = av_interleaved_write_frame(oc, &pkt);
+ av_free_packet(&pkt);
+ if (ret != 0) {
+ //fprintf(stderr, "Error while writing audio frame: %s\n",
+ // av_err2str(ret));
+ exit(1);
+ }
+
+ }
+
+ void libav::exporter::write_audio_frame(AVFormatContext *oc, AVStream *st,AVPacket *pkt)
+ {
+
+ pkt->stream_index = st->index;
+
+ // Write the compressed frame to the media file. //
+ int ret = av_interleaved_write_frame(oc, pkt);
+ if (ret != 0) {
+ //fprintf(stderr, "Error while writing audio frame: %s\n",
+ // av_err2str(ret));
+ exit(1);
+ }
+ //avcodec_free_frame(&frame);
+ av_free_packet(pkt); ///added 091013
+ }
+
+ void libav::exporter::close_audio(AVFormatContext *oc, AVStream *st)
+ {
+ mutex.lock();
+ avcodec_close(st->codec);
+ mutex.unlock();
+
+ }
+
+ void libav::exporter::write_video_frame(AVFormatContext *oc, AVStream *st, uint8_t *pixels, bool keyframe)
+ {
+ int ret;
+
+ AVCodecContext *c = st->codec;
+
+ avpicture_fill(&src_picture, pixels, PIX_FMT_RGB24, c->width,c->height);
+ //avpicture_fill(&dst_picture, outPixels, PIX_FMT_YUV420P, c->width,c->height);
+
+ sws_scale(sws_ctx, src_picture.data, src_picture.linesize, 0, c->height, dst_picture.data, dst_picture.linesize);
+ //fill_yuv_image(&dst_picture, frame_count, c->width, c->height);
+ if (oc->oformat->flags & AVFMT_RAWPICTURE) {
+ // Raw video case - directly store the picture in the packet //
+ AVPacket pkt;
+ //av_init_packet(&pkt); ///removed 101013 NOT NECESSARY
+
+ pkt.flags |= AV_PKT_FLAG_KEY;
+ pkt.stream_index = st->index;
+ pkt.data = dst_picture.data[0];
+ pkt.size = sizeof(AVPicture);
+
+ ret = av_interleaved_write_frame(oc, &pkt);
+ av_free_packet(&pkt); ///added 091013
+ } else {
+ AVPacket pkt = { 0 };
+ int got_packet;
+
+ if (keyframe) pkt.flags |= AV_PKT_FLAG_KEY;
+
+ ret = avcodec_encode_video2(c, &pkt, frame, &got_packet);
+ if (ret < 0) {
+ //fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
+ exit(1);
+ }
+ // If size is zero, it means the image was buffered. //
+
+ if (!ret && got_packet && pkt.size) {
+ pkt.stream_index = st->index;
+
+ // Write the compressed frame to the media file. //
+ ret = av_interleaved_write_frame(oc, &pkt);
+ } else {
+ ret = 0;
+ }
+ av_free_packet(&pkt); ///added 091013
+ }
+
+
+
+
+ if (ret != 0) {
+ //fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret));
+ exit(1);
+ }
+ frame_count++;
+
+ //avcodec_free_frame(&frame);
+ }
+
+ void libav::exporter::close_video(AVFormatContext *oc, AVStream *st)
+ {
+ mutex.lock();
+ //avcodec_close(st->codec); //change 0706 to trace 2nd render issue
+ avcodec_close(audio_st->codec);
+ avcodec_close(video_st->codec);
+ //
+ //
+
+
+ //av_free(src_picture.data[0]); //removed to explore weird 2nd render crash.. seems to WORK -- seems that the picture data is owned elsewhere
+ av_free(dst_picture.data[0]);
+ av_free(frame); //removed to explore crash 2nd time render
+ //gives *** Error in `./rotord': corrupted double-linked list: 0x00007fd8b005bd60 ***
+ //where is frame initialised???
+ //moved to destructor
+
+
+ av_free(outPixels); //SIGSEV here???
+ mutex.unlock();
+ } \ No newline at end of file