I have written some avifile code that refuses to decode my AVIs to
YUV format. Well, perhaps the YUV code is wrong (untested because
avifile does not want to decode my avis), but the rest _looks_ ok.
But what I get are green images with a coloured line at the
top. I know that my YUV code is not the culprit because I dump
every image to a BMP and the bmps are exactly as unusable as the
created YUV file. What am I doing wrong? Playing back videos
through avifile works when using mplayer.
This is my code (the main problem is in ProcessAVIFile):
// C includes
#include <avifile/avifile.h>
#include <avifile/StreamInfo.h>
// C++ includes
#include <string>
#include <iostream>
#include <fstream>
struct FatalError
{
std::string err;
void print () const
{
std::cerr << err << std::endl;
}
FatalError (const std::string &s)
: err (s)
{
std::cerr << "Fatal error thrown: ";
print ();
}
FatalError (const FatalError &e)
: err (e.err)
{
}
};
int MP2_Framerates[] =
{
23976,
24000,
25000,
29970,
30000,
50000,
59940,
60000,
0
};
bool equal (int x, int y)
{
int const fuzz = 10;
return (x - y > -fuzz) && (y - x > -fuzz);
}
void YUV_BeginFile (std::ostream &f, int w, int h, float Framerate)
{
std::cerr << "Framerate: " << Framerate << std::endl;
int FramerateCode;
int fr = int (Framerate * 1000);
for (FramerateCode = 0;
MP2_Framerates [FramerateCode] && !equal (MP2_Framerates [FramerateCode], fr);
++FramerateCode);
if (MP2_Framerates [FramerateCode] == 0)
throw new FatalError ("Unsupported framrate. Try to supply one yourself!");
f << "YUV4MPEG " << w << " " << h << " " << (FramerateCode + 1) << std::endl;
}
void YUV_WriteFrame (std::ostream &f, int w, int h, uint8_t *y, uint8_t *u, uint8_t *v)
{
f << "FRAME" << std::endl;
f.write (y, w * h);
f.write (u, w * h / 4);
f.write (v, w * h / 4);
}
void YUV_WriteFrame (std::ostream &f, int w, int h, uint8_t *yuv)
{
uint8_t Y [w * h];
uint8_t U [w * h / 4];
uint8_t V [w * h / 4];
for (int y = 0; y < h; ++y)
for (int x = 0; x < w; ++x)
Y [x + w * y] = yuv [3 * (x + w * y)];
for (int y = 0; y < h / 2; ++y)
for (int x = 0; x < w / 2; ++x)
{
U [x + w / 2 * y]
= (yuv [3 * (2 * x + 2 * w * y) + 1]
+ yuv [3 * (2 * x + 2 * w * y + 1) + 1]
+ yuv [3 * (2 * x + 2 * w * y + w) + 1]
+ yuv [3 * (2 * x + 2 * w * y + w + 1) + 1]) >> 2;
V [x + w / 2 * y]
= (yuv [3 * (2 * x + 2 * w * y) + 2]
+ yuv [3 * (2 * x + 2 * w * y + 1) + 2]
+ yuv [3 * (2 * x + 2 * w * y + w) + 2]
+ yuv [3 * (2 * x + 2 * w * y + w + 1) + 2]) >> 2;
}
YUV_WriteFrame (f, w, h, Y, U, V);
}
void YUV_EndFile (std::ostream &f)
{
}
void ProcessAVIFile (std::string Filename, std::string Outfile)
{
std::ofstream f (Outfile.c_str ());
IAviReadFile *fAVI = CreateIAviReadFile (Filename.c_str ());
if (!fAVI)
throw new FatalError ("Could not open AVI file.");
IAviReadStream *AVI = fAVI->GetStream (0, AviStream::Video);
if (!AVI)
throw new FatalError ("Could not open AVI stream.");
double nSeconds = AVI->GetLengthTime ();
BITMAPINFOHEADER bi;
AVI->GetVideoFormatInfo (&bi, sizeof bi);
int nWidth = bi.biWidth;
int nHeight = bi.biHeight;
StreamInfo *si = AVI->GetStreamInfo ();
double nFPS = si->GetFps ();
std::cerr << "width: " << nWidth << ", height: " << nHeight << std::endl;
AVI->StartStreaming ();
AVI->GetDecoder ()->SetDestFmt (24, 0);
YUV_BeginFile (f, nWidth, nHeight, nFPS);
while (!AVI->Eof ())
{
CImage *img = AVI->GetFrame (true);
if (!img)
throw new FatalError ("img == NULL");
img->Dump ("test.bmp");
img->ToYUV ();
std::cerr << std::endl << img->Width() << "x" << img->Height() << "x" << img->Bpp()
<< "bpp" << std::endl;
uint8_t *YUV = img->Data ();
YUV_WriteFrame (f, nWidth, nHeight, YUV);
double nSecondsDone = AVI->GetTime ();
std::cerr.setf (std::ios::fixed);
std::cerr.precision (2);
std::cerr
<< "Encoded "
<< nSecondsDone
<< " of "
<< nSeconds
<< " seconds of AVI\r";
}
std::cerr << std::endl;
YUV_EndFile (f);
AVI->StopStreaming ();
delete si;
delete AVI;
delete fAVI;
}
int main (int argc, char **argv)
{
if (argc < 3)
{
std::cerr << "USAGE: avi2yuv infile.avi outfile.yuv" << std::endl;
return 1;
}
try
{
ProcessAVIFile (argv [1], argv [2]);
}
catch (const FatalError &e)
{
std::cerr << "Fatal error" << std::endl;
e.print ();
}
return 0;
}
_______________________________________________
Avifile mailing list
[EMAIL PROTECTED]
http://prak.org/mailman/listinfo/avifile