Simple mpg encoder...

Simple mpg encoder...

In our (CAD) application we have a simple video export option based on a stadard Microsoft codec package. The problems started with Vista, as this codec package refused to install. Therefore we're looking for another solution...

To put it simple, we have a set of frames/images that we'd like to encode to some kind of video that can be read by pure Windows intallations (Me/2000 and up). I guess plain old mpg1 would do the trick, but it isn't supported by IPP? Well, maybe some of the other supported formats would fit the bill...

I know next to nothing about video codecs, so I was hoping that there were some extremely simple (IPP based) examples out there, like:

encoder = InitEncoder(outFile, width, height, fps, quality [, numberOfFrames]);
encoder->AddFrame(image1);

encoder->AddFrame(image2);

encoder->AddFrame(image3);

...
encoder->Close();

I'm sure this is TOO simple, and that I'm hoping for too much (and that I'm over my head), but if there was an example that was somewhere in the neighborhood, I'd be very happy if anybody pointed to it for me :-)

33 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hello,

I would recommend you to take a look on IPP media sample, which contains big bunch of codecs and test applications:

simple_player for playback and

video_encoder_con to encode frames.

Moreover, IPP encoders and decoders are threaded and you will automatically get benefit in performance from modern Core 2 Duo (or old SMP) systems.

Regards,
Vladimir

vdudnik:

Hello,

I would recommend you to take a look on IPP media sample, which contains big bunch of codecs and test applications:

simple_player for playback and

video_encoder_con to encode frames.

Moreover, IPP encoders and decoders are threaded and you will automatically get benefit in performance from modern Core 2 Duo (or old SMP) systems.

Regards,
Vladimir

Sorry, but I cannot find any mention of video_encoder_con anywhere in the IPP media sample package... :-(

Well, the correct name for IPP 5.2 beta is umc_video_enc_con, it is located in media_sampleapplications folder

Vladimir

Found it. Thank you so much

I've tried the encoder, but it only outputs garbage. I suspect that this is because it requires YUV encoded files, and we export RGB encoded frames.

I'm trying to skip the entire usage of "YUVReader" and read single (RGB encoded) .jpg files instead. I sure hope this is possible...

Right now I'm messing about in VideoData trying to figure out what needs to be set for p_vidEncoder->GetFrame to work...

I think you need to add ippiRGBToYUV420_8u_C3P3R function to convert your RGB data to format which is required by YUV reader. The reason is that UMC encoders take YUV420 format as an input (otherwise conversion is required)

Vladimir

Thank you Vladimir, for your patience...

Oh my God, this whole IPP thing sure is low level... I'm starting to wonder if this is really something to bother getting into after all...

I've noticed that several on this forum have asked for help reading jpg files, but as far as I've seen none has gotten any tangible answers... I've scoured through the image and media examples, but haven't found anything that helps me.

---

Too ba, as I'm so close to getting something useful!

All I want to do is to read a jpg file and use this data to fill in what's needed into the p_dataIn structure to be used in the followin call umc_video_enc_con example:

"mRetval = p_vidEncoder->GetFrame(p_dataIn, p_dataOut);"

In the example p_dataIn is provided by the YUVReader, which I was hoping to leave out alltogether by reading single jpg files.

Ah, well...

Well, IPP is Software Development Kit, which provides you optimized algorithms implementation and set of samples how to use that functionality. You need to spent some effort to integrate it into your application.

You can read JPEG files with CJPEGDecoder class from JPEGView sample.Then, you may convertdecoded image into VideoData representation with using ippiRGBToYUV420 function. UMC video encoder taakes VideoData as an input. Please read more details inUMC manual.

Let us know if youstill have any throubles with that, we will beglad to help you

Regards,
Vladimir

I'm so sorry, I hadn't downloaded the JPG samples as I though the JPG stuff was in the image samples... Talk about not using your eyes... :-(

I'll have a go at the JPG examples right now.

I've scrapped the whole jpg thing, as the ultimate goal is to eventually get uncompressed image data from our host application. Right now I'm trying to read a sequence of .bmp files instead. All seems to go fine, but the result video file is all purple... Obviously I've done something wrong. I'm unsure about this whole ippiRGBToYUV420_8u_C3P3Rthing...I'm probably not populating the right buffers, but I'm unsure how to proceed. Here's the code snippet that is supposed to encode the video from sinle .bmp images:

---

// Encode video frame by frame

char frameName[512];

BYTE inBuf[1000000];

for (mFrameCount = 0; mFrameCount < maxNumFrames; mFrameCount++)

{

m_csysinfo.GetCpuUsage();

vm_string_printf(VM_STRING("Encoding frame: %d ... "), mFrameCount);

// Load bmp file into 'inBuf'

sprintf(frameName, "v%05d.bmp", mFrameCount);

vm_string_fprintf(stderr, VM_STRING("Reading input file '%s'
"), frameName);

FILE *inFile = vm_file_open(frameName, VM_STRING("rb"));

if (!inFile)

{

vm_string_fprintf(stderr, VM_STRING("Error: Can't open input file '%s'
"), frameName);

err_code=9; goto free_memories;

}

len = fread(inBuf, 1, 1000000, inFile);

if (inFile)

fclose(inFile);

// Get to the meat of the BMP file

unsigned int offset = (unsigned int)inBuf[10];

IppiSize roi = {mWidth, mHeight};

int dstStep[3];

dstStep[0] = dstStep[1] = dstStep[2] = 0;

Ipp8u* pDst[3];

pDst[0] = pY;

pDst[1] = pU;

pDst[2] = pV;

// Vladimir:

// I think you need to add ippiRGBToYUV420_8u_C3P3R function to convert your RGB data

// to format which is required by YUV reader. The reason is that UMC encoders take YUV420

// format as an input (otherwise conversion is required)

IppStatus ippStatus = ippiRGBToYUV420_8u_C3P3R(inBuf + (BYTE)offset, 0, pDst, dstStep, roi);

if (ippStatus != ippStsNoErr)

vm_string_fprintf(stderr, VM_STRING("ippiRGBToYUV420_8u_C3P3R failed with status: %d
"
), ippStatus);

// Encode video frame

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)

{

vm_string_fprintf(stderr, VM_STRING("Error: encoding failed at %d source frame (exit with %d)!
"), mFrameCount, mRetval);

err_code = 13;

break;

}

len = fwrite(p_dataOut->GetDataPointer(), 1, p_dataOut->GetDataSize(), outFile);

mCompSize += (int)len;

if (len != p_dataOut->GetDataSize())

{

vm_string_fprintf(stderr, VM_STRING("Error: Couldn't write to output file '%s'
"), DstFileName);

err_code=11; goto free_memories;

}

// extend p_dataOut data size to buffer size

// assume data pointer isn't moved

p_dataOut->SetDataSize(p_dataOut->GetBufferSize());

vm_string_printf(VM_STRING(" done
"));

}

BMP uses BGR channel order, so you need to call ippiBGRToYCbCr420_8u_C3P3R

Vladimir

Thank you again, Vladimir!

Although it din't help. This wasn't entirely surpricing, since the (dis)order of the RGB channels shouldn't cause the constant green or purple screen that I get in the final video.

I've done some more testing and found out the following:

If I run my modified umc_video_enc_con with different codecs:

codec
File size
Playability
GSpot reports

m2
246 kB
Yes (green screen)
Codec Not Installed

m4
27 kB
no

Direct show: 0x80040265: Cannot playback file. Format no suppoerted

h264
7 kB
no

Direct show: 0x80040265: Cannot playback file. Format no suppoerted

h263
failed
-
-

h261
failed
-
-

For h263 and h261 I got "Video encode initialization failed"

I've ran the build file at ipp_samplemedia, and some sub builds failed:

video_renders
audio_renders
umc_pipeline
audio_codecs
virtual_ac_5p1
umc_reverb_demo
simple_player
audio_codec_com_so

All others passed. I don't know if this has anything to do with my problems, but thought that I should mention it.

-Rune

but all video encoders passed.

Hi Rune,

IPP media sample should build without any problems. Did you read readme.htm first to see what might be needed for compilation of that sample? Can you attach log files for us to see what was the problem with build?

If you try to play mpeg2 encoded stream on windows system, you should know that Windows do not have mpeg2 decoder installed by default.

To see encoded video you can try simple_player application from IPP media sample, it supports all codecs provided in that sample (H.261, H.263, H.264, MPEG2, MPEG4, VC1)

Regards,
Vladimir

Hmmm.... the latest DirectX SDK I was able to install on my Win2000Pro computer, was "Microsoft DirectX 9.0 SDK (Summer 2004)"

I notice that this particular version is not listed in directx_sdk.bat.

I guess this is not good at all... Do you have a link to a DX DSK that is "accepted by" ipp5.1 and still installable under W2kPro?

I've now tried installing the oldest DX SDK that is mentioned indirectx_sdk.bat, andcan confrim that is is not installable under W2kPro...

I have no idea how to proceed from here...

Hi,

actually, I think you can use your old version of DX SDK (just need to tune path to headers and libraries in directx_sdk.bat). DX functionality is mainly used in renders.

Vladimir

I finally just copied the two missing lib files from the DX SDK to the lib directory in the media tree. Now a build32 passes all sub builds without problems.

BUT

My encodings still works as before m2, m4 & h264creates very small (and unreadable) video files and h261 & h263 results in the following message:

"Error: Video encoder initialization failed"

I've included the complete modified video_enc_con.cpp file. Hope you can see where I've made a fool of myself:

//

// 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-2006 Intel Corporation. All Rights Reserved.

//

#define SINGLE_FRAME_ENCODING 1

#include "..includeutils.h"

#include "vm_time.h"

#include "umc_sys_info.h"

#include "vm_sys_info.h"

#define MAX_FILELEN 1024

UMC :: SysInfo m_csysinfo;

int encode(VideoEncoder *p_vidEncoder,

VideoEncoderParams *p_vidEncoderParams,

UMCReadYUV *YUVReader,

vm_char *DstFileName,

int *framesEncoded,

int *encoded_size,

double *enc_time)

{

VideoData *p_dataIn = NULL;

MediaData *p_dataOut = NULL;

int mFrameCount = 0, err_code = 0;

int mWidth, mHeight, mSize, maxNumFrames;

int mCompSize = 0;

Status mRetval = UMC_OK;

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;

maxNumFrames = p_vidEncoderParams->numFramesToEncode;

mSize = mWidth * mHeight;

p_dataIn = new VideoData;

p_dataOut = new MediaData;

if ((!p_dataIn) || (!p_dataOut))

{

vm_string_fprintf(stderr, VM_STRING("Error: Can't allocate Media Data objects "));

err_code=7; goto free_memories;

}

// Open output video file

outFile = vm_file_open(DstFileName, VM_STRING( "wb"));

if (!outFile)

{

vm_string_fprintf(stderr, VM_STRING("Error: Can't open output file '%s' "), 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))

{

vm_string_fprintf(stderr, VM_STRING("Error: Can't allocate data buffers! "));

err_code=10; goto free_memories;

}

p_dataIn->InitAlloc(mWidth, mHeight, YUV420);

p_dataIn->SetDest(pY, pU, pV);

#ifndef SINGLE_FRAME_ENCODING

p_dataIn->SetPitch(YUVReader->mWidth, YUVReader->mWidthChroma, YUVReader->mWidthChroma);

#endif

// p_dataIn->SetColorFormat(YUV420);

p_dataOut->SetBufferPointer(pBS, 2*mSize);

tf = vm_time_get_frequency();

time = 0;

mCompSize = 0;

// Encode video frame by frame

char frameName[512];

BYTE inBuf[1000000];

for (mFrameCount = 0; mFrameCount < maxNumFrames; mFrameCount++)

{

m_csysinfo.GetCpuUsage();

vm_string_printf(VM_STRING("Encoding frame: %d ... "), mFrameCount);

// HER KAN VI KANSKJE GJRRA NO?

#ifndef SINGLE_FRAME_ENCODING

if (YUVReader->LoadNextFrame(p_dataIn) != YUV_ERROR_NOERR)

{

vm_string_fprintf(stderr, VM_STRING("Error: Can't read next %d source frame! "), mFrameCount);

break;

}

#else

// Load bmp file into 'inBuf'

sprintf(frameName, "v%05d.bmp", mFrameCount);

vm_string_fprintf(stderr, VM_STRING("Reading input file '%s' "), frameName);

FILE *inFile = vm_file_open(frameName, VM_STRING("rb"));

if (!inFile)

{

vm_string_fprintf(stderr, VM_STRING("Error: Can't open input file '%s' "), frameName);

err_code=9; goto free_memories;

}

len = fread(inBuf, 1, 1000000, inFile);

if (inFile)

fclose(inFile);

// Get to the meat of the BMP file

unsigned int offset = (unsigned int)inBuf[10];

// vm_string_fprintf(stderr, VM_STRING("Offset to image data '%d' "), offset);

IppiSize roi = {mWidth, mHeight};

int dstStep[3];

dstStep[0] = dstStep[1] = dstStep[2] = 0;

Ipp8u* pDst[3];

pDst[0] = pY;

pDst[1] = pU;

pDst[2] = pV;

// Vladimir:

// I think you need to add ippiRGBToYUV420_8u_C3P3R function to convert your RGB data

// to format which is required by YUV reader. The reason is that UMC encoders take YUV420

// format as an input (otherwise conversion is required)

// IppStatus ippStatus = ippiRGBToYUV420_8u_C3P3R(inBuf + (BYTE)offset, 0, pDst, dstStep, roi);

IppStatus ippStatus = ippiBGRToYCbCr420_8u_C3P3R(inBuf + (BYTE)offset, 0, pDst, dstStep, roi);

if (ippStatus != ippStsNoErr)

vm_string_fprintf(stderr, VM_STRING("ippiRGBToYUV420_8u_C3P3R failed with status: %d "), ippStatus);

#endif

// Encode video frame

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)

{

vm_string_fprintf(stderr, VM_STRING("Error: encoding failed at %d source frame (exit with %d)! "), mFrameCount, mRetval);

err_code = 13;

break;

}

len = fwrite(p_dataOut->GetDataPointer(), 1, p_dataOut->GetDataSize(), outFile);

mCompSize += (int)len;

if (len != p_dataOut->GetDataSize())

{

vm_string_fprintf(stderr, VM_STRING("Error: Couldn't write to output file '%s' "), DstFileName);

err_code=11; goto free_memories;

}

// extend p_dataOut data size to buffer size

// assume data pointer isn't moved

p_dataOut ->SetDataSize(p_dataOut->GetBufferSize());

vm_string_printf(VM_STRING(" done "));

}

if (mRetval == UMC_OK && mFrameCount > 0)

{

do

{

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)

{

vm_string_fprintf(stderr, VM_STRING("Error: encoding failed at outputing buffered frames (exit with %d)! "), 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())

{

vm_string_fprintf(stderr, VM_STRING("Error: Couldn't write to output file '%s' "), DstFileName);

err_code=12; goto free_memories;

}

// mFrameCount++;

} while ((mRetval == UMC_OK )&&(p_dataOut->GetDataSize()>0));

}

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);

*framesEncoded = mFrameCount;

*encoded_size = mCompSize;

*enc_time = time;

return err_code;

}

void PrintHelp(vm_char *prog_name, vm_char *err_message)

{

vm_string_printf(VM_STRING("Error: %s "), err_message);

vm_string_printf(VM_STRING("Usage1: %s [m2|m4|h264|h263|h261] [Options] InputParFile OutputEncodedFile "), pro g_name);

vm_string_printf(VM_STRING("Usage2: %s [m2|m4|h264|h263|h261] [Options] -i InputYUVFile -o OutputEncodedFile "), prog_name);

vm_string_printf(VM_STRING("Options: "));

vm_string_printf(VM_STRING(" [-i inputFile] - input YUV video file "));

vm_string_printf(VM_STRING(" [-w width] - video width "));

vm_string_printf(VM_STRING(" [-h height] - video height "));

vm_string_printf(VM_STRING(" [-f frameRate] - video frame rate (frames per second) "));

vm_string_printf(VM_STRING(" [-b bitRate] - encoded bit rate (bits per second) "));

vm_string_printf(VM_STRING(" [-n numFrames] - max frames to encode "));

vm_string_printf(VM_STRING(" [-t num] - number of threads for encoding "));

vm_string_printf(VM_STRING(" [-r] - enables threading of read/encode/write "));

vm_string_printf(VM_STRING(" [-y dir] - directory of YUV files "));

vm_string_printf(VM_STRING(" [-u file] - file for dumping perfomance info "));

vm_string_printf(VM_STRING(" [-p file.csv] - file for dumping perfomance info into scv format "));

vm_string_printf(VM_STRING("Note: Options -i,-w,-h,-f,-b,-n override corresponding values inside InputParFile. "));

vm_string_printf(VM_STRING(" If InputParFile not specified, at least options -w,-h should be specified and -o should be added before OutputEncodedFile. "));

vm_string_printf(VM_STRING(" "));

}

#define GET_OPTION_POINTER(PTR)

if (2 == vm_string_strlen(argv[i])) {

i++;

if (argv[i][0]=='-') {

PrintHelp(argv[0], VM_STRING("in options"));

return 1;

} else {

PTR = argv[i];

}

} else {

PTR = argv[i] + 2;

}

#define CREATE_ENCODER(CODEC)

p_vidEncoder = create##CODEC##VideoEncoder();

if (ParFileName) {

p_vidEncoderParams = new CODEC ##EncoderParams;

if (Read##CODEC##EncoderParams(ParFileName,

(CODEC##EncoderParams*)(p_vidEncoderParams),

SrcFileName,

MAX_FILELEN))

{

vm_string_fprintf(stderr, VM_STRING("Error: Can't read par file %s "), ParFileName);

err_code=3; goto exit;

}

}

int main(int argc, vm_char *argv[])

{

vm_char SrcFileName[MAX_FILELEN];

vm_char *pSrcFileName = NULL;

vm_char *ParFileName = NULL;

vm_char *DstFileName = NULL;

vm_char PerfFileName[MAX_FILELEN];

vm_char *pVal;

UMCReadYUV YUVReader[1];

VideoEncoder *p_vidEncoder = NULL;

VideoEncoderParams *p_vidEncoderParams = NULL;

ColorFormat mColorFormat = YV12;

FILE *perf_file = NULL;

FILE *perf_file_csv = 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;

double size_ratio = 0;

int mWidth = 0, mHeight = 0, maxNumFrames = 0, mFramesEncoded = 0;

int BitRate = -1; // if (BitRate < 0) used below !!

double FrameRate = 0;

UMC :: sSystemInfo* m_ssysteminfo;

vm_char tmpbuf[128]={0,};

vm_char vid_type[15]={0,};

vm_char* stream_name = NULL;

*SrcFileName = 0;

*PerfFileName=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 'p':

case 'P':

i++;

vm_string_strcpy(PerfFileName, argv[i]);

break;

case 'w':

GET_OPTION_POINTER(pVal);

mWidth = (int)vm_string_atol(pVal);

break;

case 'h':

GET_OPTION_POINTER(pVal);

mHeight = (int)vm_string_atol(pVal);

break;

case 'f':

GET_OPTION_POINTER(pVal);

vm_string_sscanf(pVal, VM_STRING("%lf"), &FrameRate);

break;

case 'b':

GET_OPTION_POINTER(pVal);

BitRate = (int)vm_string_atol(pVal);

break;

case 'n':

GET_OPTION_POINTER(pVal);

maxNumFrames = (int)vm_string_atol(pVal);

break;

case 'i':

GET_OPTION_POINTER(pSrcFileName);

break;

case 'o':

GET_OPTION_POINTER(pVal);

DstFileName = pVal;

break;

case 't':

GET_OPTION_POINTER(pVal);

numThreads = (int)vm_string_atol(pVal);

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], VM_STRING("Unknown options"));

return 1;

}

}

if (!ParFileName && !codec_number) {

codec_number = 2;

}

if (!DstFileName) {

PrintHelp(argv[0], VM_STRING("Destination file name not found"));

return 1;

}

if (!codec_number) {

PrintHelp(argv[0], VM_STRING("Unknown codec"));

return 1;

}

if (!ParFileName && (!mWidth || !mHeight)) {

PrintHelp(argv[0], VM_STRING("at least ParFile or options -w,-h should be specified"));

return 1;

}

switch (codec_number) {

#ifdef UMC_ENABLE_MPEG2_VIDEO_ENCODER

case 2:

vm_string_strcpy(vid_type,VM_STRING("MPEG2"));

CREATE_ENCODER(MPEG2)

if (ParFileName) {

int chroma_format = ((MPEG2EncoderParams*)p_vidEncoderParams)->m_Params.chroma_format;

if (chroma_format == CHROMA422) mColorFormat = YUV422; else

if (chroma_format == CHROMA444) mColorFormat = YUV444;

}

break;

#endif /* UMC_ENABLE_MPEG2_VIDEO_ENCODER */

#ifdef UMC_ENABLE_MPEG4_VIDEO_ENCODER

case 4:

vm_string_strcpy(vid_type,VM_STRING("MPEG4"));

CREATE_ENCODER(MPEG4)

break;

#endif /* UMC_ENABLE_MPEG4_VIDEO_ENCODER */

#ifdef UMC_ENABLE_H261_VIDEO_ENCODER

case 261:

vm_string_strcpy(vid_type,VM_STRING("H261"));

CREATE_ENCODER(H261)

break;

#endif /* UMC_ENABLE_H261_VIDEO_ENCODER */

#ifdef UMC_ENABLE_H263_VIDEO_ENCODER

case 263:

vm_string_strcpy(vid_type,VM_STRING("H263"));

CREATE_ENCODER(H263)

break;

#endif /* UMC_ENABLE_H263_VIDEO_ENCODER */

#ifdef UMC_ENABLE_H264_VIDEO_ENCODER

case 264:

vm_string_strcpy(vid_type,VM_STRING("H264"));

CREATE_ENCODER(H264)

break;

#endif /* UMC_ENABLE_H264_VIDEO_ENCODER */

default:

vm_string_fprintf(stderr, VM_STRING("Codec (%d) not supported "), codec_number);

PrintHelp(argv[0], VM_STRING("Codec not supported"));

return 1;

}

if (!ParFileName) {

p_vidEncoderParams = new VideoEncoderParams;

if (!maxNumFrames) {

maxNumFrames = 0x7fffffff;

}

if (!FrameRate) {

FrameRate = 30;

}

if (BitRate < 0) {

BitRate = 5000000;

}

}

// override param's if non-zero

if (mWidth && mHeight) {

p_vidEncoderParams->src_width = mWidth;

p_vidEncoderParams->src_height = mHeight;

} else {

mWidth = p_vidEncoderParams->src_width;

mHeight = p_vidEncoderParams->src_height;

}

if (maxNumFrames) {

p_vidEncoderParams->numFramesToEncode = maxNumFrames;

} else {

maxNumFrames = p_vidEncoderParams->numFramesToEncode;

}

if (FrameRate) {

p_vidEncoderParams->FrameRate = FrameRate;

} else {

FrameRate = p_vidEncoderParams->FrameRate;

}

if (BitRate >= 0) {

p_vidEncoderParams->BitRate = BitRate;

} else {

BitRate = p_vidEncoderParams->BitRate;

}

p_vidEncoderParams->numThreads = numThreads;

if (NULL != pSrcFileName) {

vm_string_strcpy(SrcFileName, pSrcFileName);

}

//////////////////////////////////////////////////////////////////////////////////////////////////////

m_csysinfo.GetCpuUsage();

m_ssysteminfo = (UMC::sSystemInfo *)m_csysinfo.GetSysInfo();

if(PerfFileName[0])

perf_file_csv = vm_file_open(PerfFileName, VM_STRING("a"));

if(perf_file_csv){

stream_name = vm_string_strrchr(SrcFileName, (int)(''));

if(!stream_name)stream_name = SrcFileName;

else stream_name++;

fseek( perf_file_csv, 0, SEEK_END);

if(!ftell( perf_file_csv))

vm_string_fprintf(perf_file_csv, VM_STRING("Date,Time,Comp.name,OS,CPU,Num.CPU,CPU freq.,MEM,VGA,App,App description,Ver.,Streams(S) name,Status,S.Type,S.Res.,S.FR,S.BR,Video(V)Type,V.Format,V.Num,V.D/E(FpS),V.D/E(MHz),Compr.(%%),CPU Usage (%%),Max Cpu Usage (%%),Work.Time "));

vm_sys_info_get_date(tmpbuf,MMDDYY);

vm_string_fprintf(perf_file_csv,VM_STRING("%s,"), tmpbuf);

vm_sys_info_get_time(tmpbuf,HHMMSS);

vm_string_fprintf(perf_file_csv,VM_STRING("%s,"), tmpbuf);

vm_string_fprintf(perf_file_csv,VM_STRING("%s,"), m_ssysteminfo->computer_name);

vm_string_fprintf(perf_file_csv,VM_STRING("%s,"), m_ssysteminfo->os_name);

vm_string_fprintf(perf_file_csv,VM_STRING("%s,"), m_ssysteminfo->proc_name);

vm_string_fprintf(perf_file_csv,VM_STRING("%d,"), m_ssysteminfo->num_proc);

vm_string_fprintf(perf_file_csv,VM_STRING("%.2f,"), (double)m_ssysteminfo->cpu_freq);

vm_string_fprintf(perf_file_csv,VM_STRING("%d,"), m_ssysteminfo->phys_mem);

vm_string_fprintf(perf_file_csv,VM_STRING("%s,"), m_ssysteminfo->video_card);

vm_string_fprintf(perf_file_csv,VM_STRING("%s,"),m_ssysteminfo->program_name);

vm_string_fprintf(perf_file_csv,VM_STRING("UMC Video Encoder Con.,"));//,m_ssysteminfo->description);

vm_string_fprintf(perf_file_csv,VM_STRING(",")); // ver. of aplications

vm_string_fprintf(perf_file_csv,VM_STRING("%s,"), stream_name);

vm_string_fprintf(perf_file_csv,VM_STRING("FAIL "));

fclose(perf_file_csv);

}

///////////////////////////////////////////////////////////////////////////////////////////////////////

if (ippStaticInit() < ippStsNoErr) {

vm_string_fprintf(stderr, VM_STRING("Error: Can't initialize ipp libs! "));

err_code=5; goto exit;

}

if (p_vidEncoder->Init(p_vidEncoderParams) != UMC_OK) {

vm_string_fprintf(stderr, VM_STRING("Error: Video encoder initialization failed "));

err_code=6; goto exit;

}

if (p_vidEncoder->GetInfo(p_vidEncoderParams) != UMC_OK) {

vm_string_fprintf(stderr, VM_STRING("Error: Video encoder GetInfo failed "));

err_code=7; goto exit;

}

// if (YUVReader->Init(SrcFileName, mWidth, mHeight, mColorFormat) != YUV_ERROR_NOERR){

// vm_string_fprintf(stderr, VM_STRING("Error: Can't initialize yuv data reader for file %s "), SrcFileName);

// err_code=8; goto exit;

// }

vm_string_printf(VM_STRING(" "));

vm_string_printf(VM_STRING("Starting encoding %s to file %s "), SrcFileName, DstFileName);

vm_string_printf(VM_STRING("Source video width = %d, height = %d, frameRate = %.2lf "),

mWidth, mHeight, FrameRate);

vm_string_printf(VM_STRING("Ma x frames to encode = %d "), maxNumFrames);

if (p_vidEncoderParams->BitRate > 0)

vm_string_printf(VM_STRING("Encoding bit rate = %d bits per second "), p_vidEncoderParams->BitRate);

else

vm_string_printf(VM_STRING("Encoding without rate control "));

ts = vm_time_get_tick();

if (!rw_threading) {

encode(p_vidEncoder, p_vidEncoderParams, YUVReader,

DstFileName, &mFramesEncoded, &encoded_size, &enc_time);

} else {

vm_string_printf(VM_STRING("Enabled threading of read/encode/write! "));

encode_threaded(p_vidEncoder, p_vidEncoderParams, YUVReader, DstFileName, &mFramesEncoded, &encoded_size, &enc_time);

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////

m_csysinfo.GetCpuUsage();

te = vm_time_get_tick();

tf = vm_time_get_frequency();

ov_time = (double)(vm_var64s)(te - ts) / (double)(vm_var64s)tf;

if(PerfFileName[0])

perf_file_csv = vm_file_open(PerfFileName, VM_STRING("r+"));

if(perf_file_csv) {

fseek( perf_file_csv, -6, SEEK_END);

vm_string_fprintf(perf_file_csv,VM_STRING("PASSED,"));

vm_string_fprintf(perf_file_csv,VM_STRING("PV,"));

vm_string_fprintf(perf_file_csv,VM_STRING("%dx%d,"),p_vidEncoderParams->dst_width,p_vidEncoderParams->dst_height);

vm_string_fprintf(perf_file_csv,VM_STRING("%.2lf,"),p_vidEncoderParams->FrameRate);

vm_string_fprintf(perf_file_csv,VM_STRING("%d,"),p_vidEncoderParams->BitRate/1000);

vm_string_fprintf(perf_file_csv,VM_STRING("%s,"), vid_type);

vm_string_fprintf(perf_file_csv,VM_STRING(","));

vm_string_fprintf(perf_file_csv,VM_STRING("%d,"), mFramesEncoded);

vm_string_fprintf(perf_file_csv,VM_STRING("%.2lf,"), mFramesEncoded/enc_time);

vm_string_fprintf(perf_file_csv,VM_STRING("%.2lf,"), (double)(p_vidEncoderParams->FrameRate/(mFramesEncoded/enc_time)*(m_ssysteminfo->cpu_freq)));

vm_string_fprintf(perf_file_csv,VM_STRING("%.2lf,"), ((double)encoded_size*100.0/(mFramesEncoded*YUVReader->mFrameSize)));

vm_string_fprintf(perf_file_csv,VM_STRING("%.2lf,"), m_csysinfo.GetAvgCpuUsage());

vm_string_fprintf(perf_file_csv,VM_STRING("%.2lf,"), m_csysinfo.GetMaxCpuUsage());

vm_string_fprintf(perf_file_csv,VM_STRING("%02d:%02d:%02d.%02d,"),(int)ov_time/3600,(int)(ov_time)%3600/60,(int)ov_time%3600%60,(int)((ov_time-(int)ov_time)*100));

vm_string_fprintf(perf_file_csv,VM_STRING(" " ));

fclose(perf_file_csv);

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

vm_string_printf(VM_STRING("Summary: "));

vm_string_printf(VM_STRING(" Num frames encoded = %d "), mFramesEncoded);

vm_string_printf(VM_STRING(" Encoding Time = %.2f sec, %.2f fps "), enc_time, mFramesEncoded/enc_time);

vm_string_printf(VM_STRING(" Overall Time = %.2f sec, %.2f fps "), ov_time, mFramesEncoded/ov_time);

vm_string_printf(VM_STRING(" Encoded Size = %d bytes "), encoded_size);

vm_string_printf(VM_STRING(" Compression Ratio = %.2f "), ((double)mFramesEncoded*YUVReader->mFrameSize)/encoded_size);

if (p_vidEncoderParams->FrameRate > 0 && p_vidEncoderParams->BitRate > 0) {

size_ratio = encoded_size/(((double)mFramesEncoded/p_vidEncoderParams->FrameRate)*(p_vidEncoderParams->BitRate/8));

vm_string_printf(VM_STRING(" EncodedSize/ExpectedSize = %.2f "), size_ratio);

}

#ifdef UMC_ENABLE_MPEG2_VIDEO_ENCODER

if (codec_number == 2) {

p_vidEncoder->GetInfo(p_vidEncoderParams);

vm_string_printf(VM_STRING(" MPEG2 internal performance = %6.2lf fps "), ((MPEG2EncoderParams*)p_vidEncoderParams)->m_Params.performance);

}

vm_string_printf(VM_STRING(" "));

#endif

if (perf_file != NULL) {

vm_string_fprintf(perf_file, VM_STRING("Performance = %.2f fps"), mFramesEncoded/enc_time);

vm_string_fp rintf(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;

}

If you could please help me... I've only changed the code from line 92 to 135, so you don't have to look through the entire thing to see what I've done :-)

Sorry if this is to stupid a request. If it is so, please tell me and I've try elsewere to find answers...

-Rune

I'll ask our experts to take a look on this

Regards,
Vladimir

Thank you so very much!

-Rune

Hi, there is some advices from our experts:

line 62 (numbers could have been shifted): change InitAlloc to Init, because external buffer is used.

line 105 pDstStep should be filled with proper pitches, not zeros: pDstStep[0] = (int)p_dataIn->m_lPitch[0]; etc for 1 and 2.

line 116: in ippiBGRToYCbCr420_8u_C3P3R call 2nd argument should be set (srcStep). 3*mWidth, I guess.

Please also check if mWidth and mHeight are correct, that bitrate (in bits/sec) isnt too small, that bmp file fits into 1000000 size.

If width and height are not multiple of 16 they should be extended.

Also note that different codecs require .par files of different format, if used. Lines order should be kept.

It would be nice if command line, .par file if any and one .bmp file have been provided.

Regards,
Vladimir

>It would be nice if command line, .par file if any and one .bmp file have been provided.

I would love to, but I'm not sure how I can attatch enything here... is it possible, or should I place them onmy web server and provide you with links?

-Rune

Hi!

Your expert advice worked! I'm now able to create an mpeg-2 based avi file from a set of bmp files!

However, I can only get the mpeg-2 encoding to work. I was hoping for a more up to date encoder, like mpg-4, but I'm not able to get any of the others to work!!!

The command line I use is this:

For mpeg-2 encoding:
encoder m2 -i blah -w 384 -h 288 -f 25 -b 800000 -n 100 -o out_m2.avi
For h264-encoding:
encoder h264 -i blah -w 384 -h 288 -f 25 -b 800000 -n 100 -o out_h264.avi

etc. etc. (as I don't use an avi file as input I just write "dummy")

The result from the m2 command line is an avi file of 396 kB, not far from the goal (800 kbps x 4 secs = 400 kB). You can find the (working) mpeg-2 file here.

mpeg-4
When I try encoding with mpeg-4, the application completes without any error messages and the filesize is as expected (391 kB). The avi file, however, is not playable in any of my players (and I do have a lot).You can find it here.

h264
When I try encoding with h264, the application also completes without any error messages, nut this time the filesize isnot as expected (901 kB), and it's not playable either. You can find the output file here.

h262 & h263
When I try encoding with h261 or h263, the application fails on this line:

p_vidEncoder->Init(p_vidEncoderParams)

As far as I can see there's nothing wrong with the parameters, but who am I to tell...?

The source for my test application is here and the executable is here.

Thank you, Vladimir, your expert advice certainly helped!

I'm now able to convert a set of bmp files to a (working) mpeg-2 avi file!

However I'm not able to use any of the other codecs successfully. The application goes thought both the m4 and the h264 encoding process without any error messages, but the resulting files are unplayable. The m4 file is of the expected size (ca 400kB), but the h264 file is much larger than expected (ca 900 kB).

Trying to encode with h261/h263, the application failsat the following line:

if (p_vidEncoder->Init(p_vidEncoderParams) != UMC_OK)

As Init() returns not UMC_OK.

I don't care about h261/h263, however, as I only want to get the h264 / mpeg-4 encoding working.

I use the following command line:

vEnc h264 -i blah -w 384 -h 288 -f 25 -b 800000 -n 100 -o out_h264.avi

And here you can find my files:

Source file

Executable file
Working mpeg-2 file
Not working mpeg-4 file
Not working h264 file

Thank you for your time!

-Rune

Hi Rune,

Actually your output files are raw bitstreamsand not true AVI. You can try FFDSHOW to play your files

Nikolay

Hi Nikolay, and thanks for answering!

Raw bitstreams? I had no idea... I need very badly to be able to create a"legal" AVI file that can be played back natively on all platforms from WinXP and up.

My impression was that this was handled by the umc_video_enc_con example, but I may have screwed this up when I modified it to take single images as input.

Is there some way of modifying"my" source to create a "fully functional" AVI file?

-R

Rune,

the output of umc_video_enc_con is raw compressed video bitstream. To mux it to AVI you can use ffmpeg application for example. It is need only to rename out_m4.avi to out_m4.m4v and use such cmd

ffmpeg.exe-vcodec copy -i out_m4.m4v new.avi

the new.avi file will be created with 'FMP4' fourcc codec. You need to change FMP4 to DIVX

Nikolay

Hi Nicolay, and thanks for your reply!

I didn't know about the raw compressed video output of umc_video_enc_con...

I have a couple of problems with ffmpeg. One is the legal problem ofbundling ffmpeg with out commercial application.We already had a working video export based on mplayer/mencoder, but it was abandoned because of legal issues. i don't think we can use ffmpeg either, although I'm not 100% sure of this.

The other problem is that I don't know how to change the fourcc from FMP4 to DIVX. Does this require yet another third party application?

---

Can I alternatively use simple_player as a playback application without going through the hassle of using ffmepg and changing the fourcc?

-Rune

Hi Rune,

There are a lot of free tools for changing FOURCC.

About muxing - You can use some commercial AVI muxer in your application. Also you can look on sample below - this is a simple AVI muxer. It works good enough :) You mayusesomething similarin your application

#include

#include

#include

#include

#define MPEG4_W 352

#define MPEG4_H 288

void main(void)

{

char *AVIfilename = "out.avi";

char *MPEG4filename = "input.m4v";

AVISTREAMINFO strhdr;

PAVIFILE pfile;

PAVISTREAM ppavi;

int nFrames =0;

HRESULT hr;

BITMAPINFOHEADER bmpInfoHdr;

memset(&bmpInfoHdr, 0, sizeof(bmpInfoHdr));

bmpInfoHdr.biSize = sizeof(bmpInfoHdr);

bmpInfoHdr.biCompression = mmioFOURCC('D', 'I', 'V', 'X');

bmpInfoHdr.biWidth = MPEG4_W;

bmpInfoHdr.biHeight = MPEG4_H;

bmpInfoHdr.biBitCount = 24;

bmpInfoHdr.biPlanes = 1;

AVIFileInit();

hr = AVIFileOpen(&pfile, AVIfilename, OF_WRITE | OF_CREATE, NULL);

memset(&strhdr, 0, sizeof(strhdr));

strhdr.fccType = streamtypeVIDEO;

strhdr.fccHandler = mmioFOURCC('D', 'I', 'V', 'X');

strhdr.dwScale = 1;

strhdr.dwRate = 30;

strhdr.dwSuggestedBufferSize = MPEG4_W * MPEG4_H;

SetRect(&strhdr.rcFrame, 0, 0, MPEG4_W, MPEG4_H);

hr = AVIFileCreateStream(pfile, &ppavi, &strhdr);

hr = AVIStreamSetFormat(ppavi, nFrames, &bmpInfoHdr, sizeof(bmpInfoHdr));

FILE *fp =fopen(MPEG4filename, "rb");

int tmp1 = fseek(fp, 0, SEEK_END);

long length = ftell(fp);

int tmp2 = fseek(fp, 0, SEEK_SET);

BYTE *tmp_buf = new BYTE[length];

int tmp3 = fread(tmp_buf, 1, length, fp);

bool first = true;

int i = 0, j = 0, frameCount = 0, frameLength;

for (;;) {

for (; i < length; i ++) {

// find VOP or GOV start code

if (tmp_buf[i] == 0x00 && tmp_buf[i+1] == 0x00 && tmp_buf[i+2] == 0x01 && tmp_buf[i+3] == 0xB6 ||

tmp_buf[i] == 0x00 && tmp_buf[i+1] == 0x00 && tmp_buf[i+2] == 0x01 && tmp_buf[i+3] == 0xB3) {

if (first)

first = false;

else

break;

}

}

frameLength = i - j;

hr = AVIStreamWrite(ppavi, frameCount, 1, (LPBYTE) (tmp_buf+j), frameLength, AVIIF_KEYFRAME, NULL, NULL);

frameCount ++;

j = i;

i += 4;

if (i >= length)

break;

}

fclose(fp);

delete [] tmp_buf;

AVIStreamClose(ppavi);

if(pfile != NULL)

AVIFileRelease(pfile);

AVIFileExit();

}

Nikolay

Nikolay - you're da man!

Thank you so very much! Now it works from A to Z, no problems!

Now I'll make the code lean and clean and hopefully add audio (mp3 file) to the mux (if I figure it out...)

Thanks again!

-Rune

ARRRRRRGHH!

The generated videos won't play on pure Vista OR XP systems without any extra codecs installed (which was one of the goals of this whole project)...

I've tried to "cheat" by using other fourcc's than DIVX (like MP42 and such), but to no avail. Windows Media Player opens the file, but refuses to play it on newly installed Vista or XP boxes :-(

I'm using the mpg4 encoder. Is it any hopes for any of the other ones in the umc_video_encoder example (for instance h264)?

-Rune

Hi Rune,

As far as I know, MJPEG decoder should be available on any Windows system by default. I think that the same is true for H.263 decoder.

On Windows Vista there should be default MPEG2 decoder (but not on Windows XP)

Regards,
Vladimir

Hi Vladimir!

OK. I'll give it a shot with the H.263-encoder then. Any idea what FOURCC is to be used with the H.263 codec?

Thanks!

-Rune

Leave a Comment

Please sign in to add a comment. Not a member? Join today