diff options
author | deva <deva> | 2008-03-17 09:10:42 +0000 |
---|---|---|
committer | deva <deva> | 2008-03-17 09:10:42 +0000 |
commit | 2f10a73cbbe4333e2a41e87a94eda7fb3d442dc5 (patch) | |
tree | cc023927be890bb4880d6c97ddaf055041c512ea /miavd/ffmpeg_encoder.cc | |
parent | 6ae128fc80dd8a32ec6f062c7767ced32e9ba495 (diff) |
Major code changes... FFMPEG introduced. Project splitup into subfolders.
Diffstat (limited to 'miavd/ffmpeg_encoder.cc')
-rw-r--r-- | miavd/ffmpeg_encoder.cc | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/miavd/ffmpeg_encoder.cc b/miavd/ffmpeg_encoder.cc new file mode 100644 index 0000000..2f73c4c --- /dev/null +++ b/miavd/ffmpeg_encoder.cc @@ -0,0 +1,204 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * mov_encoder_thread.cc + * + * Tue May 17 16:00:01 CEST 2005 + * Copyright 2005 Bent Bisballe + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of MIaV. + * + * MIaV 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. + * + * MIaV 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 MIaV; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include <config.h> +#include "ffmpeg_encoder.h" +#include <errno.h> +#include "miav_config.h" +#include <math.h> + +#include <ffmpeg/avcodec.h> +#include <ffmpeg/avformat.h> + +#define AUDIO_BUFFER_SIZE DV_AUDIO_MAX_SAMPLES +//(DV_AUDIO_MAX_SAMPLES * sizeof(int16_t)) + +FFMpegEncoder::FFMpegEncoder(const char *clientip, const char *cpr) +{ + MIaV::info->info("FFMpegEncoder"); + + // init encoder + output = new FFOutput(cpr, clientip); + + // Init DV decoder + avcodec_init(); + + // Video + dvvcodec = avcodec_find_decoder(CODEC_ID_DVVIDEO); + if(!dvvcodec) MIaV::info->error("Could not find DV Video codec."); + + dvvcontext = avcodec_alloc_context(); + if(avcodec_open(dvvcontext, dvvcodec) < 0) MIaV::info->error("Could not open DV Video codec."); + + // Audio + dvacodec = avcodec_find_decoder(CODEC_ID_PCM_S16LE); + if(!dvacodec) MIaV::info->error("Could not find DV Audio codec."); + + dvacontext = avcodec_alloc_context(); + if(avcodec_open(dvacontext, dvacodec) < 0) MIaV::info->error("Could not open DV Audio codec."); + + frame_number = 0; + + audio_buffer[0] = (int16_t*)calloc(AUDIO_BUFFER_SIZE, sizeof(int16_t)); + audio_buffer[1] = (int16_t*)calloc(AUDIO_BUFFER_SIZE, sizeof(int16_t)); + + sin_cnt = 0; + decoder = NULL; + + // CBuffer init + cbufferdatasize = 0; + cbuffer_size = AUDIO_BUFFER_SIZE * 4; // Buffer max, 2 frames * 2 channels. + cbuffer = (int16_t *)malloc(cbuffer_size * sizeof(int16_t)); + pbegin = 0; +} + +//#include <unistd.h> +FFMpegEncoder::~FFMpegEncoder() +{ + MIaV::info->info("~FFMpegEncoder..."); + + delete output; + + free(audio_buffer[0]); + free(audio_buffer[1]); + + free(cbuffer); + dv_decoder_free(decoder); + + MIaV::info->info("~FFMpegEncoder::done"); +} + +void FFMpegEncoder::encode(Frame* frame) +{ + if(frame_number % 250 == 0) + MIaV::info->info("Got frame %d ...", frame_number); + + if(frame == NULL) { + MIaV::info->info("FFMpegEncoder::encode - NULL frame detected."); + // Terminate + return; + } + + if(frame->endOfFrameStream) { + // MIaV::info->info("endOfStream"); + return; + } + + frame->number = frame_number; + +#if 0 + // Use to half the framerate. + if(frame_number % 2 == 0) { + frame_number ++; + return; + } +#endif + + // + // VIDEO + // + FFFrame *vfrm = new FFFrame(); + vfrm->avframe = avcodec_alloc_frame(); + vfrm->codec_context = dvvcontext; + int got_picture; + int pos = avcodec_decode_video(dvvcontext, vfrm->avframe, &got_picture, frame->data, frame->size); + if(!got_picture) + MIaV::info->warn("Decoding did not result in a picture!"); + output->writeFrame(vfrm); + + // + // AUDIO + // + FFFrame *afrm = new FFFrame(); + afrm->pcmdatasize = output->audio_st->codec->frame_size * 2 * sizeof(int16_t); + afrm->pcmdata = (int16_t*)malloc(afrm->pcmdatasize); + //afrm->avframe = avcodec_alloc_frame(); + afrm->codec_context = dvacontext; + + if(frame->mute) { + // Overwrite audiobuffer with dummy data + double volume = 1000; // Min:= 0 - Max := 32000 + double frequency = 440; // in Hz + + for(int cnt = 0; cnt < 48000/25; cnt++) { + sin_cnt++; + double sin_val = (((double)sin_cnt / (double)48000) * (double)M_PI) * frequency; + audio_buffer[0][cnt] = audio_buffer[1][cnt] = (short int)(sin(sin_val) * volume); + } + } else { + // Decode audio from dv frame + if(!decoder) { + decoder = dv_decoder_new(FALSE, FALSE, FALSE); + decoder->quality = DV_QUALITY_BEST; + + dv_parse_header(decoder, frame->data); + + decoder->system = e_dv_system_625_50; // PAL lines, PAL framerate + decoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v + decoder->std = e_dv_std_iec_61834; + decoder->num_dif_seqs = 12; + } + + // Decode audio using libdv + int frames = dv_decode_full_audio( decoder, frame->data, audio_buffer ); + + } + + // Write new data to cbuffer + int pend = pbegin + cbufferdatasize; + for(int i = 0; i < (48000/25)*2; i++) { + cbuffer[(pend + i) % cbuffer_size] = audio_buffer[i%2][i/2]; + } + cbufferdatasize += (48000/25)*2; + + // Read out full ffmpeg frames from cbuffer. + while(cbufferdatasize >= output->audio_st->codec->frame_size * 2) { + for(int i = 0; i < output->audio_st->codec->frame_size * 2; i++) { + afrm->pcmdata[i] = cbuffer[(pbegin + i) % cbuffer_size]; + } + + cbufferdatasize -= output->audio_st->codec->frame_size * 2; + pbegin += output->audio_st->codec->frame_size * 2; + + output->writeFrame(afrm); + } + + + frame_number ++; + + av_free(vfrm->avframe); + delete vfrm; + + free(afrm->pcmdata); + delete afrm; + + delete frame; +} + +void FFMpegEncoder::setSaveState(n_savestate savestate) +{ + output->setSaveState(savestate); +} |