- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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);
}
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
IPP Mirror function can be used here to flip the image:
Mirrors an image about a horizontal or vertical axis, orboth.
IppStatus ippiMirror_
Thanks,
Chao
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IPPlibarary does not include such function. IPP UIC sample code(\ipp-samples\image-codecs\uic) include some code on BMP file handling.
Thanks,
Chao
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page