www.pudn.com > w_ipp-sample-media_p_5.0.017.zip > video_enc_threading.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. 
// 
// 
// 
// 
// 
 
#include "vm_thread.h" 
#include "vm_mmap.h" 
#include "vm_time.h" 
#include "umc_sys_info.h" 
#include "vm_sys_info.h" 
#include "ippcore.h" 
#include "ippcc.h" 
#include "umc_cyclic_buffer.h" 
#include "umc_video_data.h" 
 
#include "umc_mpeg2_video_encoder.h" 
#include "umc_h264_video_encoder.h" 
#include "umc_mpeg4_video_encoder.h" 
#include "umc_h263_video_encoder.h" 
#include "umc_h261_video_encoder.h" 
 
using namespace UMC; 
 
#include "utils.h" 
 
#define GET_TICKS vm_time_get_tick() 
 
typedef struct { 
  VideoEncoder *pEncoder; 
  VideoEncoderParams *Params; 
  UMCReadYUV   *YUVReader; 
  SampleBuffer YUVFrames[1]; 
  SampleBuffer CopressedFrames[1]; 
  vm_char      DstFName[256]; 
  ColorFormat  umcCFormat; 
  int    m_FrameCount; 
  long   m_EncodedSize; 
  double t_read_time; 
  double t_encode_time; 
  double t_write_time; 
} EncodeInfo; 
 
unsigned int ThreadLoadFrame(void* ptr) 
{ 
  int                   FrameCount; 
  vm_tick               t_freq, t_start, t_end; 
  double                curr_pts = 0, len_frame; 
  VideoData             data; 
  VideoEncoder          *pEncoder; 
  VideoEncoderParams    *Params; 
  Status                umcSts = UMC_OK; 
 
  assert(ptr); 
 
  EncodeInfo *Info = (EncodeInfo*)ptr; 
  pEncoder = Info->pEncoder; 
  Params = Info->Params; 
 
  data.SetVideoParameters(Params->src_width, Params->src_height, Info->umcCFormat); 
 
  len_frame = 1.0 / Info->Params->FrameRate; 
 
  t_freq = vm_time_get_frequency(); 
 
  FrameCount = 0; 
 
  while ((umcSts == UMC_OK)&&(FrameCount < (int)Info->Params->numFramesToEncode)) 
  { 
    do 
    { 
      umcSts = Info->YUVFrames->LockInputBuffer(&data); 
      if (UMC::UMC_NOT_ENOUGH_BUFFER == umcSts) 
        vm_time_sleep(5); 
    } while (UMC::UMC_NOT_ENOUGH_BUFFER == umcSts); 
    if (UMC::UMC_OK != umcSts) 
    { 
      break; 
    } 
 
    t_start = vm_time_get_tick(); 
    if (Info->YUVReader->LoadNextFrame(&data) != YUV_ERROR_NOERR) { 
      Info->YUVFrames->UnLockInputBuffer(&data); 
      break; 
    } 
    t_end = vm_time_get_tick(); 
 
    data.SetTime(curr_pts); 
    //vm_string_printf(__VM_STRING("Load: %f\n"),data.GetTime()); 
    curr_pts += len_frame; 
    Info->t_read_time   +=(double)(vm_var64s)(t_end-t_start)/(vm_var64s)t_freq; 
 
    if(UMC_OK != (umcSts = Info->YUVFrames->UnLockInputBuffer(&data))) 
    { 
      break; 
    } 
 
    FrameCount++; 
  } 
 
  // set EOS 
  do 
  { 
    umcSts = Info->YUVFrames->LockInputBuffer(&data); 
    if (UMC::UMC_NOT_ENOUGH_BUFFER == umcSts) 
      vm_time_sleep(5); 
  } while (UMC::UMC_NOT_ENOUGH_BUFFER == umcSts); 
  if (UMC::UMC_OK == umcSts) 
  { 
    data.SetDataSize(0); 
    data.SetTime(-1); 
    Info->YUVFrames->UnLockInputBuffer(&data, UMC::UMC_END_OF_STREAM); 
  } 
 
  return 0x0add; 
} 
 
unsigned int ThreadEncoding(void* ptr) 
{ 
  //int                 FrameCount; 
  vm_tick               t_freq, t_start, t_end; 
  MediaData             compressed_data; 
  VideoData             yuv_data; 
  VideoEncoderParams    *Params; 
  VideoEncoder          *pEncoder; 
  Status                umcSts = UMC_OK; 
 
  assert(ptr); 
 
  EncodeInfo *Info = (EncodeInfo*)ptr; 
  pEncoder = Info->pEncoder; 
  Params = Info->Params; 
 
  yuv_data.SetVideoParameters(Params->src_width, Params->src_height, Info->umcCFormat); 
 
  t_freq = vm_time_get_frequency(); 
 
  Info->m_FrameCount = 0; 
 
  while(umcSts == UMC_OK) 
  { 
    // get destination buffer 
    do 
    { 
      umcSts = Info->CopressedFrames->LockInputBuffer(&compressed_data); 
      if (UMC::UMC_NOT_ENOUGH_BUFFER == umcSts) 
        vm_time_sleep(5); 
 
    } while (UMC::UMC_NOT_ENOUGH_BUFFER == umcSts); 
    if(UMC_OK != umcSts) 
    { 
      break; 
    } 
 
    // get source buffer 
    do 
    { 
      umcSts = Info->YUVFrames->LockOutputBuffer(&yuv_data); 
      if (UMC::UMC_NOT_ENOUGH_DATA == umcSts) 
        vm_time_sleep(5); 
 
    } while (UMC::UMC_NOT_ENOUGH_DATA == umcSts); 
    if(UMC_OK != umcSts) 
    { 
      break; 
    } 
 
    // compress 
    vm_string_printf(VM_STRING("Encoding frame: %d ... "), Info->m_FrameCount); 
    t_start = GET_TICKS; 
    VideoData *p_yuv_data = (yuv_data.GetTime() >= 0) ? &yuv_data : NULL; 
    if(UMC_OK != (umcSts = pEncoder->GetFrame(p_yuv_data, &compressed_data))) 
    { 
      break; 
    } 
    t_end = GET_TICKS; 
    Info->t_encode_time += (double)(vm_var64s)(t_end-t_start)/(vm_var64s)t_freq; 
    vm_string_printf(VM_STRING(" done\n")); 
 
    //vm_string_printf(__VM_STRING("Enc: %f\n"),compressed_data.GetTime()); 
 
    if(UMC_OK != (umcSts = Info->CopressedFrames->UnLockInputBuffer(&compressed_data))) 
    { 
      break; 
    } 
    yuv_data.SetDataSize(0); 
    if(UMC_OK != (umcSts = Info->YUVFrames->UnLockOutputBuffer(&yuv_data))) 
    { 
      break; 
    } 
    Info->m_FrameCount++; 
  } 
 
  // epilog 
  for(;;) 
  { 
    // get destination buffer 
    do 
    { 
      umcSts = Info->CopressedFrames->LockInputBuffer(&compressed_data); 
      if (UMC::UMC_NOT_ENOUGH_BUFFER == umcSts) 
        vm_time_sleep(5); 
 
    } while (UMC::UMC_NOT_ENOUGH_BUFFER == umcSts); 
    if(UMC_OK != umcSts) 
    { 
      break; 
    } 
 
    // compress 
    t_start = GET_TICKS; 
    if(UMC_OK != (umcSts = pEncoder->GetFrame(NULL, &compressed_data))) 
    { 
      // put EOS and exit 
      compressed_data.SetDataSize(0); 
      compressed_data.SetTime(-1.0); 
      Info->CopressedFrames->UnLockInputBuffer(&compressed_data, UMC::UMC_END_OF_STREAM); 
      break; 
    } 
    t_end = GET_TICKS; 
    Info->t_encode_time += (double)(vm_var64s)(t_end-t_start)/(vm_var64s)t_freq; 
 
    if(UMC_OK != (umcSts = Info->CopressedFrames->UnLockInputBuffer(&compressed_data))) 
    { 
      break; 
    } 
    Info->m_FrameCount++; 
  } 
 
  //vm_string_printf("Encoded %d frames\n", Info->m_FrameCount); 
 
  return 0x0ecc; 
} 
 
unsigned int ThreadSaveFrame(void* ptr) 
{ 
  int                   FrameCount, size; 
  vm_tick               t_freq, t_start, t_end; 
  double                st,en; 
  VideoData             data; 
  VideoEncoder          *pEncoder; 
  VideoEncoderParams    *Params; 
  FILE                  *out_file; 
  Status                umcSts = UMC_OK; 
 
  assert(ptr); 
 
  EncodeInfo *Info = (EncodeInfo*)ptr; 
  pEncoder = Info->pEncoder; 
  Params = Info->Params; 
 
  out_file = vm_file_open(Info->DstFName, VM_STRING("wb")); 
  if(!out_file) 
  { 
    vm_string_printf( __VM_STRING("Cann't open out file\n")); 
    return 0; 
  } 
 
  t_freq = vm_time_get_frequency(); 
 
  FrameCount = 0; 
 
  while(umcSts == UMC_OK) 
  { 
    do 
    { 
      umcSts = Info->CopressedFrames->LockOutputBuffer(&data); 
      if (UMC::UMC_NOT_ENOUGH_DATA == umcSts) 
        vm_time_sleep(5); 
 
    } while (UMC::UMC_NOT_ENOUGH_DATA == umcSts); 
    if(UMC_OK != umcSts) 
    { 
      break; 
    } 
    //vm_string_printf(__VM_STRING("Sav: %f\n"),data.GetTime()); 
 
    data.GetTime(st,en); 
    size = (int)data.GetDataSize(); 
    t_start = vm_time_get_tick(); 
    if (1 != fwrite(data.GetDataPointer(), size, 1, out_file)) 
    { 
      break; 
    } 
 
    Info->m_EncodedSize += size; 
    assert(size == (int)data.GetDataSize()); 
    t_end = vm_time_get_tick(); 
    Info->t_write_time += (double)(vm_var64s)(t_end-t_start)/(vm_var64s)t_freq; 
    data.SetDataSize(0); 
    if(UMC_OK != (umcSts = Info->CopressedFrames->UnLockOutputBuffer(&data))) 
    { 
      break; 
    } 
    FrameCount++; 
  } 
 
  fclose(out_file); 
 
  return 0x0123; 
} 
 
int encode_threaded(VideoEncoder       *Encoder, 
                    VideoEncoderParams *Params, 
                    UMCReadYUV         *YUVReader, 
                    vm_char            *DstFileName, 
                    int                *encoded_size, 
                    double             *enc_time) 
{ 
  EncodeInfo Info[1]; 
  VideoBufferParams bufferPar; 
  int i = 1; 
  vm_thread m_hThreadLoad[1]; 
  vm_thread m_hThreadEnc[1]; 
  vm_thread m_hThreadSave[1]; 
 
  Info->pEncoder = Encoder; 
  Info->Params = Params; 
  Info->YUVReader = YUVReader; 
  Info->umcCFormat = YUVReader->mColorFormat; 
  vm_string_strcpy(Info->DstFName, DstFileName); 
  Info->m_FrameCount = 0; 
  Info->m_EncodedSize = 0; 
  Info->t_read_time = 0; 
  Info->t_encode_time = 0; 
  Info->t_write_time = 0; 
 
  // Init YUVFrames 
  bufferPar.m_numberOfFrames = 16; 
  bufferPar.m_prefInputBufferSize = 
  bufferPar.m_prefOutputBufferSize = 2*YUVReader->mFrameSize; 
  if(UMC_OK != (Info->YUVFrames->Init(&bufferPar))) 
  { 
    vm_string_printf( __VM_STRING("Video Buffer for YUV creation failed\n")); 
    goto __exit_out; 
  } 
 
  // Init CopressedFrames 
  bufferPar.m_numberOfFrames = 4; 
  if(UMC_OK != (Info->CopressedFrames->Init(&bufferPar))) 
  { 
    vm_string_printf( __VM_STRING("Video Buffer for MPEG2 stream creation failed\n")); 
    goto __exit_out; 
  } 
 
  vm_thread_set_invalid(m_hThreadLoad); 
  if(!vm_thread_create(m_hThreadLoad, ThreadLoadFrame, Info)) 
  { 
    vm_string_printf(__VM_STRING("ThreadLoadFrame creation failed\n")); 
    goto __exit_out; 
  } 
  vm_thread_set_priority(m_hThreadLoad, VM_THREAD_PRIORITY_HIGHEST); 
 
  vm_thread_set_invalid(m_hThreadEnc); 
  if(!vm_thread_create(m_hThreadEnc, ThreadEncoding, Info)) 
  { 
    vm_string_printf(__VM_STRING("ThreadEncoding creation failed\n")); 
    goto __exit_out; 
  } 
  vm_thread_set_priority(m_hThreadEnc, VM_THREAD_PRIORITY_HIGH); 
 
  vm_thread_set_invalid(m_hThreadSave); 
  if(!vm_thread_create(m_hThreadSave, ThreadSaveFrame, Info)) 
  { 
    vm_string_printf(__VM_STRING("ThreadSaveFrame creation failed\n")); 
    goto __exit_out; 
  } 
  vm_thread_set_priority(m_hThreadSave, VM_THREAD_PRIORITY_LOWEST); 
 
  vm_thread_wait(m_hThreadLoad); 
  vm_thread_wait(m_hThreadEnc); 
  vm_thread_wait(m_hThreadSave); 
 
  vm_thread_close(m_hThreadLoad); 
  vm_thread_close(m_hThreadEnc); 
  vm_thread_close(m_hThreadSave); 
 
__exit_out: 
  Info->CopressedFrames->Close(); 
  Info->YUVFrames->Close(); 
 
  *encoded_size = Info->m_EncodedSize; 
  *enc_time = Info->t_encode_time; 
  return 0; 
}