summaryrefslogtreecommitdiffstats
path: root/libmpdemux/muxer_avi.c
diff options
context:
space:
mode:
authorranma <ranma@b3059339-0415-0410-9bf9-f77b7e298cf2>2004-03-17 14:50:37 +0000
committerranma <ranma@b3059339-0415-0410-9bf9-f77b7e298cf2>2004-03-17 14:50:37 +0000
commit873b579c1afbe832b108bf4254adc9bb27130db6 (patch)
tree052e21d9fefff721cbe8d91329e92c325597a242 /libmpdemux/muxer_avi.c
parent6080f085606ffe918a0260dc94a0e9c59f02cce7 (diff)
downloadmpv-873b579c1afbe832b108bf4254adc9bb27130db6.tar.bz2
mpv-873b579c1afbe832b108bf4254adc9bb27130db6.tar.xz
OpenDML read/write support
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@12037 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux/muxer_avi.c')
-rw-r--r--libmpdemux/muxer_avi.c411
1 files changed, 360 insertions, 51 deletions
diff --git a/libmpdemux/muxer_avi.c b/libmpdemux/muxer_avi.c
index f98f4b0002..f6be330f69 100644
--- a/libmpdemux/muxer_avi.c
+++ b/libmpdemux/muxer_avi.c
@@ -1,16 +1,16 @@
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
+#include <limits.h>
#include "config.h"
#include "../version.h"
-//#include "stream.h"
-//#include "demuxer.h"
-//#include "stheader.h"
+#include "stream.h"
+#include "demuxer.h"
+#include "stheader.h"
#include "wine/mmreg.h"
#include "wine/avifmt.h"
@@ -19,6 +19,7 @@
#include "muxer.h"
#include "aviheader.h"
+#include "mp_msg.h"
extern char *info_name;
extern char *info_artist;
@@ -28,11 +29,38 @@ extern char *info_copyright;
extern char *info_sourceform;
extern char *info_comment;
+/* #define ODML_CHUNKLEN 0x02000000 */ /* for testing purposes */
+#define ODML_CHUNKLEN 0x40000000
+#define ODML_NOTKEYFRAME 0x80000000U
+#define MOVIALIGN 0x00001000
+
+struct avi_odmlidx_entry {
+ uint64_t ofs;
+ uint32_t len;
+ uint32_t flags;
+};
+
+struct avi_odmlsuperidx_entry {
+ uint64_t ofs;
+ uint32_t len;
+ uint32_t duration;
+};
+
+struct avi_stream_info {
+ int idxsize;
+ int idxpos;
+ int superidxpos;
+ int superidxsize;
+ struct avi_odmlidx_entry *idx;
+ struct avi_odmlsuperidx_entry *superidx;
+};
+
static muxer_stream_t* avifile_new_stream(muxer_t *muxer,int type){
+ struct avi_stream_info *si;
muxer_stream_t* s;
if (!muxer) return NULL;
if(muxer->avih.dwStreams>=MUXER_MAX_STREAMS){
- printf("Too many streams! increase MUXER_MAX_STREAMS !\n");
+ mp_msg(MSGT_MUXER, MSGL_ERR, "Too many streams! increase MUXER_MAX_STREAMS !\n");
return NULL;
}
s=malloc(sizeof(muxer_stream_t));
@@ -44,6 +72,11 @@ static muxer_stream_t* avifile_new_stream(muxer_t *muxer,int type){
s->timer=0.0;
s->size=0;
s->muxer=muxer;
+ s->priv=si=malloc(sizeof(struct avi_stream_info));
+ memset(si,0,sizeof(struct avi_stream_info));
+ si->idxsize=256;
+ si->idx=malloc(sizeof(struct avi_odmlidx_entry)*si->idxsize);
+
switch(type){
case MUXER_TYPE_VIDEO:
s->ckid=mmioFOURCC(('0'+s->id/10),('0'+(s->id%10)),'d','c');
@@ -55,7 +88,7 @@ static muxer_stream_t* avifile_new_stream(muxer_t *muxer,int type){
s->h.fccType=streamtypeAUDIO;
break;
default:
- printf("WarninG! unknown stream type: %d\n",type);
+ mp_msg(MSGT_MUXER, MSGL_WARN, "Warning! unknown stream type: %d\n",type);
return NULL;
}
muxer->avih.dwStreams++;
@@ -90,28 +123,80 @@ if(len>0){
}
}
+static void write_avi_list(FILE *f,unsigned int id,int len);
+static void avifile_write_index(muxer_t *muxer);
+
+static void avifile_odml_new_riff(muxer_t *muxer)
+{
+ FILE *f = muxer->file;
+ uint32_t riff[3];
+
+ /* Pad to ODML_CHUNKLEN */
+ write_avi_chunk(f,ckidAVIPADDING,ODML_CHUNKLEN - (ftello(f)%ODML_CHUNKLEN) - 8,NULL);
+
+ /* RIFF/AVIX chunk */
+ riff[0]=le2me_32(mmioFOURCC('R','I','F','F'));
+ riff[1]=0;
+ riff[2]=le2me_32(mmioFOURCC('A','V','I','X'));
+ fwrite(riff,12,1,f);
+
+ write_avi_list(f,listtypeAVIMOVIE,0);
+}
+
static void avifile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags){
+ off_t pos;
+ struct avi_stream_info *si = s->priv;
muxer_t *muxer=s->muxer;
+ int isodml = muxer->file_end > ODML_CHUNKLEN ? 1 : 0;
+
+ if (!isodml) {
+ // add to the traditional index:
+ if(muxer->idx_pos>=muxer->idx_size){
+ muxer->idx_size+=256; // 4kB
+ muxer->idx=realloc(muxer->idx,16*muxer->idx_size);
+ }
+ muxer->idx[muxer->idx_pos].ckid=s->ckid;
+ muxer->idx[muxer->idx_pos].dwFlags=flags; // keyframe?
+ muxer->idx[muxer->idx_pos].dwChunkOffset=ftello(muxer->file)-(muxer->movi_start-4);
+ muxer->idx[muxer->idx_pos].dwChunkLength=len;
+ ++muxer->idx_pos;
+ }
+
+ // add to odml index
+ if(si->idxpos>=si->idxsize){
+ si->idxsize+=256;
+ si->idx=realloc(si->idx,sizeof(*si->idx)*si->idxsize);
+ }
+ si->idx[si->idxpos].flags=(flags&AVIIF_KEYFRAME)?0:ODML_NOTKEYFRAME;
+ si->idx[si->idxpos].ofs=ftello(muxer->file);
+ si->idx[si->idxpos].len=len;
+ ++si->idxpos;
+
+ pos = muxer->file_end;
+ if (pos < ODML_CHUNKLEN &&
+ pos + 16*muxer->idx_pos + len + 8 > ODML_CHUNKLEN) {
- // add to the index:
- if(muxer->idx_pos>=muxer->idx_size){
- muxer->idx_size+=256; // 4kB
- muxer->idx=realloc(muxer->idx,16*muxer->idx_size);
+ avifile_write_index(muxer);
+ avifile_odml_new_riff(muxer);
+
+ pos = muxer->file_end = ftello(muxer->file);
+ }
+ if (pos % ODML_CHUNKLEN + len + 8 > ODML_CHUNKLEN) {
+ avifile_odml_new_riff(muxer);
+ muxer->file_end = ftello(muxer->file);
}
- muxer->idx[muxer->idx_pos].ckid=s->ckid;
- muxer->idx[muxer->idx_pos].dwFlags=flags; // keyframe?
- muxer->idx[muxer->idx_pos].dwChunkOffset=ftell(muxer->file)-(muxer->movi_start-4);
- muxer->idx[muxer->idx_pos].dwChunkLength=len;
- ++muxer->idx_pos;
// write out the chunk:
write_avi_chunk(muxer->file,s->ckid,len,s->buffer); /* unsigned char */
// alter counters:
+ if (len > s->h.dwSuggestedBufferSize){
+ s->h.dwSuggestedBufferSize = len;
+ }
if(s->h.dwSampleSize){
// CBR
s->h.dwLength+=len/s->h.dwSampleSize;
- if(len%s->h.dwSampleSize) printf("Warning! len isn't divisable by samplesize!\n");
+ if(len%s->h.dwSampleSize) mp_msg(MSGT_MUXER, MSGL_WARN, "Warning! len isn't divisable by samplesize!\n");
} else {
// VBR
s->h.dwLength++;
@@ -120,6 +205,7 @@ static void avifile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags)
s->size+=len;
if((unsigned int)len>s->h.dwSuggestedBufferSize) s->h.dwSuggestedBufferSize=len;
+ muxer->file_end += len + 8;
}
static void write_avi_list(FILE *f,unsigned int id,int len){
@@ -137,28 +223,79 @@ static void write_avi_list(FILE *f,unsigned int id,int len){
#define WFSIZE(wf) (sizeof(WAVEFORMATEX)+(wf)->cbSize)
+static unsigned int avi_aspect(sh_video_t *sh_video)
+{
+ float aspect = sh_video->aspect;
+ if (aspect <= 0.0) {
+ aspect = (float)sh_video->disp_w/(float)sh_video->disp_h;
+ }
+ if (aspect >= 3.99/3.0 &&
+ aspect <= 4.01/3.0) return MAKE_AVI_ASPECT(4,3);
+ if (aspect >= 15.99/9.0 &&
+ aspect <= 16.01/9.0) return MAKE_AVI_ASPECT(16,9);
+ if (aspect >= 0.99 &&
+ aspect <= 1.01) return MAKE_AVI_ASPECT(1,1);
+ if (aspect<1.0) return MAKE_AVI_ASPECT((int)(aspect*8192),8192);
+ return MAKE_AVI_ASPECT(8192,(int)(8192/aspect));
+}
+
static void avifile_write_header(muxer_t *muxer){
uint32_t riff[3];
+ unsigned int dmlh[1];
unsigned int i;
unsigned int hdrsize;
muxer_info_t info[16];
- FILE *f=muxer->file;
-
- // RIFF header:
- riff[0]=mmioFOURCC('R','I','F','F');
- riff[1]=muxer->file_end-2*sizeof(unsigned int); // filesize
- riff[2]=formtypeAVI; // 'AVI '
- riff[0]=le2me_32(riff[0]);
- riff[1]=le2me_32(riff[1]);
- riff[2]=le2me_32(riff[2]);
- fwrite(&riff,12,1,f);
+ FILE *f = muxer->file;
+ VideoPropHeader vprp;
+ off_t pos;
+ int isodml = muxer->file_end > ODML_CHUNKLEN ? 1 : 0;
+
+ if (isodml) {
+ for (pos = 0; pos < muxer->file_end; pos += ODML_CHUNKLEN) {
+ unsigned int rifflen, movilen;
+
+ /* fixup RIFF length */
+ if (muxer->file_end - pos > ODML_CHUNKLEN) {
+ rifflen = le2me_32(ODML_CHUNKLEN - 8);
+ movilen = le2me_32(ODML_CHUNKLEN - 20);
+ } else {
+ rifflen = le2me_32(muxer->file_end - pos - 8);
+ movilen = le2me_32(muxer->file_end - pos - 20);
+ }
+ fseeko(f, pos + 4, SEEK_SET);
+ fwrite(&rifflen,4,1,f);
+
+ /* fixup movi length */
+ if (pos > 0) {
+ fseeko(f, pos + 16, SEEK_SET);
+ fwrite(&movilen,4,1,f);
+ }
+ }
+
+ fseeko(f, 12, SEEK_SET);
+ } else {
+ // RIFF header:
+ riff[0]=mmioFOURCC('R','I','F','F');
+ riff[1]=muxer->file_end-2*sizeof(unsigned int); // filesize
+ riff[2]=formtypeAVI; // 'AVI '
+ riff[0]=le2me_32(riff[0]);
+ riff[1]=le2me_32(riff[1]);
+ riff[2]=le2me_32(riff[2]);
+ fwrite(&riff,12,1,f);
+ }
+
// update AVI header:
if(muxer->def_v){
+ int i;
muxer->avih.dwMicroSecPerFrame=1000000.0*muxer->def_v->h.dwScale/muxer->def_v->h.dwRate;
// muxer->avih.dwMaxBytesPerSec=1000000; // dummy!!!!! FIXME
// muxer->avih.dwPaddingGranularity=2; // ???
muxer->avih.dwFlags|=AVIF_ISINTERLEAVED|AVIF_TRUSTCKTYPE;
- muxer->avih.dwTotalFrames=muxer->def_v->h.dwLength;
+ muxer->avih.dwTotalFrames=0;
+ for (i=0; i<muxer->idx_pos; i++) {
+ if (muxer->idx[i].ckid == muxer->def_v->ckid)
+ muxer->avih.dwTotalFrames++;
+ }
// muxer->avih.dwSuggestedBufferSize=muxer->def_v->h.dwSuggestedBufferSize;
muxer->avih.dwWidth=muxer->def_v->bih->biWidth;
muxer->avih.dwHeight=muxer->def_v->bih->biHeight;
@@ -166,18 +303,26 @@ static void avifile_write_header(muxer_t *muxer){
// AVI header:
hdrsize=sizeof(muxer->avih)+8;
+ if (isodml) hdrsize+=sizeof(dmlh)+20; // dmlh
// calc total header size:
for(i=0;i<muxer->avih.dwStreams;i++){
+ muxer_stream_t *s = muxer->streams[i];
+ struct avi_stream_info *si = s->priv;
+
hdrsize+=12; // LIST
hdrsize+=sizeof(muxer->streams[i]->h)+8; // strh
switch(muxer->streams[i]->type){
case MUXER_TYPE_VIDEO:
hdrsize+=muxer->streams[i]->bih->biSize+8; // strf
+ hdrsize+=8+4*(9+8*1); // vprp
break;
case MUXER_TYPE_AUDIO:
hdrsize+=WFSIZE(muxer->streams[i]->wf)+8; // strf
break;
}
+ if (isodml && si && si->superidx && si->superidxsize) {
+ hdrsize += 32 + 16*si->superidxsize; //indx
+ }
}
write_avi_list(f,listtypeAVIHEADER,hdrsize);
@@ -187,40 +332,103 @@ static void avifile_write_header(muxer_t *muxer){
// stream headers:
for(i=0;i<muxer->avih.dwStreams;i++){
- hdrsize=sizeof(muxer->streams[i]->h)+8; // strh
- switch(muxer->streams[i]->type){
+ muxer_stream_t *s = muxer->streams[i];
+ struct avi_stream_info *si = s->priv;
+ unsigned int idxhdr[8];
+ int j,n;
+
+ hdrsize=sizeof(s->h)+8; // strh
+ if (si && si->superidx && si->superidxsize) {
+ hdrsize += 32 + 16*si->superidxsize; //indx
+ }
+ switch(s->type){
case MUXER_TYPE_VIDEO:
- hdrsize+=muxer->streams[i]->bih->biSize+8; // strf
- muxer->streams[i]->h.fccHandler = muxer->streams[i]->bih->biCompression;
+ hdrsize+=s->bih->biSize+8; // strf
+ s->h.fccHandler = s->bih->biCompression;
+ s->h.rcFrame.right = s->bih->biWidth;
+ s->h.rcFrame.bottom = s->bih->biHeight;
+ // fill out vprp info
+ memset(&vprp, 0, sizeof(vprp));
+ vprp.dwVerticalRefreshRate = (s->h.dwRate+s->h.dwScale-1)/s->h.dwScale;
+ vprp.dwHTotalInT = muxer->avih.dwWidth;
+ vprp.dwVTotalInLines = muxer->avih.dwHeight;
+ vprp.dwFrameAspectRatio = avi_aspect(s->source);
+ vprp.dwFrameWidthInPixels = muxer->avih.dwWidth;
+ vprp.dwFrameHeightInLines = muxer->avih.dwHeight;
+ vprp.nbFieldPerFrame = 1;
+ vprp.FieldInfo[0].CompressedBMHeight = muxer->avih.dwHeight;
+ vprp.FieldInfo[0].CompressedBMWidth = muxer->avih.dwWidth;
+ vprp.FieldInfo[0].ValidBMHeight = muxer->avih.dwHeight;
+ vprp.FieldInfo[0].ValidBMWidth = muxer->avih.dwWidth;
+ hdrsize+=8+4*(9+8*1); // vprp
break;
case MUXER_TYPE_AUDIO:
- hdrsize+=WFSIZE(muxer->streams[i]->wf)+8; // strf
- muxer->streams[i]->h.fccHandler = muxer->streams[i]->wf->wFormatTag;
+ hdrsize+=WFSIZE(s->wf)+8; // strf
+ s->h.fccHandler = s->wf->wFormatTag;
break;
}
+
write_avi_list(f,listtypeSTREAMHEADER,hdrsize);
- le2me_AVIStreamHeader(&muxer->streams[i]->h);
- write_avi_chunk(f,ckidSTREAMHEADER,sizeof(muxer->streams[i]->h),&muxer->streams[i]->h); /* AVISTreamHeader */ // strh
- le2me_AVIStreamHeader(&muxer->streams[i]->h);
+ le2me_AVIStreamHeader(&s->h);
+ write_avi_chunk(f,ckidSTREAMHEADER,sizeof(s->h),&s->h); /* AVISTreamHeader */ // strh
+ le2me_AVIStreamHeader(&s->h);
- switch(muxer->streams[i]->type){
+ switch(s->type){
case MUXER_TYPE_VIDEO:
{
- int biSize=muxer->streams[i]->bih->biSize;
- le2me_BITMAPINFOHEADER(muxer->streams[i]->bih);
- write_avi_chunk(f,ckidSTREAMFORMAT,biSize,muxer->streams[i]->bih); /* BITMAPINFOHEADER */
- le2me_BITMAPINFOHEADER(muxer->streams[i]->bih);
+ int biSize=s->bih->biSize;
+ le2me_BITMAPINFOHEADER(s->bih);
+ write_avi_chunk(f,ckidSTREAMFORMAT,biSize,s->bih); /* BITMAPINFOHEADER */
+ le2me_BITMAPINFOHEADER(s->bih);
+ le2me_VideoPropHeader(&vprp);
+ le2me_VIDEO_FIELD_DESC(&vprp.FieldInfo[0]);
+ le2me_VIDEO_FIELD_DESC(&vprp.FieldInfo[1]);
+ write_avi_chunk(f,mmioFOURCC('v','p','r','p'),
+ sizeof(VideoPropHeader) -
+ sizeof(VIDEO_FIELD_DESC)*(2-vprp.nbFieldPerFrame),
+ &vprp); /* Video Properties Header */
}
break;
case MUXER_TYPE_AUDIO:
{
- int wfsize = WFSIZE(muxer->streams[i]->wf);
- le2me_WAVEFORMATEX(muxer->streams[i]->wf);
- write_avi_chunk(f,ckidSTREAMFORMAT,wfsize,muxer->streams[i]->wf); /* WAVEFORMATEX */
- le2me_WAVEFORMATEX(muxer->streams[i]->wf);
+ int wfsize = WFSIZE(s->wf);
+ le2me_WAVEFORMATEX(s->wf);
+ write_avi_chunk(f,ckidSTREAMFORMAT,wfsize,s->wf); /* WAVEFORMATEX */
+ le2me_WAVEFORMATEX(s->wf);
}
break;
}
+ if (isodml && si && si->superidx && si->superidxsize) {
+ n = si->superidxsize;
+
+ idxhdr[0] = le2me_32(mmioFOURCC('i', 'n', 'd', 'x'));
+ idxhdr[1] = le2me_32(24 + 16*n);
+ idxhdr[2] = le2me_32(0x00000004);
+ idxhdr[3] = le2me_32(si->superidxpos);
+ idxhdr[4] = le2me_32(s->ckid);
+ idxhdr[5] = 0;
+ idxhdr[6] = 0;
+ idxhdr[7] = 0;
+
+ fwrite(idxhdr,sizeof(idxhdr),1,f);
+ for (j=0; j<n; j++) {
+ struct avi_odmlsuperidx_entry *entry = &si->superidx[j];
+ unsigned int data[4];
+ data[0] = le2me_32(entry->ofs);
+ data[1] = le2me_32(entry->ofs >> 32);
+ data[2] = le2me_32(entry->len);
+ data[3] = le2me_32(entry->duration);
+ fwrite(data,sizeof(data),1,f);
+ }
+ }
+ }
+
+ // ODML
+ if (isodml) {
+ memset(dmlh, 0, sizeof(dmlh));
+ dmlh[0] = le2me_32(muxer->avih.dwTotalFrames);
+ write_avi_list(f,mmioFOURCC('o','d','m','l'),sizeof(dmlh)+8);
+ write_avi_chunk(f,mmioFOURCC('d','m','l','h'),sizeof(dmlh),dmlh);
}
// ============= INFO ===============
@@ -274,14 +482,115 @@ info[i].id=0;
}
// JUNK:
- write_avi_chunk(f,ckidAVIPADDING,2048-(ftell(f)&2047)-8,NULL); /* junk */
- // 'movi' header:
- write_avi_list(f,listtypeAVIMOVIE,muxer->movi_end-ftell(f)-12);
- muxer->movi_start=ftell(f);
+ write_avi_chunk(f,ckidAVIPADDING,MOVIALIGN-(ftello(f)%MOVIALIGN)-8,NULL); /* junk */
+ if (!isodml) {
+ // 'movi' header:
+ write_avi_list(f,listtypeAVIMOVIE,muxer->movi_end-ftello(f)-12);
+ } else {
+ if (ftello(f) != MOVIALIGN) {
+ mp_msg(MSGT_MUXER, MSGL_ERR, "Opendml superindex is too big for reserved space!\n");
+ mp_msg(MSGT_MUXER, MSGL_ERR, "Expected filepos %d, real filepos %d, missing space %d\n", MOVIALIGN, ftell(muxer->file), ftell(muxer->file)-MOVIALIGN);
+ mp_msg(MSGT_MUXER, MSGL_ERR, "Try increasing MOVIALIGN in libmpdemux/muxer_avi.c\n", MOVIALIGN, ftell(muxer->file), ftell(muxer->file)-MOVIALIGN);
+ }
+ write_avi_list(f,listtypeAVIMOVIE,muxer->movi_end-ftello(f)-12);
+ }
+ muxer->movi_start=ftello(muxer->file);
+}
+
+static void avifile_odml_write_index(muxer_t *muxer){
+ muxer_stream_t* s;
+ struct avi_stream_info *si;
+ int i;
+
+ for (i=0; i<muxer->avih.dwStreams; i++) {
+ int j,k,n,idxpos,len,last,entries_per_subidx;
+ unsigned int idxhdr[8];
+ s = muxer->streams[i];
+ si = s->priv;
+
+ /*
+ * According to Avery Lee MSMP wants the subidx chunks to have the same size.
+ *
+ * So this code figures out how many entries we can put into
+ * an ix?? chunk, so that each ix?? chunk has the same size and the offsets
+ * don't overflow (Using ODML_CHUNKLEN for that is a bit more restrictive
+ * than it has to be though).
+ */
+
+ len = 0;
+ n = 0;
+ entries_per_subidx = INT_MAX;
+ do {
+ off_t start = si->idx[0].ofs;
+ last = entries_per_subidx;
+ for (j=0; j<si->idxpos; j++) {
+ len = si->idx[j].ofs - start;
+ if(len >= ODML_CHUNKLEN || n >= entries_per_subidx) {
+ if (entries_per_subidx > n) {
+ entries_per_subidx = n;
+ }
+ start = si->idx[j].ofs;
+ len = 0;
+ n = 0;
+ }
+ n++;
+ }
+ } while (last != entries_per_subidx);
+
+ si->superidxpos = (si->idxpos+entries_per_subidx-1) / entries_per_subidx;
+
+ mp_msg(MSGT_MUXER, MSGL_V, "ODML: Stream %d: Using %d entries per subidx, %d entries in superidx\n",
+ i, entries_per_subidx, si->superidxpos);
+
+ si->superidxsize = si->superidxpos;
+ si->superidx = malloc(sizeof(*si->superidx) * si->superidxsize);
+ memset(si->superidx, 0, sizeof(*si->superidx) * si->superidxsize);
+
+ idxpos = 0;
+ for (j=0; j<si->superidxpos; j++) {
+ off_t start = si->idx[idxpos].ofs;
+ int duration;
+
+ duration = 0;
+ for (k=0; k<entries_per_subidx && idxpos+k<si->idxpos; k++) {
+ duration += s->h.dwSampleSize ? si->idx[idxpos+k].len/s->h.dwSampleSize : 1;
+ }
+
+ idxhdr[0] = le2me_32((s->ckid << 16) | mmioFOURCC('i', 'x', 0, 0));
+ idxhdr[1] = le2me_32(24 + 8*k);
+ idxhdr[2] = le2me_32(0x01000002);
+ idxhdr[3] = le2me_32(k);
+ idxhdr[4] = le2me_32(s->ckid);
+ idxhdr[5] = le2me_32(start + 8);
+ idxhdr[6] = le2me_32((start + 8)>> 32);
+ idxhdr[7] = 0; /* unused */
+
+ si->superidx[j].len = 32 + 8*k;
+ si->superidx[j].ofs = ftello(muxer->file);
+ si->superidx[j].duration = duration;
+
+ fwrite(idxhdr,sizeof(idxhdr),1,muxer->file);
+ for (k=0; k<entries_per_subidx && idxpos<si->idxpos; k++) {
+ unsigned int entry[2];
+ entry[0] = le2me_32(si->idx[idxpos].ofs - start);
+ entry[1] = le2me_32(si->idx[idxpos].len | si->idx[idxpos].flags);
+ idxpos++;
+ fwrite(entry,sizeof(entry),1,muxer->file);
+ }
+ }
+ }
+ muxer->file_end=ftello(muxer->file);
}
static void avifile_write_index(muxer_t *muxer){
- muxer->movi_end=ftell(muxer->file);
+
+ if(muxer->file_end > ODML_CHUNKLEN &&
+ muxer->idx && muxer->idx_pos>0) {
+ avifile_odml_write_index(muxer);
+ return;
+ }
+
+ muxer->movi_end=ftello(muxer->file);
if(muxer->idx && muxer->idx_pos>0){
int i;
// fixup index entries:
@@ -292,7 +601,7 @@ static void avifile_write_index(muxer_t *muxer){
for (i=0; i<muxer->idx_pos; i++) le2me_AVIINDEXENTRY((&muxer->idx[i]));
muxer->avih.dwFlags|=AVIF_HASINDEX;
}
- muxer->file_end=ftell(muxer->file);
+ muxer->file_end=ftello(muxer->file);
}
void muxer_init_muxer_avi(muxer_t *muxer){