www.pudn.com > w_ipp-sample-media_p_5.0.017.zip > video_enc_con.cpp


// 
//               INTEL CORPORATION PROPRIETARY INFORMATION 
//  This software is supplied under the terms of a license agreement or 
//  nondisclosure agreement with Intel Corporation and may not be copied 
//  or disclosed except in accordance with the terms of that agreement. 
//        Copyright (c) 2005 Intel Corporation. All Rights Reserved. 
// 
 
//ipp 
#include "ipp.h" 
 
//mpeg2 
#include "umc_mpeg2_video_encoder.h" 
//h264 
#include "umc_h264_video_encoder.h" 
//mpeg4 
#include "umc_mpeg4_video_encoder.h" 
//h263 
#include "umc_h263_video_encoder.h" 
//h261 
#include "umc_h261_video_encoder.h" 
//vm 
#include "vm_time.h" 
 
using namespace UMC; 
 
#include "utils.h" 
 
#define MAX_FILELEN 1024 
 
int encode(VideoEncoder *p_vidEncoder, 
           VideoEncoderParams *p_vidEncoderParams, 
           UMCReadYUV *YUVReader, 
           vm_char   *DstFileName, 
           int    *encoded_size, 
           double *enc_time) 
{ 
  VideoData *p_dataIn = NULL; 
  MediaData *p_dataOut = NULL; 
  int       mFrameCount = 0, err_code = 0; 
  int       mWidth, mHeight, mSize, mTotalFrames; 
  int       mCompSize, mRetval; 
  size_t    len; 
  FILE      *outFile = NULL; 
  vm_tick   tf, ts, te; 
  double    time = 0.0; 
  Ipp8u     *pY = NULL, *pU = NULL, *pV = NULL, *pBS = NULL; 
 
  mWidth = p_vidEncoderParams->src_width; 
  mHeight = p_vidEncoderParams->src_height; 
  mTotalFrames = p_vidEncoderParams->numFramesToEncode; 
  mSize = mWidth * mHeight; 
 
  p_dataIn = new VideoData; 
  p_dataOut = new MediaData; 
 
  if ((!p_dataIn) || (!p_dataOut)) { 
    fprintf(stderr,"Error: Can't allocate Media Data objects \n"); 
    err_code=7; goto free_memories; 
  } 
 
  outFile = vm_file_open(DstFileName, VM_STRING("wb")); 
 
  if (!outFile) { 
    fprintf(stderr,"Error: Can't open output file '%s'\n", DstFileName); 
    err_code=9; goto free_memories; 
  } 
 
  pY = pU = pV = pBS = NULL; 
  pY = new Ipp8u[mSize]; 
  pU = new Ipp8u[mSize]; 
  pV = new Ipp8u[mSize]; 
  pBS = new Ipp8u[2*mSize]; 
 
  if (( !pY ) || ( !pU ) || ( !pV )|| ( !pBS )) { 
    fprintf(stderr,"Error: Can't allocate data buffers! \n"); 
    err_code=10; goto free_memories; 
  } 
 
  p_dataIn->SetDest(pY, pU, pV); 
  p_dataIn->SetPitch(YUVReader->mWidth, YUVReader->mWidthChroma, YUVReader->mWidthChroma); 
  p_dataIn->SetColorFormat(YUVReader->mColorFormat); 
 
  p_dataOut->SetBufferPointer(pBS, 2*mSize); 
 
  tf = vm_time_get_frequency(); 
  time = 0; 
  mCompSize = 0; 
 
  while (mFrameCount < mTotalFrames) { 
    printf("Encoding frame: %d ... ",mFrameCount); 
 
    if (YUVReader->LoadNextFrame(p_dataIn) != YUV_ERROR_NOERR) { 
      fprintf(stderr,"Error: Can't read next %d source frame!\n", mFrameCount); 
      break; 
    } 
 
    ts = vm_time_get_tick(); 
    mRetval = p_vidEncoder->GetFrame(p_dataIn, p_dataOut); 
    te = vm_time_get_tick(); 
    time += (double)(vm_var64s)(te - ts) / (double)(vm_var64s)tf; 
 
    if(mRetval != UMC_OK && mRetval != UMC_NOT_ENOUGH_DATA){ 
      fprintf(stderr,"Error: encoding failed at %d source frame (exit with %d)!\n", mFrameCount, mRetval); 
      err_code = 13; 
      break; 
    } 
 
    len = fwrite(p_dataOut->GetDataPointer(), 1, p_dataOut->GetDataSize(), outFile); 
    mCompSize += (int)len; 
    if (len != p_dataOut->GetDataSize()) { 
      fprintf(stderr,"Error: Couldn't write to output file '%s'\n", DstFileName); 
      err_code=11; goto free_memories; 
    } 
 
    printf(" done\n" ); 
    mFrameCount ++; 
  } 
 
  while ((mRetval == UMC_OK )&&(p_dataOut->GetDataSize()>0)) { 
    ts = vm_time_get_tick(); 
    mRetval = p_vidEncoder->GetFrame(NULL, p_dataOut); 
    te = vm_time_get_tick(); 
    time += (double)(vm_var64s)(te - ts) / (double)(vm_var64s)tf; 
 
    if(mRetval != UMC_OK && mRetval != UMC_END_OF_STREAM){ 
      fprintf(stderr,"Error: encoding failed at outputing buffered frames (exit with %d)!\n", mRetval); 
      err_code = 13; // Incorrectly processed buffered frames encoding request!!! 
      break; 
    } 
 
    len = fwrite(p_dataOut->GetDataPointer(), 1, p_dataOut->GetDataSize(), outFile); 
    mCompSize += (int)len; 
    if (len != p_dataOut->GetDataSize()) { 
      fprintf(stderr,"Error: Couldn't write to output file '%s'\n", DstFileName); 
      err_code=12; goto free_memories; 
    } 
 
    mFrameCount++; 
  } 
 
free_memories: 
  if (p_dataIn) delete p_dataIn; 
  if (p_dataOut) delete p_dataOut; 
  if (pY) delete [] pY; 
  if (pV) delete [] pV; 
  if (pU) delete [] pU; 
  if (pBS) delete [] pBS; 
  if (outFile) fclose(outFile); 
 
  *enc_time = time; 
  *encoded_size = mCompSize; 
  return err_code; 
} 
 
void PrintHelp(vm_char *prog_name) 
{ 
  vm_string_printf(VM_STRING("Usage: %s [Options] [m2|m4|h264|h263|h261] InputParFile OutputEncodedFile\n\n"), prog_name); 
  vm_string_printf(VM_STRING("Options: \n")); 
  vm_string_printf(VM_STRING("   [-t num]  - number of threads for encoding\n")); 
  vm_string_printf(VM_STRING("   [-r]      - enables threading of read/encode/write\n")); 
  vm_string_printf(VM_STRING("   [-y dir]  - directory of YUV files\n")); 
  vm_string_printf(VM_STRING("   [-u file] - file for dumping perfomance info\n")); 
  vm_string_printf(VM_STRING("\n")); 
} 
 
int main(int argc, vm_char *argv[]) 
{ 
  vm_char            SrcFileName[MAX_FILELEN]; 
  vm_char            *ParFileName = NULL; 
  vm_char            *DstFileName = NULL; 
  UMCReadYUV         YUVReader[1]; 
  VideoEncoder       *p_vidEncoder = NULL; 
  VideoEncoderParams *p_vidEncoderParams = NULL; 
  ColorFormat        mColorFormat = YV12; 
  FILE *perf_file = NULL; 
  vm_char *p; 
  int     encoded_size; 
  double  enc_time, ov_time; 
  vm_tick tf, ts, te; 
  int numThreads = 1; 
  int rw_threading = 0; 
  int codec_number = 0; 
  int err_code = 0; 
  int i; 
  int mWidth; 
  int mHeight; 
  int mTotalFrames; 
  double size_ratio; 
 
  *SrcFileName = 0; 
 
  for (i = 1; i < argc; i++) 
  { 
    if (vm_string_strcmp(argv[i], VM_STRING("m2")) == 0) { 
      codec_number = 2; 
    } else 
    if (vm_string_strcmp(argv[i], VM_STRING("m4")) == 0) { 
      codec_number = 4; 
    } else 
    if (vm_string_strcmp(argv[i], VM_STRING("h264")) == 0) { 
      codec_number = 264; 
    } else 
    if (vm_string_strcmp(argv[i], VM_STRING("h263")) == 0) { 
      codec_number = 263; 
    } else 
    if (vm_string_strcmp(argv[i], VM_STRING("h261")) == 0) { 
      codec_number = 261; 
    } else 
    if ('-' != argv[i][0]) { 
      if (NULL == ParFileName) { 
        ParFileName = argv[i]; 
      } else { 
        DstFileName = argv[i]; 
      } 
    } else 
    switch (argv[i][1]) 
    { 
      case 'y': 
        i++; 
        vm_string_strcpy(SrcFileName, argv[i]); 
        p = SrcFileName + vm_string_strlen(SrcFileName) - 1; 
        if (*p != '\\' && *p != '/') { 
          vm_string_strcat(SrcFileName, VM_STRING("\\")); 
        } 
        break; 
      case 't': 
        if (2 == vm_string_strlen(argv[i])) { 
          i++; 
          if (argv[i][0]=='-') { 
            PrintHelp(argv[0]); 
            return 1; 
          } else { 
            numThreads = (int)vm_string_atol(argv[i]); 
          } 
        } else { 
          numThreads = (int)vm_string_atol(argv[i] + 2); 
        } 
        break; 
      case 'r': 
        rw_threading = 1; 
        break; 
      case 'u': 
        i++; 
        perf_file = vm_file_open(argv[i], VM_STRING("w")); 
        break; 
      case 'h': 
      case '?': 
      default: 
        PrintHelp(argv[0]); 
        return 1; 
    } 
  } 
 
  if (!ParFileName || !DstFileName || !codec_number) { 
    PrintHelp(argv[0]); 
    return 1; 
  } 
 
  switch (codec_number) { 
    case 2: 
      p_vidEncoder = createMPEG2VideoEncoder(); 
      p_vidEncoderParams = new MPEG2EncoderParams; 
      if (ReadMPEG2EncoderParams(ParFileName,(MPEG2EncoderParams*)(p_vidEncoderParams), 
        SrcFileName, MAX_FILELEN )) 
      { 
        fprintf(stderr,"Error: Can't read par file %s \n", ParFileName); 
        err_code=3; goto exit; 
      } 
      { 
        int chroma_format = ((MPEG2EncoderParams*)p_vidEncoderParams)->chroma_format; 
        if (chroma_format == CHROMA422) mColorFormat = YUV422; else 
        if (chroma_format == CHROMA444) mColorFormat = YUV444; 
      } 
      ((MPEG2EncoderParams*)p_vidEncoderParams)->numThreads = numThreads; 
      break; 
    case 4: 
      p_vidEncoder = createMPEG4VideoEncoder(); 
      p_vidEncoderParams = new MPEG4EncoderParams; 
      if (ReadMPEG4EncoderParams(ParFileName,(MPEG4EncoderParams*)(p_vidEncoderParams), 
        SrcFileName, MAX_FILELEN )) { 
          fprintf(stderr,"Error: Can't read par file %s \n", ParFileName); 
          err_code=3; goto exit; 
      } 
      break; 
    case 264: 
      p_vidEncoder = createH264VideoEncoder(); 
      p_vidEncoderParams = new H264EncoderParams; 
      if (ReadH264EncoderParams(ParFileName,(H264EncoderParams*)(p_vidEncoderParams), 
        SrcFileName, MAX_FILELEN )){ 
          fprintf(stderr,"Error: Can't par file %s \n", ParFileName); 
          err_code=3; goto exit; 
      } 
      break; 
    case 263: 
      p_vidEncoder = createH263VideoEncoder(); 
      p_vidEncoderParams = new H263EncoderParams; 
      if (ReadH263EncoderParams(ParFileName,(H263EncoderParams*)(p_vidEncoderParams), 
        SrcFileName, MAX_FILELEN )){ 
          fprintf(stderr,"Error: Can't par file %s \n", ParFileName); 
          err_code=3; goto exit; 
      } 
      break; 
    case 261: 
      p_vidEncoder = createH261VideoEncoder(); 
      p_vidEncoderParams = new H261EncoderParams; 
      if (ReadH261EncoderParams(ParFileName,(H261EncoderParams*)(p_vidEncoderParams), 
        SrcFileName, MAX_FILELEN )){ 
          fprintf(stderr,"Error: Can't par file %s \n", ParFileName); 
          err_code=3; goto exit; 
      } 
      break; 
  } 
 
  if (ippStaticInit() < ippStsNoErr) { 
    fprintf(stderr,"Error: Can't initialize ipp libs! \n"); 
    err_code=5; goto exit; 
  } 
 
  if (p_vidEncoder->Init(p_vidEncoderParams) != UMC_OK) { 
    fprintf(stderr,"Error: Video encoder initialization failed\n"); 
    err_code=6; goto exit; 
  } 
 
  mWidth = p_vidEncoderParams->src_width; 
  mHeight = p_vidEncoderParams->src_height; 
  mTotalFrames = p_vidEncoderParams->numFramesToEncode; 
 
  if (YUVReader->Init(SrcFileName, mWidth, mHeight, mColorFormat) != YUV_ERROR_NOERR){ 
    fprintf(stderr,"Error: Can't initalize yuv data reader for file %s \n",SrcFileName ); 
    err_code=8; goto exit; 
  } 
 
  printf("\n"); 
  printf("Starting encoding %s to file %s\n", SrcFileName, DstFileName); 
  printf("Source video width=%d, height=%d, frames to encode=%d\n\n", 
    mWidth, mHeight, mTotalFrames); 
 
  ts = vm_time_get_tick(); 
 
  if (!rw_threading) { 
    encode(p_vidEncoder, p_vidEncoderParams, YUVReader, DstFileName, &encoded_size, &enc_time); 
  } else { 
    printf("Enabled threading of read/encode/write!\n\n"); 
    encode_threaded(p_vidEncoder, p_vidEncoderParams, YUVReader, DstFileName, &encoded_size, &enc_time); 
  } 
 
  te = vm_time_get_tick(); 
  tf = vm_time_get_frequency(); 
  ov_time = (double)(vm_var64s)(te - ts) / (double)(vm_var64s)tf; 
 
  printf("Summary:\n" ); 
  printf("    Encoding Time = %.2f sec, %.2f fps\n", enc_time, mTotalFrames/enc_time); 
  printf("    Overall  Time = %.2f sec, %.2f fps\n", ov_time,  mTotalFrames/ov_time); 
  printf("    Encoded Size = %d bytes\n", encoded_size); 
  printf("    Compression Ratio = %.2f\n", ((double)mTotalFrames*YUVReader->mFrameSize)/encoded_size); 
 
  size_ratio = 0; 
 
  if (p_vidEncoderParams->FrameRate != 0 && p_vidEncoderParams->BitRate != 0) { 
    size_ratio = encoded_size/(((double)mTotalFrames/p_vidEncoderParams->FrameRate)*(p_vidEncoderParams->BitRate/8)); 
    printf("    EncodedSize/ExpectedSize = %.2f\n", size_ratio); 
  } 
  if (codec_number == 2) { 
    p_vidEncoder->GetInfo(p_vidEncoderParams); 
    printf("    MPEG2 internal performance = %6.2lf fps\n", ((MPEG2EncoderParams*)p_vidEncoderParams)->performance); 
  } 
  printf("\n"); 
 
  if (perf_file != NULL) { 
    vm_string_fprintf(perf_file, VM_STRING("Performance = %.2f fps"), mTotalFrames/enc_time); 
    vm_string_fprintf(perf_file, VM_STRING(", EncodedSize/ExpectedSize = %.2f"), size_ratio); 
    fclose(perf_file); 
  } 
 
exit: 
  if (p_vidEncoder) delete p_vidEncoder; 
  if (p_vidEncoderParams) delete p_vidEncoderParams; 
 
  return err_code; 
}