diff options
Diffstat (limited to 'src/mov_encoder.cc')
-rw-r--r-- | src/mov_encoder.cc | 207 |
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); +} |