Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

Get Frame and Bitamp save problem

ulisses87
Beginner
629 Views

Hi,

I want to save all frames from MP4 video files as BMP files on my hard drive. I have designed working part of code, but unfortunately, saved BMP file is rotated at 180 degrees and flipped. You can see its below:

...and this is correct image:

I see also that colors are not the same...

I suppose that it's connected with little endian byte order of BMP and fact that lines in BMP standard are stored in inverted order BUT I still can't solve my problem.

What I did wrong?

BTW: Is it correct way? Maybe IPP has internal easy to use function for saving BMP files.

Thanks for any help.

It's my code:

#include
#include
#include "ipp.h"
#include "umc_file_reader.h"
#include "umc_fio_reader.h"
#include "umc_mp4_spl.h"
#include "umc_splitter.h"
#include "umc_video_render.h"
#include "fw_video_render.h"
#include "umc_h264_dec.h"
#include "vm_time.h"

//unsigned char rgbBuff[384 * 288 * 3];

void SaveBitmap(unsigned char *image, IppiSize imgSize, char* name){
//printf("%d\\n",sizeof(ℑ));
FILE *outputFp;
outputFp = fopen(name,"wb");
if(outputFp != NULL) {
BITMAPFILEHEADER bmpFileHdr;
BITMAPINFOHEADER bmpInfoHdr;
memset(&bmpFileHdr,0,sizeof(BITMAPFILEHEADER));
memset(&bmpInfoHdr,0,sizeof(BITMAPINFOHEADER));
//bmpFileHdr.bfType = 'B' + ('M'<<8); // 'BM'
bmpFileHdr.bfType = ('M' << 8) | 'B';
bmpFileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpFileHdr.bfSize = bmpFileHdr.bfOffBits + imgSize.width * imgSize.height * 3;
bmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHdr.biHeight = imgSize.height;
bmpInfoHdr.biWidth = imgSize.width;
bmpInfoHdr.biPlanes = 1;
bmpInfoHdr.biBitCount = 24;
bmpInfoHdr.biCompression = BI_RGB;
bmpInfoHdr.biSizeImage = imgSize.width * imgSize.height * 3;
fwrite(&bmpFileHdr,sizeof(BITMAPFILEHEADER),1,outputFp);
fwrite(&bmpInfoHdr,sizeof(BITMAPINFOHEADER),1,outputFp);
fwrite(image,1,sizeof(image),outputFp);
fclose(outputFp);
//printf("%d\\n",sizeof(image));
}
}

void EncodeStream(vm_char * inputfilename, vm_char * outputfilename)
{
Ipp32u videoTrack=0; int exit_flag =0;
UMC::Status status;
UMC::MediaData in; UMC::VideoData out;
UMC::FIOReader reader; UMC::FileReaderParams readerParams;
UMC::SplitterParams splitterParams; UMC::SplitterInfo * streamInfo;
UMC::MP4Splitter Splitter;

UMC::VideoStreamInfo *videoInfo=NULL;
UMC::VideoDecoder * videoDecoder; UMC::VideoDecoderParams videoDecParams;
UMC::FWVideoRender fwRender; UMC::FWVideoRenderParams fwRenderParams;

readerParams.m_portion_size = 0;
vm_string_strcpy(readerParams.m_file_name, inputfilename);
if((status = reader.Init(&readerParams))!= UMC::UMC_OK)
return;
splitterParams.m_lFlags = UMC::VIDEO_SPLITTER;
splitterParams.m_pDataReader = &reader;
if((status = Splitter.Init(splitterParams))!= UMC::UMC_OK)
return;
Splitter.GetInfo(&streamInfo);
for (videoTrack = 0; videoTrack < streamInfo->m_nOfTracks; videoTrack++) {
if (streamInfo->m_ppTrackInfo[videoTrack]->m_Type == UMC::TRACK_H264)
break;
}
videoInfo = (UMC::VideoStreamInfo*)(streamInfo->m_ppTrackInfo[videoTrack]->m_pStreamInfo);
if(videoInfo->stream_type!=UMC::H264_VIDEO)
return;
videoDecParams.info = (*videoInfo);
videoDecParams.m_pData = streamInfo->m_ppTrackInfo[videoTrack]->m_pDecSpecInfo;
videoDecParams.numThreads = 1;
videoDecoder = (UMC::VideoDecoder*)(new UMC::H264VideoDecoder());
if((status = videoDecoder->Init(&videoDecParams))!= UMC::UMC_OK)
return;
fwRenderParams.out_data_template.Init(videoInfo->clip_info.width, videoInfo->clip_info.height, videoInfo->color_format);
fwRenderParams.pOutFile = outputfilename;
if(status = fwRender.Init(&fwRenderParams)!= UMC::UMC_OK)
return;
Splitter.Run();

//for BMP saving
DWORD nWritten;
HANDLE fh;
FILE *outputFp;
BITMAPFILEHEADER bmpFileHdr;
BITMAPINFOHEADER bmpInfoHdr;
IppiSize imgSize;
imgSize.height=videoInfo->clip_info.height;
imgSize.width=videoInfo->clip_info.width;
unsigned char rgbBuff[384 * 288 * 3];
char name[20]="output ";
int i=0;
char number[10];
const Ipp8u* dst[3];
dst[0] = (Ipp8u*)malloc(imgSize.width * imgSize.height);
dst[1] = (Ipp8u*)malloc(imgSize.width * imgSize.height);
dst[2] = (Ipp8u*)malloc(imgSize.width * imgSize.height);

////
do
{ do{
if (in.GetDataSize() < 4) {
do{
status= Splitter.GetNextData(&in,videoTrack);
if(status==UMC::UMC_ERR_NOT_ENOUGH_DATA)
vm_time_sleep(5);
}while(status==UMC::UMC_ERR_NOT_ENOUGH_DATA);
if(((status != UMC::UMC_OK) && (status != UMC::UMC_ERR_END_OF_STREAM))||
(status == UMC::UMC_ERR_END_OF_STREAM)&& (in.GetDataSize()<4)) {
exit_flag=1;
}
}
fwRender.LockInputBuffer(&out);
videoDecoder->GetFrame(&in,&out);
//YUV420 to RGB conversion
dst[0] = (Ipp8u*)out.GetPlanePointer(0);
dst[1] = (Ipp8u*)out.GetPlanePointer(1);
dst[2] = (Ipp8u*)out.GetPlanePointer(2);
// printf("%d\\n",sizeof(rgbBuff));
/*ippSt =*/ ippiYUV420ToRGB_8u_P3C3(dst,rgbBuff,imgSize);
//printf("%d\\n",sizeof(rgbBuff));
/*if(ippSt != ippStsNoErr) {
return -1;
}*/
strcpy(name,"output ");
itoa(i,number,10);
strcat(name,number);
strcat(name,".bmp");
//SaveBitmap(rgbBuff,imgSize,name);/
/////////////

//outputFp = fopen(name,"wb");
//if(outputFp != NULL) {
memset(&bmpFileHdr,0,sizeof(BITMAPFILEHEADER));
memset(&bmpInfoHdr,0,sizeof(BITMAPINFOHEADER));
//bmpFileHdr.bfType = 'B' + ('M'<<8); // 'BM'
bmpFileHdr.bfType = ('M' << 8) | 'B';
bmpFileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpFileHdr.bfSize = bmpFileHdr.bfOffBits + imgSize.width * imgSize.height * 3;
bmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHdr.biHeight = imgSize.height;
bmpInfoHdr.biWidth = imgSize.width;
bmpInfoHdr.biPlanes = 1;
bmpInfoHdr.biBitCount = 24;
bmpInfoHdr.biCompression = BI_RGB;
bmpInfoHdr.biSizeImage = imgSize.width * imgSize.height * 3;
//fwrite(&bmpFileHdr,sizeof(BITMAPFILEHEADER),1,outputFp);
//fwrite(&bmpInfoHdr,sizeof(BITMAPINFOHEADER),1,outputFp);
//fwrite(rgbBuff,1,sizeof(rgbBuff),outputFp);
//fclose(outputFp);
//printf("%d\\n",sizeof(image));
fh = CreateFile(L"cos.bmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(fh, &bmpFileHdr,sizeof(BITMAPFILEHEADER), &nWritten, NULL);
WriteFile(fh, &bmpInfoHdr,sizeof(BITMAPINFOHEADER), &nWritten, NULL);
WriteFile(fh, rgbBuff, sizeof(rgbBuff), &nWritten, NULL);
CloseHandle(fh);
//}

//////////
fwRender.UnLockInputBuffer(&out);
fwRender.RenderFrame();
i++;
}while(!exit_flag && (status == UMC::UMC_ERR_NOT_ENOUGH_DATA || status == UMC::UMC_ERR_SYNC));
}while (exit_flag!=1);

do{
fwRender.LockInputBuffer(&out);
status = videoDecoder->GetFrame(NULL,&out);
fwRender.UnLockInputBuffer(&out);
fwRender.RenderFrame();
}while(status == UMC::UMC_OK);
}

void main(int argc, vm_char* argv[])
{
vm_char * InputVideofileName, *OutputYUVFileName;
InputVideofileName = VM_STRING("teststream.mp4"); //use unicode string if project use unicode characters
OutputYUVFileName = VM_STRING("testoutput.yuv"); //use unicode string if project use unicode characters

EncodeStream(InputVideofileName,OutputYUVFileName);
}

0 Kudos
3 Replies
Chao_Y_Intel
Moderator
629 Views


Hi,

IPP Mirror function can be used here to flip the image:

Mirrors an image about a horizontal or vertical axis, orboth.

IppStatus ippiMirror_(const Ipp* pSrc, int srcStep, Ipp* pDst,int dstStep, IppiSize roiSize, IppiAxis flip);

Thanks,
Chao

0 Kudos
ulisses87
Beginner
629 Views

Hi,

Thank you very much for your reply! It was solved my problem.

Could you tell me, if I find a built-in IPP function for BMP saving?

0 Kudos
Chao_Y_Intel
Moderator
629 Views


IPPlibarary does not include such function. IPP UIC sample code(\ipp-samples\image-codecs\uic) include some code on BMP file handling.

Thanks,
Chao
0 Kudos
Reply