Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

Get Frame and Bitamp save problem

ulisses87
Beginner
419 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
419 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
419 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
419 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