summaryrefslogtreecommitdiff
path: root/rotord/libavexporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'rotord/libavexporter.cpp')
-rw-r--r--rotord/libavexporter.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/rotord/libavexporter.cpp b/rotord/libavexporter.cpp
new file mode 100644
index 0000000..a46de5a
--- /dev/null
+++ b/rotord/libavexporter.cpp
@@ -0,0 +1,124 @@
+#include "libavexporter.h"
+
+bool libav::exporter::setup(int w,int h, int bitRate, int frameRate, std::string container){
+ // Initialize libavcodec, and register all codecs and formats. //
+ av_register_all();
+
+ this->w=w;
+ this->h=h;
+ this->bitRate=bitRate;
+ this->frameRate=frameRate;
+ this->container=container;
+
+ 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;
+
+ // Add the audio and video streams using the default format codecs
+ // * and initialize the codecs. //
+ video_st = NULL;
+ audio_st = NULL;
+
+ 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);
+ }
+
+ //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 = 10; /* emit one intra frame every ten frames */
+ video_st->codec->pix_fmt = PIX_FMT_YUV420P;
+
+ // Now that all the parameters are set, we can open the audio and
+ // * video codecs and allocate the necessary encode buffers. //
+ if (video_st)
+ open_video(oc, video_codec, video_st);
+ if (audio_st)
+ open_audio(oc, audio_codec, audio_st);
+
+ av_dump_format(oc, 0, filename.c_str(), 1);
+
+ // open the output file, if needed //
+ if (!(fmt->flags & AVFMT_NOFILE)) {
+ 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;
+ }
+ }
+
+ // Write the stream header, if any. //
+ int ret = avformat_write_header(oc, NULL);
+ if (ret < 0) {
+ //std::cerr <<"Error occurred when opening output file:" << av_err2str(ret) << std::endl;
+ return false;
+ }
+
+ frame=0;
+ return true;
+}
+bool libav::exporter::encodeFrame(unsigned char *pixels){
+ // 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;
+
+ uint16_t *samples = av_malloc(audio_input_frame_size *
+ av_get_bytes_per_sample(audio_st->codec->sample_fmt) *
+ audio_st->codec->channels); //dummy audio
+
+ // 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);
+ }
+
+ av_free(samples);
+
+ std::cerr << "encoded frame " << outputframe << std::endl;
+ outputframe++;
+
+ return true;
+}
+void libav::exporter::finishRecord(){
+ // 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. //
+ avio_close(oc->pb);
+
+ // free the stream //
+ avformat_free_context(oc);
+} \ No newline at end of file