diff options
| -rw-r--r-- | TODO | 3 | ||||
| -rw-r--r-- | configure.in | 10 | ||||
| -rw-r--r-- | etc/miav.conf | 2 | ||||
| -rw-r--r-- | src/mov_encoder.cc | 423 | ||||
| -rw-r--r-- | src/mov_encoder.h | 34 | 
5 files changed, 172 insertions, 300 deletions
| @@ -1,3 +1,6 @@ +// This is how it's done! +http://lists.debian.org/debian-user-spanish/2005/01/msg00380.html +  ==========================================================================   TASKS (client) diff --git a/configure.in b/configure.in index 1d48f84..4a4b171 100644 --- a/configure.in +++ b/configure.in @@ -43,8 +43,14 @@ fi  dnl ======================  dnl Check for Jpeg library  dnl ====================== -AC_CHECK_HEADER(jpeglib.h, , AC_MSG_ERROR([*** LibJpeg not found!])) -AC_CHECK_LIB(jpeg, jpeg_start_compress, ,  AC_MSG_ERROR([*** LibJpeg not found!])) +AC_CHECK_HEADER(jpeglib.h, , AC_MSG_ERROR([*** libJpeg not found!])) +AC_CHECK_LIB(jpeg, jpeg_start_compress, ,  AC_MSG_ERROR([*** libJpeg not found!])) + +dnl ====================== +dnl Check for Fame library +dnl ====================== +AC_CHECK_HEADER(fame.h, , AC_MSG_ERROR([*** libFame include files not found!])) +AC_CHECK_LIB(fame, fame_init, ,  AC_MSG_ERROR([*** libFame not found!]))  AC_SUBST(CFLAGS)  AC_SUBST(CPPFLAGS) diff --git a/etc/miav.conf b/etc/miav.conf index 5e8843f..240d2a0 100644 --- a/etc/miav.conf +++ b/etc/miav.conf @@ -17,7 +17,7 @@ pixel_width	= 1024  pixel_height	= 768  # How and where to connect to the miav server? -server_addr	= "192.168.0.10" +server_addr	= "127.0.0.1"  server_port	= 30000  # Where top store the files recieved by the server diff --git a/src/mov_encoder.cc b/src/mov_encoder.cc index 917cd32..4eae91b 100644 --- a/src/mov_encoder.cc +++ b/src/mov_encoder.cc @@ -39,6 +39,11 @@  /*   * $Log$ + * Revision 1.12  2005/05/05 20:41:38  deva + * + * Removed the last pieces of ffmpeg... replaced it with libfame... + * Not quite working yet, but all the major code is in place! + *   * Revision 1.11  2005/05/03 17:12:53  deva   * Fixed a bug (forgot to set the frametime).   * @@ -60,310 +65,156 @@  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"); fflush(stderr); -    exit(1); -  }  - -  //  efc->oformat = guess_format("avi", NULL, NULL); -  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"); fflush(stderr); -    switch((int)st) { -    case AVERROR_UNKNOWN     : fprintf(stderr, "unknown error\n"); fflush(stderr); -      break; -    case AVERROR_IO          : fprintf(stderr, "i/o error\n"); fflush(stderr); -      break; -    case AVERROR_NUMEXPECTED : fprintf(stderr, "number syntax expected in filename\n"); fflush(stderr); -      break; -    case AVERROR_INVALIDDATA : fprintf(stderr, "invalid data found\n"); fflush(stderr); -      break; -    case AVERROR_NOMEM       : fprintf(stderr, "not enough memory\n"); fflush(stderr); -      break; -    case AVERROR_NOFMT       : fprintf(stderr, "unknown format\n"); fflush(stderr); -      break; -    case AVERROR_NOTSUPP     : fprintf(stderr, "operation not supported\n"); fflush(stderr); -      break; -    } -    exit(1); -  } - -  //enc_codec = avcodec_find_encoder(CODEC_ID_MPEG4); -  enc_codec = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO); -  if(!enc_codec) { -    fprintf(stderr, "Unsupported codec for output stream\n"); fflush(stderr); -    exit(1); -  } -  avcodec_get_context_defaults(&st->codec); -  ecc = &st->codec; -  //ecc->codec_id = CODEC_ID_MPEG4;  -  ecc->codec_id = CODEC_ID_MPEG2VIDEO;  -  ecc->bit_rate = 8192*1000; -  //ecc->bit_rate = 4096*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) { -    fprintf(stderr, "Error while opening codec for stream\n"); fflush(stderr); -    exit(1); -  } - -  if(url_fopen(&efc->pb, filename, URL_RDWR) < 0) { -    fprintf(stderr, "Could not open '%s'\n", filename); fflush(stderr); -    exit(1); -  } - -  if(av_set_parameters(efc, NULL) < 0) { -    fprintf(stderr, "%s: Invalid encoding parameters\n", filename); fflush(stderr); -    exit(1); -  } - -  dump_format(efc, 0, filename, 1); - -  if(av_write_header(efc) < 0) { -    fprintf(stderr, "Could not write header for output file \n"); fflush(stderr); -    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; -  fprintf(stderr, "Video decoding\n"); -   -  // find the dvvideo decoder -  deccodec = avcodec_find_decoder(CODEC_ID_DVVIDEO); -  if (!deccodec) { -    fprintf(stderr, "codec not found\n"); fflush(stderr); -    exit(1); -  } -   -  dcc= avcodec_alloc_context(); +  // FIXME: Hmmm... should this be detected somewhere?! +  static int w = 720; +  static int h = 576; + +  // Initialize yuv strucutre. +  yuv.w = w; +  yuv.h = h; +  yuv.p = w; +  yuv.y = new unsigned char [w*h]; +  yuv.u = new unsigned char [w*h/4]; +  yuv.v = new unsigned char [w*h/4]; + +  ////////////LIBDV STUFF/////////////// -  // open it -  if (avcodec_open(dcc, deccodec) < 0) { -    fprintf(stderr, "could not open codec\n"); fflush(stderr); -    exit(1); -  } +  dvdecoder = NULL; // Initialize in encode method + +  /////////LIBFAME STUFF/////////// + +  // Allocate the output buffer. +  fame_buffer = new unsigned char [FAME_BUFFER_SIZE]; + +  // Open output file +  f=fopen(filename, "wb"); +  // FIXME: check f == NULL + +  // Open a new session of the fame library. +  fame_context = fame_open(); +  // FIXME: check fame_context == NULL +  // (If initialization was successful, it returns a non-null context which  +  // can then be used for subsequent library calls.) + +  /* +  typedef struct _fame_parameters_ { +    int width;                        // width of the video sequence +    int height;                       // height of the video sequence +    char const *coding;               // coding sequence +    int quality;                      // video quality +    int slices_per_frame;             // number of slices per frame +    unsigned int frames_per_sequence; // number of frames per sequence +    int frame_rate_num;               // numerator of frames per second +    int frame_rate_den;               // denominator of frames per second +    unsigned int shape_quality;       // binary shape quality +    unsigned int search_range;        // motion estimation search range +    unsigned char verbose;            // verbosity +  } fame_parameters_t; +  */ +  // width and height specify the size of each frames of the video sequence.  +  // Both must be multiple of 16. width and height must be less than 4096x4096 +  fame_par.width = 720; +  fame_par.height = 576; + +  // coding is a string of I, P or B characters representing the sequence of  +  // frames the encoder must produce. I frames are intra-coded frames (similar  +  // to JPEG), whereas P and B frames are motion compressed, respectively  +  // predicted from past reference (I or P) frame, or bidirectionally predicted  +  // from past and future reference frame. +  static const char coding[] = "I\0"; +  fame_par.coding = coding; + +  // quality is a percentage, which controls compression versus quality. +  fame_par.quality = 100; + +  // slices_per_frame is the number of frame slices per frame. More slices provide  +  // better error recovery. There must be at least one slice per frame, and at most  +  // height / 16 +  fame_par.slices_per_frame = fame_par.height / 16; + +  // frames_per_sequence is the maximum number of frames contained in a video  +  // sequence. +  fame_par.frames_per_sequence = 25 * 60 * 60 * 2; // 25 fps in two hours. + +  // frame_rate_num/frame_rate_den specify the number of frames per second for  +  // playback. +  fame_par.frame_rate_num = 25; // 25 / 1 fps = 25 fps +  fame_par.frame_rate_den = 1; + +  // shape_quality is percentage determing the average binary shape accuracy in  +  // video with arbitrary shape. +  fame_par.shape_quality = 100; + +  // search_range specifies the motion estimation search range in pixel unit.  +  // Small search ranges work best with slow motion videos, whereas larger search  +  // ranges are rather for fast motion videos. +  fame_par.search_range = 42; // FIXME: No idea what this should be!? + +  // verbose when set to 1 outputs information on copyright, modules used and  +  // current frame on standard error. +  fame_par.verbose = 0; + +  fame_init(fame_context, &fame_par, fame_buffer, FAME_BUFFER_SIZE); +  // FIXME: fame_init return a new context, or NULL if an error occurred.  }  MovEncoder::~MovEncoder()  { -  av_free(video_buffer); FREE(video_buffer); -  url_fclose(&efc->pb); +  int written = fame_close(fame_context); +  fwrite(fame_buffer, written, 1, f); +  fclose(f); +  delete [] fame_buffer; +  delete [] yuv.y; +  delete [] yuv.u; +  delete [] yuv.v;  }  void MovEncoder::encode(Frame *dvframe)  {    encode_video(dvframe); -  //  encode_audio(dvframe); +  encode_audio(dvframe);  } -#define WOW(x) fprintf(stderr, x); fflush(stderr); -  void MovEncoder::encode_video(Frame *dvframe)  { -  int ret; -  AVFrame *rawframe = avcodec_alloc_frame(); -  static int64_t timestamp = 0LL; -  int got_picture = 1; - -  //  uint8_t *ptr; -  //  int len; - -  //  ptr = (uint8_t *)dvframe->data; -  //  len = dvframe->size; - -  ///////////////////////// DECODE VIDEO - -  //  ret = avcodec_decode_video(dcc, rawframe, &got_picture, ptr, len); -  ret = avcodec_decode_video(dcc, rawframe, &got_picture, dvframe->data, dvframe->size); -  rawframe->pts = timestamp; -  timestamp += 40000; -  fprintf(stderr, "ret fra decode: %d\n", ret); fflush(stderr); - -  if(ret <= 0) { -    fprintf(stderr, "Decoder fuckup during video decoding!\n"); fflush(stderr); -    return; -  } -  ///////////////////////// ENCODE VIDEO -   -  ret = avcodec_encode_video(ecc, video_buffer, VIDEO_BUFFER_SIZE, rawframe); - -  if(ret <= 0) { -    fprintf(stderr, "MovEncoder fuckup during video encoding!\n"); fflush(stderr); -    return; +  // Decode DV Frame to YUV +  unsigned char *pixels[3]; +  int pitches[3]; + +  pitches[0] = yuv.w; +  pitches[1] = yuv.h; +  pitches[2] = yuv.p; +  pixels[0] = yuv.y; +  pixels[1] = yuv.u; +  pixels[2] = yuv.v; + +  if(!dvdecoder) { +    dvdecoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE); +    dvdecoder->quality = DV_QUALITY_BEST; + +    dv_parse_header(dvdecoder, dvframe->data); +    //dv_parse_packs(decoder, frame->data); // Not needed anyway! +     +    dvdecoder->system = e_dv_system_625_50;  // PAL lines, PAL framerate +    dvdecoder->sampling = e_dv_sample_422;  // 4 bytes y, 2 bytes u, 2 bytes v +    dvdecoder->std = e_dv_std_iec_61834; +    dvdecoder->num_dif_seqs = 12;    } -  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); +  dv_decode_full_frame(dvdecoder,  +                       dvframe->data,  +                       e_dv_color_yuv,  +                       pixels, +                       pitches); +   +  // Encode YUV frame and write it to disk. +  fame_start_frame(fame_context, &yuv, 0); +  int written = fame_encode_slice(fame_context); +  fwrite(fame_buffer, written, 1, f); +  fame_end_frame(fame_context,0);  } -#define INBUF_SIZE 48000  void MovEncoder::encode_audio(Frame *dvframe)  { -  uint8_t *decbuf; - -  ///////////////////////// DECODE AUDIO -  { -    AVCodec *codec; -    AVCodecContext *c= NULL; -    int out_size, size, len; -    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr; -  -    printf("Audio decoding\n"); -      -    /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ -    memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); -  -    /* find the mpeg audio decoder */ -    codec = avcodec_find_decoder(CODEC_ID_DVAUDIO); -    if (!codec) { -      fprintf(stderr, "codec not found\n"); -      exit(1); -    } -  -    c= avcodec_alloc_context(); -  -    /* open it */ -    if (avcodec_open(c, codec) < 0) { -      fprintf(stderr, "could not open codec\n"); -      exit(1); -    } -      -    decbuf = (uint8_t*)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); -  -      -    /* decode until eof */ -    size = dvframe->size; -    inbuf_ptr = dvframe->data; - -    while (size > 0) { -      len = avcodec_decode_audio(c, (short *)decbuf, &out_size,  -                                 inbuf_ptr, size); -      if (len < 0) { -        fprintf(stderr, "Error while decoding\n"); -        exit(1); -      } -      if (out_size > 0) { -        /* if a frame has been decoded, output it */ -      } -      size -= len; -      inbuf_ptr += len; -    } -  -    avcodec_close(c); -    av_free(c); -  } -  ///////////////////////// ENCODE AUDIO -  {   -    char filename[]="audio.mp2"; -    AVCodec *codec; -    AVCodecContext *c= NULL; -    int frame_size, i, j, out_size, outbuf_size; -    FILE *f; -    short *samples; -    float t, tincr; -    uint8_t *outbuf; -  -    printf("Audio encoding\n"); -  -    /* find the MP2 encoder */ -    codec = avcodec_find_encoder(CODEC_ID_MP2); -    if (!codec) { -      fprintf(stderr, "codec not found\n"); -      exit(1); -    } -  -    c= avcodec_alloc_context(); -      -    /* put sample parameters */ -    c->bit_rate = 64000; -    c->sample_rate = 44100; -    c->channels = 2; -  -    /* open it */ -    if (avcodec_open(c, codec) < 0) { -      fprintf(stderr, "could not open codec\n"); -      exit(1); -    } -      -    /* the codec gives us the frame size, in samples */ -    frame_size = c->frame_size; -    samples = (short int*)malloc(frame_size * 2 * c->channels); -    outbuf_size = 10000; -    outbuf = (uint8_t*)malloc(outbuf_size); -  -    f = fopen(filename, "a"); -    if (!f) { -      fprintf(stderr, "could not open %s\n", filename); -      exit(1); -    } -          -    // encode the sample -    out_size = avcodec_encode_audio(c, outbuf, outbuf_size, (const short int*)decbuf); -    fwrite(outbuf, 1, out_size, f); - -    fclose(f); -    free(outbuf); -    free(samples); -  -    avcodec_close(c); -    av_free(c); -  } - -  // Don't free outputbuffer until this point! -  free(decbuf); +  // TODO: Do some audio stuff here sometime!  } diff --git a/src/mov_encoder.h b/src/mov_encoder.h index 2e3eca3..17412a2 100644 --- a/src/mov_encoder.h +++ b/src/mov_encoder.h @@ -36,6 +36,11 @@  /*   * $Log$ + * Revision 1.6  2005/05/05 20:41:38  deva + * + * Removed the last pieces of ffmpeg... replaced it with libfame... + * Not quite working yet, but all the major code is in place! + *   * Revision 1.5  2005/05/03 08:31:59  deva   * Removed the error object, and replaced it with a more generic info object.   * @@ -49,13 +54,20 @@  #include <stdio.h>  #include <stdlib.h>  #include <string.h> -#include <avformat.h> + +// Use libfame +#include <fame.h> + +// Use libdv +#include <libdv/dv.h> +#include <libdv/dv_types.h>  #include "frame.h"  #include "util.h" -#define VIDEO_BUFFER_SIZE	(1024*1024)	// FIXME: One size fits all... +// size specifies the length of the buffer.  +#define FAME_BUFFER_SIZE	(2*1024*1024)	// FIXME: One size fits all...  class MovEncoder {   public: @@ -67,16 +79,16 @@ class MovEncoder {    void encode_video(Frame *frame);    void encode_audio(Frame *frame); -  // Decoder -  AVFormatContext *dfc; -  AVCodecContext *dcc; +  // buffer is the buffer where encoded data will be written to. It must be large  +  // enough to contain a few frames. +  unsigned char *fame_buffer; +  fame_parameters_t fame_par; +  fame_context_t *fame_context; +  fame_yuv_t yuv; +  FILE *f; -  // Encoder -  AVFormatContext *efc; -  AVCodecContext *ecc; -  AVPacket epkt; -  unsigned char *video_buffer; -  //  AVPacket pkt; +  // libdv decoder + 	dv_decoder_t *dvdecoder;  };  #endif | 
