/**
 *  GraphTFT plugin for the Video Disk Recorder 
 * 
 *  mpeg2encoder.c - A plugin for the Video Disk Recorder
 *
 *  (c) 2004 Lars Tegeler, Sascha Volkenandt  
 *
 * This code is distributed under the terms and conditions of the
 * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
 *
 * $Id: mpeg2encoder.c,v 1.3 2004/05/09 10:20:57 tegeler Exp $
 *
 **/

//The most part of this Code is from the MMS V.2 Project:

#include "mpeg2encoder.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include "avcodec.h"
#include "common.h"

AVCodecContext codec_context;
UINT8 *mpg_buf, *pic_dat;
AVFrame yuv_buf;
AVPicture pic;

void mpeg_init(int video_width, int video_height, int fps){

  AVCodec *codec;
  AVCodecContext *c;
  int i = 0;

  avcodec_init();
  avcodec_register_all();
    
  codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
  if (!codec) {
    d(4, "mpeg2encoder.c: codec not found\n");
    exit(1);
  }

  c = &codec_context;

  /* encoder parameters */
  memset(c, 0, sizeof(*c) );

  avcodec_get_context_defaults(c);

  c->bit_rate   = 0;
  c->width      = video_width;
  c->height     = video_height;
  #if LIBAVCODEC_BUILD >= 4754
    c->time_base=(AVRational){1, fps};
  #else
    c->frame_rate = fps;
    c->frame_rate_base = 1;
  #endif
  c->gop_size   = 1; /* with a gop (keyframe interval) length of <= 1 
			avcodec enters 'I-Frame only' mode :-) */
  c->flags = CODEC_FLAG_QSCALE;

  if (avcodec_open(c, codec) < 0) {
    d(4, "mpeg2encoder.c: codec could not be opened\n");
    exit(1);
  }

  /* prepare necessary buffers */
  pic_dat = (UINT8 *) malloc( avpicture_get_size(PIX_FMT_YUV420P, video_width, video_height) );
  memset(pic_dat, 0, avpicture_get_size(PIX_FMT_YUV420P, video_width, video_height)); 
  mpg_buf = (UINT8 *) malloc(1000000); /* if segfaults are generated in encode_video, raise this size */
  avpicture_fill(&pic, pic_dat, PIX_FMT_YUV420P, video_width, video_height);

  /* prepare an AVPicture out of our buffers */
  yuv_buf = *avcodec_alloc_frame();

  /* the lower the better quality, but also larger images => slower to
     transfer */
  yuv_buf.quality = 2;

  /* copy the data from avpicture to avframe */
  for(i=0; i<4; ++i){
    yuv_buf.data[i]= pic.data[i];
    yuv_buf.linesize[i]= pic.linesize[i];
  }
}

mpeg_frame mpeg_draw(UINT8* buf){

  mpeg_frame new_frame;
  const int width = 720, height = 576;
  int i;

  AVPicture avpsrc;

  avpicture_fill(&avpsrc, buf, PIX_FMT_RGBA32, width, height);
  img_convert(&pic, PIX_FMT_YUV420P, &avpsrc, PIX_FMT_RGBA32, width, height);

  /* copy the data from avpicture to avframe */
    
  for (i=0; i<4; ++i){
    yuv_buf.data[i]= pic.data[i];
    yuv_buf.linesize[i]= pic.linesize[i];
  }

  new_frame.data = mpg_buf; /* mpg_buf just gives us a pointer to mpeg data
			       and tells us how large it is */


  /* raise 100000 if this segfaults */
  new_frame.size = avcodec_encode_video(&codec_context, mpg_buf, 1000000, &yuv_buf);

  return new_frame;
}

void mpeg_deinit(){
  avcodec_close(&codec_context);
  free(pic_dat);
  free(mpg_buf);
}
