Reputation: 633
I've read frame which is encoded with H264, decoded it, and converted it to YUV420P and the data is stored in frameYUV420->data
, (type of frame is AVFrame
). I want to save that data into a file that can be displayed with GIMP for example.
I know how to save RGB25 pixel format but i'm not quite sure how to do YUV420P. Though i know that Y component will take width x height , and Cb/Cr will take (width/2) x (height/2) amount of space needed to save the data. So i'm guessing i need to first write Y data, and after that i need to write Cb and Cr data. Does anyone have finished code that i could take a look at?
Upvotes: 1
Views: 4080
Reputation: 633
int saveYUVFrameToFile(AVFrame* frame, int width, int height)
{
FILE* fileHandle;
int y, writeError;
char filename[32];
static int frameNumber = 0;
sprintf(filename, "frame%d.yuv", frameNumber);
fileHandle = fopen(filename, "wb");
if (fileHandle == NULL)
{
printf("Unable to open %s...\n", filename);
return ERROR;
}
/*Writing Y plane data to file.*/
for (y = 0; y < height; y++)
{
writeError = fwrite(frame->data[0] + y*frame->linesize[0], 1, width, fileHandle);
if (writeError != width)
{
printf("Unable to write Y plane data!\n");
return ERROR;
}
}
/*Dividing by 2.*/
height >>= 1;
width >>= 1;
/*Writing U plane data to file.*/
for (y = 0; y < height; y++)
{
writeError = fwrite(frame->data[1] + y*frame->linesize[1], 1, width, fileHandle);
if (writeError != width)
{
printf("Unable to write U plane data!\n");
return ERROR;
}
}
/*Writing V plane data to file.*/
for (y = 0; y < height; y++)
{
writeError = fwrite(frame->data[2] + y*frame->linesize[2], 1, width, fileHandle);
if (writeError != width)
{
printf("Unable to write V plane data!\n");
return ERROR;
}
}
fclose(fileHandle);
frameNumber++;
return NO_ERROR;
Basicly this is what i came up with using several examples provided by FFmpeg and stackoverflow users.
Upvotes: 1
Reputation: 2432
void SaveAvFrame(AVFrame *avFrame)
{
FILE *fDump = fopen("...", "ab");
uint32_t pitchY = avFrame->linesize[0];
uint32_t pitchU = avFrame->linesize[1];
uint32_t pitchV = avFrame->linesize[2];
uint8_t *avY = avFrame->data[0];
uint8_t *avU = avFrame->data[1];
uint8_t *avV = avFrame->data[2];
for (uint32_t i = 0; i < avFrame->height; i++) {
fwrite(avY, avFrame->width, 1, fDump);
avY += pitchY;
}
for (uint32_t i = 0; i < avFrame->height/2; i++) {
fwrite(avU, avFrame->width/2, 1, fDump);
avU += pitchU;
}
for (uint32_t i = 0; i < avFrame->height/2; i++) {
fwrite(avV, avFrame->width/2, 1, fDump);
avV += pitchV;
}
fclose(fDump);
}
Upvotes: 5