summaryrefslogtreecommitdiff
path: root/src/mov_encoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mov_encoder.cc')
-rw-r--r--src/mov_encoder.cc207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/mov_encoder.cc b/src/mov_encoder.cc
new file mode 100644
index 0000000..92b2657
--- /dev/null
+++ b/src/mov_encoder.cc
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * RTVideoRec Realtime video recoder and encoder for Linux
+ *
+ * Copyright (C) 2004 Bent Bisballe
+ * Copyright (C) 2004 B. Stultiens
+ * Copyright (C) 2004 Koen Otter and Glenn van der Meyden
+ *
+ * This program 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 program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mov_encoder.h"
+
+//av_alloc_format_context
+//av_destruct_packet_nofree
+
+MovEncoder::MovEncoder(const char *filename)
+{
+ //////////////////// GLOBAL INIT
+ av_register_all();
+
+ //////////////////// ENCODE INIT
+ AVStream *st;
+ AVCodec *enc_codec;
+
+ if(!(efc = av_alloc_format_context())) {
+ fprintf(stderr, "Could not alloc output format context\n");
+ exit(1);
+ }
+
+ efc->oformat = guess_format("mpeg", NULL, NULL);
+ //efc->oformat = guess_format(NULL, filename, NULL);
+
+ if(!(st = av_new_stream(efc, 0))) {
+ fprintf(stderr, "Could not alloc stream\n");
+ switch((int)st) {
+ case AVERROR_UNKNOWN : printf("unknown error\n");
+ break;
+ case AVERROR_IO : printf("i/o error\n");
+ break;
+ case AVERROR_NUMEXPECTED : printf("number syntax expected in filename\n");
+ break;
+ case AVERROR_INVALIDDATA : printf("invalid data found\n");
+ break;
+ case AVERROR_NOMEM : printf("not enough memory\n");
+ break;
+ case AVERROR_NOFMT : printf("unknown format\n");
+ break;
+ case AVERROR_NOTSUPP : printf("operation not supported\n");
+ break;
+ }
+ exit(1);
+ }
+
+ enc_codec = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO);
+ if(!enc_codec) {
+ printf("Unsupported codec for output stream\n");
+ exit(1);
+ }
+ avcodec_get_context_defaults(&st->codec);
+ ecc = &st->codec;
+ ecc->codec_id = CODEC_ID_MPEG2VIDEO;
+ ecc->bit_rate = 8192*1000;
+ ecc->bit_rate_tolerance = 8000*1000;
+ ecc->frame_rate = 25;
+ ecc->frame_rate_base = 1;
+
+ ecc->width = 720;
+ ecc->height = 576;
+ ecc->pix_fmt = PIX_FMT_YUV420P;
+ ecc->gop_size = 0;
+ ecc->mb_decision = FF_MB_DECISION_SIMPLE;
+ ecc->qmin = 2;
+ ecc->qmax = 31;
+ ecc->mb_qmin = 2;
+ ecc->mb_qmax = 31;
+ ecc->max_qdiff = 3;
+ ecc->qblur = 0.5;
+ ecc->qcompress = 0.5;
+ ecc->rc_eq = "tex^qComp";
+ ecc->debug= 0;
+
+ ecc->rc_override_count=0;
+ ecc->rc_max_rate = 0;
+ ecc->rc_min_rate = 0;
+ ecc->rc_buffer_size = 0;
+ ecc->rc_buffer_aggressivity = 1.0;
+ ecc->rc_initial_cplx= 0;
+ ecc->i_quant_factor = -0.8;
+ ecc->b_quant_factor = 1.25;
+ ecc->i_quant_offset = 0.8;
+ ecc->b_quant_offset = 1.25;
+ ecc->dct_algo = 0;
+ ecc->idct_algo = 0;
+ ecc->strict_std_compliance = 0;
+ ecc->me_method = ME_EPZS;
+
+ if(avcodec_open(&st->codec, enc_codec) < 0) {
+ printf("Error while opening codec for stream\n");
+ exit(1);
+ }
+
+ if(url_fopen(&efc->pb, filename, URL_RDWR) < 0) {
+ fprintf(stderr, "Could not open '%s'\n", filename);
+ exit(1);
+ }
+
+ if(av_set_parameters(efc, NULL) < 0) {
+ fprintf(stderr, "%s: Invalid encoding parameters\n", filename);
+ exit(1);
+ }
+
+ dump_format(efc, 0, filename, 1);
+
+ if(av_write_header(efc) < 0) {
+ fprintf(stderr, "Could not write header for output file \n");
+ exit(1);
+ }
+
+ video_buffer = (unsigned char *)av_malloc(VIDEO_BUFFER_SIZE);
+
+ av_init_packet(&epkt);
+
+ epkt.stream_index = efc->streams[0]->index;
+
+ // ecc = &efc->streams[0]->codec;
+
+ //////////////////// DECODE INIT
+ AVCodec *deccodec;
+ // AVCodecContext *dcc= NULL;
+ printf("Video decoding\n");
+
+ /* find the dvvideo decoder */
+ deccodec = avcodec_find_decoder(CODEC_ID_DVVIDEO);
+ if (!deccodec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ dcc= avcodec_alloc_context();
+
+ /* open it */
+ if (avcodec_open(dcc, deccodec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+}
+
+MovEncoder::~MovEncoder()
+{
+ av_free(video_buffer);
+ url_fclose(&efc->pb);
+}
+
+void MovEncoder::encode(DVFrame *dvframe)
+{
+ int ret;
+ AVFrame *rawframe = avcodec_alloc_frame();
+
+ ///////////////////////// DECODE
+ uint8_t *ptr;
+ int got_picture = 1;
+ int len;
+
+ ptr = (uint8_t *)dvframe->frame;
+ len = sizeof(dvframe->frame);
+
+ ret = avcodec_decode_video(dcc,//&dfc->streams[0]->codec,
+ rawframe, &got_picture, ptr, len);
+
+ if(!ret) {
+ printf("Decoder fuckup!\n");
+ return;
+ }
+
+ ///////////////////////// ENCODE
+
+ ret = avcodec_encode_video(ecc, video_buffer, VIDEO_BUFFER_SIZE, rawframe);
+
+ if(!ret) {
+ printf("MovEncoder fuckup!\n");
+ return;
+ }
+
+ epkt.data = video_buffer;
+ epkt.size = ret;
+
+ if(ecc->coded_frame) epkt.pts = ecc->coded_frame->pts;
+
+ if(ecc->coded_frame && ecc->coded_frame->key_frame) epkt.flags |= PKT_FLAG_KEY;
+
+ av_write_frame(efc, &epkt);
+
+ av_free(rawframe);
+}