Log in

View Full Version : How to wrap an already compressed stream to avi file?


yunsole
30th January 2006, 18:09
Hello,

I encode an yuv input to a compressed stream by some standard, let's say h.263, avc or mpeg4. This stream only has the head info. defined by the standard, and I would like to wrap it an avi file by using the AVIFILE functions.

My simple procedure is :

1. use AVIFileCreateStream() to create an empty stream associated with an avi file (exp. output.avi) to write.

2. set its format with AVIStreamSetFormat(), the FOURCC is also set in this step.

3. Assume I could handle each frame freely. After encoding a frame with a codec(exp. xvid), the compressed stream is stored in a buffer, lpOutput, and the size of the stream for the current frame is currFrmStreamSize, then I call function

AVIStreamWrite(pOutAvistream, FrmIdx, 1, lpOutput,
currFrmStreamSize, IsKeyFrame, NULL, NULL);

Where, pOutAvistream is the output avi stream created by AVIFileCreateStream(), FrmIdx is the index of the current frame.

My doubt is that whether the AVIStreamWrite() will aslo do compression itself since the microsoft document does not clearly say this function only write the data from lpOutput to pOutAvistream directly.

4. when all frames are coded, call AVIStreamRelease() and AVIFileRelease()


Has anybody done similar things before without only depending on the AVIFILE functions to create an avi file?

Thanks.

Guest
30th January 2006, 18:22
Wrong forum. Moving to Development.

squid_80
31st January 2006, 11:19
Sounds right. I've done a very similar thing with xvid_encraw to put mpeg4 asp in avi files.

Here's the setup code (sorry about the indents): /* Open the .avi output then close it */
/* Resets the file size to 0, which AVIFile doesn't seem to do */
FILE *scrub;
if ((scrub = fopen(ARG_AVIOUTPUTFILE, "w+b")) == NULL) {
fprintf(stderr, "Error opening output file %s\n", ARG_AVIOUTPUTFILE);
goto release_all;
}
else
fclose(scrub);

memset(&myAVIStreamInfo, 0, sizeof(AVISTREAMINFO));
myAVIStreamInfo.fccType = streamtypeVIDEO;
myAVIStreamInfo.fccHandler = MAKEFOURCC('x', 'v', 'i', 'd');
myAVIStreamInfo.dwScale = ARG_DWSCALE;
myAVIStreamInfo.dwRate = ARG_DWRATE;
myAVIStreamInfo.dwLength = ARG_MAXFRAMENR;
myAVIStreamInfo.dwQuality = 10000;
SetRect(&myAVIStreamInfo.rcFrame, 0, 0, YDIM, XDIM);

if (avierr=AVIFileOpen(&myAVIFile, ARG_AVIOUTPUTFILE, OF_CREATE|OF_WRITE, NULL)) {
fprintf(stderr, "AVIFileOpen failed opening output file %s, error code %d\n", ARG_AVIOUTPUTFILE, avierr);
goto release_all;
}

if (avierr=AVIFileCreateStream(myAVIFile, &myAVIStream, &myAVIStreamInfo)) {
fprintf(stderr, "AVIFileCreateStream failed, error code %d\n", avierr);
goto release_all;
}

memset(&myBitmapInfoHeader, 0, sizeof(BITMAPINFOHEADER));
myBitmapInfoHeader.biHeight = YDIM;
myBitmapInfoHeader.biWidth = XDIM;
myBitmapInfoHeader.biPlanes = 1;
myBitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
myBitmapInfoHeader.biCompression = MAKEFOURCC('X', 'V', 'I', 'D');
myBitmapInfoHeader.biBitCount = 12;
myBitmapInfoHeader.biSizeImage = 6*XDIM*YDIM;
if (avierr=AVIStreamSetFormat(myAVIStream, 0, &myBitmapInfoHeader, sizeof(BITMAPINFOHEADER))) {
fprintf(stderr, "AVIStreamSetFormat failed, error code %d\n", avierr);
goto release_all;

And for writing a compressed data to a frame:
if (AVIStreamWrite(myAVIStream, output_num, 1, mp4_buffer, m4v_size, key ? AVIIF_KEYFRAME : 0, NULL, NULL)) {
fprintf(stderr, "AVIStreamWrite failed writing frame %d\n", output_num);
goto release_all;
}

And finishing off: if (myAVIStream) AVIStreamRelease(myAVIStream);
if (myAVIFile) AVIFileRelease(myAVIFile);

Of course don't forget AVIFileInit() and AVIFileExit(). I think AVIStreamWrite only attempts compression itself when the stream is created with AVIMakeCompressedStream().