void TextureMap::GenerateFilteredMaps() { int r,s,x,y; int lowres,highres; float sample[samples]; float *sample1=(float*)calloc(samples,sizeof(float)), *sample2=(float*)calloc(samples,sizeof(float)), *sample3=(float*)calloc(samples,sizeof(float)), *sample4=(float*)calloc(samples,sizeof(float)); for(r=maxresolution-1;r>=0;r--) { highres=2*(1<<r); lowres=(1<<r); for(x=0;x<lowres;x++) { for(y=0;y<lowres;y++) { ReadUnfilteredSample(r+1,x*2+0,y*2+0,sample1); ReadUnfilteredSample(r+1,x*2+1,y*2+0,sample2); ReadUnfilteredSample(r+1,x*2+0,y*2+1,sample3); ReadUnfilteredSample(r+1,x*2+1,y*2+1,sample4); for(s=0;s<samples;s++) { sample[s]=0.25*(sample1[s]+sample2[s]+sample3[s]+sample4[s]); } WriteSample(r,x,y,sample); } } } free(sample1); free(sample2); free(sample3); free(sample4); }
static double ChooseSample (void *vpar, long i, long j) { Sample_Param *param = (Sample_Param *)vpar; double x, y; if (swrite_Basic) WriteSample (vpar, 0, j); x = i * param->a + j * param->b + param->c; y = param->F(x); return y; }
/*---------------------------------------------------------------------- | WriteSamples +---------------------------------------------------------------------*/ static void WriteSamples(AP4_Track* track, AP4_SampleDescription* sdesc, AP4_ByteStream* output) { // make the frame prefix unsigned int nalu_length_size = 0; AP4_DataBuffer prefix; if (AP4_FAILED(MakeFramePrefix(sdesc, prefix, nalu_length_size))) { return; } AP4_Sample sample; AP4_DataBuffer data; AP4_Ordinal index = 0; while (AP4_SUCCEEDED(track->ReadSample(index, sample, data))) { WriteSample(data, prefix, nalu_length_size, output); index++; } }
/*---------------------------------------------------------------------- | DecryptAndWriteSamples +---------------------------------------------------------------------*/ static void DecryptAndWriteSamples(AP4_Track* track, AP4_SampleDescription* sdesc, AP4_Byte* key, AP4_ByteStream* output) { AP4_ProtectedSampleDescription* pdesc = AP4_DYNAMIC_CAST(AP4_ProtectedSampleDescription, sdesc); if (pdesc == NULL) { fprintf(stderr, "ERROR: unable to obtain cipher info\n"); return; } // get the original sample description and make the prefix AP4_SampleDescription* orig_sdesc = pdesc->GetOriginalSampleDescription(); unsigned int nalu_length_size = 0; AP4_DataBuffer prefix; if (AP4_FAILED(MakeFramePrefix(orig_sdesc, prefix, nalu_length_size))) { return; } // create the decrypter AP4_SampleDecrypter* decrypter = AP4_SampleDecrypter::Create(pdesc, key, 16); if (decrypter == NULL) { fprintf(stderr, "ERROR: unable to create decrypter\n"); return; } AP4_Sample sample; AP4_DataBuffer encrypted_data; AP4_DataBuffer decrypted_data; AP4_Ordinal index = 0; while (AP4_SUCCEEDED(track->ReadSample(index, sample, encrypted_data))) { if (AP4_FAILED(decrypter->DecryptSampleData(encrypted_data, decrypted_data))) { fprintf(stderr, "ERROR: failed to decrypt sample\n"); return; } WriteSample(decrypted_data, prefix, nalu_length_size, output); index++; } }
void WriteSamples2(s16* rl , u32 sample_count) { for (u32 i=0;i<(sample_count*2);i+=2) WriteSample(rl[i|0],rl[i|1]); }
void WriteSamples1(s16* r , s16* l , u32 sample_count) { for (u32 i=0;i<sample_count;i++) WriteSample(r[i],l[i]); }
GF_Err DoInterleave(MovieWriter *mw, GF_List *writers, GF_BitStream *bs, u8 Emulation, u64 StartOffset, Bool drift_inter) { u32 i, tracksDone; TrackWriter *tmp, *curWriter; GF_Err e; u32 descIndex, sampSize, chunkNumber; u64 DTS; u16 curGroupID; u8 forceNewChunk, writeGroup, isEdited; //this is used to emulate the write ... u64 offset, sampOffset, size, mdatSize; u32 count; GF_ISOFile *movie = mw->movie; mdatSize = 0; #ifdef TEST_LARGE_FILES if (!Emulation) { char *blank; u32 count, i; i = count = 0; blank = gf_malloc(sizeof(char)*1024*1024); memset(blank, 0, sizeof(char)*1024*1024); count = 4096; memset(blank, 0, sizeof(char)*1024*1024); while (i<count) { u32 res = gf_bs_write_data(bs, blank, 1024*1024); if (res != 1024*1024) fprintf(stdout, "error writing to disk: only %d bytes written\n", res); i++; fprintf(stdout, "writing blank block: %.02f done - %d/%d \r", (100.0*i)/count , i, count); } gf_free(blank); } mdatSize = 4096*1024; mdatSize *= 1024; #endif /*write meta content first - WE DON'T support fragmentation of resources in ISOM atm*/ if (movie->meta) { e = DoWriteMeta(movie, movie->meta, bs, Emulation, StartOffset, &size); if (e) return e; mdatSize += size; StartOffset += (u32) size; } if (movie->moov && movie->moov->meta) { e = DoWriteMeta(movie, movie->moov->meta, bs, Emulation, StartOffset, &size); if (e) return e; mdatSize += size; StartOffset += (u32) size; } i=0; while ((tmp = (TrackWriter*)gf_list_enum(writers, &i))) { if (tmp->mdia->mediaTrack->meta) { e = DoWriteMeta(movie, tmp->mdia->mediaTrack->meta, bs, Emulation, StartOffset, &size); if (e) return e; mdatSize += size; StartOffset += (u32) size; } } if (movie->storageMode == GF_ISOM_STORE_TIGHT) return DoFullInterleave(mw, writers, bs, Emulation, StartOffset); e = GF_OK; curGroupID = 1; //we emulate a write from this offset... offset = StartOffset; writeGroup = 1; tracksDone = 0; #ifdef TEST_LARGE_FILES offset += mdatSize; #endif count = gf_list_count(writers); //browse each groups while (1) { /*the max DTS the chunk of the current writer*/ u64 chunkLastDTS = 0; /*the timescale related to the max DTS*/ u32 chunkLastScale = 0; writeGroup = 1; //proceed a group while (writeGroup) { curWriter = NULL; for (i=0 ; i < count; i++) { tmp = (TrackWriter*)gf_list_get(writers, i); //is it done writing ? if (tmp->isDone) continue; //is it in our group ?? if (tmp->mdia->information->sampleTable->groupID != curGroupID) continue; //write till this chunk is full on this track... while (1) { //To Check: are empty sample tables allowed ??? if (tmp->sampleNumber > tmp->mdia->information->sampleTable->SampleSize->sampleCount) { tmp->isDone = 1; tracksDone ++; break; } //OK, get the current sample in this track stbl_GetSampleDTS(tmp->mdia->information->sampleTable->TimeToSample, tmp->sampleNumber, &DTS); //can this sample fit in our chunk ? if ( ( (DTS - tmp->DTSprev) + tmp->chunkDur) * movie->moov->mvhd->timeScale > movie->interleavingTime * tmp->timeScale /*drfit check: reject sample if outside our check window*/ || (drift_inter && chunkLastDTS && ( ((u64)tmp->DTSprev*chunkLastScale) > ((u64)chunkLastDTS*tmp->timeScale)) ) ) { //in case the sample is longer than InterleaveTime if (!tmp->chunkDur) { forceNewChunk = 1; } else { //this one is full. go to next one (exit the loop) tmp->chunkDur = 0; break; } } else { forceNewChunk = tmp->chunkDur ? 0 : 1; } //OK, we can write this track curWriter = tmp; //small check for first 2 samples (DTS = 0 :) if (tmp->sampleNumber == 2 && !tmp->chunkDur) forceNewChunk = 0; tmp->chunkDur += (u32) (DTS - tmp->DTSprev); tmp->DTSprev = DTS; e = stbl_GetSampleInfos(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, &sampOffset, &chunkNumber, &descIndex, &isEdited); if (e) return e; e = stbl_GetSampleSize(curWriter->mdia->information->sampleTable->SampleSize, curWriter->sampleNumber, &sampSize); if (e) return e; //do we actually write, or do we emulate ? if (Emulation) { //update our offsets... if (Media_IsSelfContained(curWriter->mdia, descIndex) ) { e = stbl_SetChunkAndOffset(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, descIndex, curWriter->stsc, &curWriter->stco, offset, forceNewChunk); if (e) return e; offset += sampSize; mdatSize += sampSize; } else { if (curWriter->prev_offset != sampOffset) forceNewChunk = 1; curWriter->prev_offset = sampOffset + sampSize; //we have a DataRef, so use the offset idicated in sampleToChunk //and ChunkOffset tables... e = stbl_SetChunkAndOffset(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, descIndex, curWriter->stsc, &curWriter->stco, sampOffset, forceNewChunk); if (e) return e; } } else { //this is no game, we're writing .... if (Media_IsSelfContained(curWriter->mdia, descIndex) ) { e = WriteSample(mw, sampSize, sampOffset, isEdited, bs); if (e) return e; } } //ok, the sample is done if (curWriter->sampleNumber == curWriter->mdia->information->sampleTable->SampleSize->sampleCount) { curWriter->isDone = 1; //one more track done... tracksDone ++; break; } else { curWriter->sampleNumber ++; } } /*record chunk end-time & track timescale for drift-controled interleaving*/ if (drift_inter && curWriter) { chunkLastScale = curWriter->timeScale; chunkLastDTS = curWriter->DTSprev; /*add one interleave window drift - since the "maxDTS" is the previously written one, we will have the following cases: - sample doesn't fit: post-pone and force new chunk - sample time larger than previous chunk time + interleave: post-pone and force new chunk - otherwise store and track becomes current reference this ensures a proper drift regulation (max DTS diff is less than the interleaving window) */ chunkLastDTS += curWriter->timeScale * movie->interleavingTime / movie->moov->mvhd->timeScale; } } //no sample found, we're done with this group if (!curWriter) { writeGroup = 0; continue; } } //if all our track are done, break if (tracksDone == gf_list_count(writers)) break; //go to next group curGroupID ++; } if (movie->mdat) movie->mdat->dataSize = mdatSize; return GF_OK; }
GF_Err DoFullInterleave(MovieWriter *mw, GF_List *writers, GF_BitStream *bs, u8 Emulation, u64 StartOffset) { u32 i, tracksDone; TrackWriter *tmp, *curWriter, *prevWriter; GF_Err e; u64 DTS, DTStmp, TStmp; s64 res; u32 descIndex, sampSize, chunkNumber; u16 curGroupID, curTrackPriority; u8 forceNewChunk, writeGroup, isEdited; //this is used to emulate the write ... u64 offset, totSize, sampOffset; GF_ISOFile *movie = mw->movie; e = GF_OK; totSize = 0; curGroupID = 1; prevWriter = NULL; //we emulate a write from this offset... offset = StartOffset; writeGroup = 1; tracksDone = 0; //browse each groups while (1) { writeGroup = 1; //proceed a group while (writeGroup) { //first get the appropriated sample for the min time in this group curWriter = NULL; DTStmp = (u64) -1; TStmp = 0; curTrackPriority = (u16) -1; i=0; while ((tmp = (TrackWriter*)gf_list_enum(writers, &i))) { //is it done writing ? //is it in our group ?? if (tmp->isDone || tmp->mdia->information->sampleTable->groupID != curGroupID) continue; //OK, get the current sample in this track stbl_GetSampleDTS(tmp->mdia->information->sampleTable->TimeToSample, tmp->sampleNumber, &DTS); res = TStmp ? DTStmp * tmp->timeScale - DTS * TStmp : 0; if (res < 0) continue; if ((!res) && curTrackPriority <= tmp->mdia->information->sampleTable->trackPriority) continue; curWriter = tmp; curTrackPriority = tmp->mdia->information->sampleTable->trackPriority; DTStmp = DTS; TStmp = tmp->timeScale; } //no sample found, we're done with this group if (!curWriter) { //we're done with the group curTrackPriority = 0; writeGroup = 0; continue; } //To Check: are empty sample tables allowed ??? if (curWriter->sampleNumber > curWriter->mdia->information->sampleTable->SampleSize->sampleCount) { curWriter->isDone = 1; tracksDone ++; continue; } e = stbl_GetSampleInfos(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, &sampOffset, &chunkNumber, &descIndex, &isEdited); if (e) return e; e = stbl_GetSampleSize(curWriter->mdia->information->sampleTable->SampleSize, curWriter->sampleNumber, &sampSize); if (e) return e; //do we actually write, or do we emulate ? if (Emulation) { //are we in the same track ??? If not, force a new chunk when adding this sample if (curWriter != prevWriter) { forceNewChunk = 1; } else { forceNewChunk = 0; } //update our offsets... if (Media_IsSelfContained(curWriter->mdia, descIndex) ) { e = stbl_SetChunkAndOffset(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, descIndex, curWriter->stsc, &curWriter->stco, offset, forceNewChunk); if (e) return e; offset += sampSize; totSize += sampSize; } else { if (curWriter->prev_offset != sampOffset) forceNewChunk = 1; curWriter->prev_offset = sampOffset + sampSize; //we have a DataRef, so use the offset idicated in sampleToChunk //and ChunkOffset tables... e = stbl_SetChunkAndOffset(curWriter->mdia->information->sampleTable, curWriter->sampleNumber, descIndex, curWriter->stsc, &curWriter->stco, sampOffset, 0); if (e) return e; } } else { //this is no game, we're writing .... if (Media_IsSelfContained(curWriter->mdia, descIndex) ) { e = WriteSample(mw, sampSize, sampOffset, isEdited, bs); if (e) return e; } } //ok, the sample is done if (curWriter->sampleNumber == curWriter->mdia->information->sampleTable->SampleSize->sampleCount) { curWriter->isDone = 1; //one more track done... tracksDone ++; } else { curWriter->sampleNumber ++; } prevWriter = curWriter; } //if all our track are done, break if (tracksDone == gf_list_count(writers)) break; //go to next group curGroupID ++; } movie->mdat->dataSize = totSize; return GF_OK; }
//this function writes track by track in the order of tracks inside the moov... GF_Err DoWrite(MovieWriter *mw, GF_List *writers, GF_BitStream *bs, u8 Emulation, u64 StartOffset) { u32 i; GF_Err e; TrackWriter *writer; u64 offset, sampOffset, predOffset; u32 chunkNumber, descIndex, sampSize; u8 isEdited, force; u64 size, mdatSize = 0; GF_ISOFile *movie = mw->movie; /*write meta content first - WE DON'T support fragmentation of resources in ISOM atm*/ if (movie->openMode != GF_ISOM_OPEN_WRITE) { if (movie->meta) { e = DoWriteMeta(movie, movie->meta, bs, Emulation, StartOffset, &size); if (e) return e; mdatSize += size; StartOffset += size; } if (movie->moov && movie->moov->meta) { e = DoWriteMeta(movie, movie->meta, bs, Emulation, StartOffset, &size); if (e) return e; mdatSize += size; StartOffset += size; } i=0; while ((writer = (TrackWriter*)gf_list_enum(writers, &i))) { if (writer->mdia->mediaTrack->meta) { e = DoWriteMeta(movie, movie->meta, bs, Emulation, StartOffset, &size); if (e) return e; mdatSize += size; StartOffset += size; } } } offset = StartOffset; predOffset = 0; i=0; while ((writer = (TrackWriter*)gf_list_enum(writers, &i))) { while (!writer->isDone) { //To Check: are empty sample tables allowed ??? if (writer->sampleNumber > writer->mdia->information->sampleTable->SampleSize->sampleCount) { writer->isDone = 1; continue; } e = stbl_GetSampleInfos(writer->mdia->information->sampleTable, writer->sampleNumber, &sampOffset, &chunkNumber, &descIndex, &isEdited); if (e) return e; e = stbl_GetSampleSize(writer->mdia->information->sampleTable->SampleSize, writer->sampleNumber, &sampSize); if (e) return e; //update our chunks. force = 0; if (movie->openMode == GF_ISOM_OPEN_WRITE) { offset = sampOffset; if (predOffset != offset) force = 1; } //update our global offset... if (Media_IsSelfContained(writer->mdia, descIndex) ) { e = stbl_SetChunkAndOffset(writer->mdia->information->sampleTable, writer->sampleNumber, descIndex, writer->stsc, &writer->stco, offset, force); if (e) return e; if (movie->openMode == GF_ISOM_OPEN_WRITE) { predOffset = sampOffset + sampSize; } else { offset += sampSize; mdatSize += sampSize; } } else { if (predOffset != offset) force = 1; predOffset = sampOffset + sampSize; //we have a DataRef, so use the offset idicated in sampleToChunk and ChunkOffset tables... e = stbl_SetChunkAndOffset(writer->mdia->information->sampleTable, writer->sampleNumber, descIndex, writer->stsc, &writer->stco, sampOffset, force); if (e) return e; } //we write the sample if not emulation if (!Emulation) { if (Media_IsSelfContained(writer->mdia, descIndex) ) { e = WriteSample(mw, sampSize, sampOffset, isEdited, bs); if (e) return e; } } //ok, the track is done if (writer->sampleNumber == writer->mdia->information->sampleTable->SampleSize->sampleCount) { writer->isDone = 1; } else { writer->sampleNumber ++; } } } //set the mdatSize... movie->mdat->dataSize = mdatSize; return GF_OK; }
bool module_renderer::SaveITProject(LPCSTR lpszFileName) //------------------------------------------------- { // Check song type if(!(m_dwSongFlags & SONG_ITPROJECT)) return false; UINT i,j = 0; for(i = 0 ; i < m_nInstruments ; i++) { if(m_szInstrumentPath[i][0] != '\0' || !Instruments[i+1]) j++; } if(m_nInstruments && j != m_nInstruments) return false; // Open file FILE *f; if((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return false; // File ID uint32_t id = ITP_FILE_ID; fwrite(&id, 1, sizeof(id), f); id = ITP_VERSION; fwrite(&id, 1, sizeof(id), f); // Song name // name string length id = 27; fwrite(&id, 1, sizeof(id), f); // song name char namebuf[27]; copy_with_padding(namebuf, 27, this->song_name); fwrite(namebuf, 1, 27, f); // Song comments // comment string length id = m_lpszSongComments ? strlen(m_lpszSongComments)+1 : 0; fwrite(&id, 1, sizeof(id), f); // comment string if(m_lpszSongComments) fwrite(&m_lpszSongComments[0], 1, strlen(m_lpszSongComments)+1, f); // Song global config id = (m_dwSongFlags & SONG_FILE_FLAGS); fwrite(&id, 1, sizeof(id), f); id = m_nDefaultGlobalVolume; fwrite(&id, 1, sizeof(id), f); id = m_nSamplePreAmp; fwrite(&id, 1, sizeof(id), f); id = m_nDefaultSpeed; fwrite(&id, 1, sizeof(id), f); id = m_nDefaultTempo; fwrite(&id, 1, sizeof(id), f); // Song channels data // number of channels id = m_nChannels; fwrite(&id, 1, sizeof(id), f); // channel name string length id = MAX_CHANNELNAME; fwrite(&id, 1, sizeof(id), f); // channel config data for(i=0; i<m_nChannels; i++){ id = ChnSettings[i].nPan; fwrite(&id, 1, sizeof(id), f); id = ChnSettings[i].dwFlags; fwrite(&id, 1, sizeof(id), f); id = ChnSettings[i].nVolume; fwrite(&id, 1, sizeof(id), f); fwrite(&ChnSettings[i].szName[0], 1, MAX_CHANNELNAME, f); } // Song mix plugins // mix plugins data length id = SaveMixPlugins(NULL, TRUE); fwrite(&id, 1, sizeof(id), f); // mix plugins data SaveMixPlugins(f, FALSE); // Song midi config // midi cfg data length id = sizeof(MODMIDICFG); fwrite(&id, 1, sizeof(id), f); // midi cfg fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); // Song Instruments // number of instruments id = m_nInstruments; fwrite(&id, 1, sizeof(id), f); // path name string length id = _MAX_PATH; fwrite(&id, 1, sizeof(id), f); // instruments' path for(i=0; i<m_nInstruments; i++) fwrite(&m_szInstrumentPath[i][0], 1, _MAX_PATH, f); // Song Orders // order array size id = Order.size(); fwrite(&id, 1, sizeof(id), f); // order array Order.WriteAsByte(f, id); // Song Patterns // number of patterns id = MAX_PATTERNS; fwrite(&id, 1, sizeof(id), f); // number of pattern name strings modplug::tracker::patternindex_t numNamedPats = Patterns.GetNumNamedPatterns(); numNamedPats = bad_min(numNamedPats, MAX_PATTERNS); id = numNamedPats; fwrite(&id, 1, sizeof(id), f); // length of a pattern name string id = MAX_PATTERNNAME; fwrite(&id, 1, sizeof(id), f); // pattern name string for(modplug::tracker::patternindex_t nPat = 0; nPat < numNamedPats; nPat++) { char name[MAX_PATTERNNAME]; MemsetZero(name); Patterns[nPat].GetName(name, MAX_PATTERNNAME); fwrite(name, 1, MAX_PATTERNNAME, f); } // modcommand data length id = sizeof(modplug::tracker::modevent_t); fwrite(&id, 1, sizeof(id), f); // patterns data content for(UINT npat=0; npat<MAX_PATTERNS; npat++){ // pattern size (number of rows) id = Patterns[npat] ? Patterns[npat].GetNumRows() : 0; fwrite(&id, 1, sizeof(id), f); // pattern data if(Patterns[npat] && Patterns[npat].GetNumRows()) Patterns[npat].WriteITPdata(f); //fwrite(Patterns[npat], 1, m_nChannels * Patterns[npat].GetNumRows() * sizeof(modplug::tracker::modcommand_t), f); } // Song lonely (instrument-less) samples // Write original number of samples id = m_nSamples; fwrite(&id, 1, sizeof(id), f); vector<bool> sampleUsed(m_nSamples, false); // Mark samples used in instruments for(i=0; i<m_nInstruments; i++) { if(Instruments[i + 1] != nullptr) { modinstrument_t *p = Instruments[i + 1]; for(j = 0; j < 128; j++) { if(p->Keyboard[j] > 0 && p->Keyboard[j] <= m_nSamples) sampleUsed[p->Keyboard[j] - 1] = true; } } } // Count samples not used in any instrument i = 0; for(j = 1; j <= m_nSamples; j++) if(!sampleUsed[j - 1] && Samples[j].sample_data) i++; id = i; fwrite(&id, 1, sizeof(id), f); // Write samples not used in any instrument (help, this looks like duplicate code!) ITSAMPLESTRUCT itss; for(UINT nsmp=1; nsmp<=m_nSamples; nsmp++) { if(!sampleUsed[nsmp - 1] && Samples[nsmp].sample_data) { modsample_t *psmp = &Samples[nsmp]; memset(&itss, 0, sizeof(itss)); memcpy(itss.filename, psmp->legacy_filename, 12); memcpy(itss.name, m_szNames[nsmp], 26); itss.id = LittleEndian(IT_IMPS); itss.gvl = (uint8_t)psmp->global_volume; itss.flags = 0x00; if(psmp->flags & CHN_LOOP) itss.flags |= 0x10; if(psmp->flags & CHN_SUSTAINLOOP) itss.flags |= 0x20; if(psmp->flags & CHN_PINGPONGLOOP) itss.flags |= 0x40; if(psmp->flags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80; itss.C5Speed = psmp->c5_samplerate; if (!itss.C5Speed) itss.C5Speed = 8363; itss.length = psmp->length; itss.loopbegin = psmp->loop_start; itss.loopend = psmp->loop_end; itss.susloopbegin = psmp->sustain_start; itss.susloopend = psmp->sustain_end; itss.vol = (uint8_t)(psmp->default_volume >> 2); itss.dfp = (uint8_t)(psmp->default_pan >> 2); itss.vit = autovibxm2it[psmp->vibrato_type & 7]; itss.vis = bad_min(psmp->vibrato_rate, 64); itss.vid = bad_min(psmp->vibrato_depth, 32); itss.vir = bad_min(psmp->vibrato_sweep, 255); //(psmp->vibrato_sweep < 64) ? psmp->vibrato_sweep * 4 : 255; if (psmp->flags & CHN_PANNING) itss.dfp |= 0x80; if ((psmp->sample_data) && (psmp->length)) itss.cvt = 0x01; UINT flags = RS_PCM8S; if(psmp->flags & CHN_STEREO) { flags = RS_STPCM8S; itss.flags |= 0x04; } if(psmp->flags & CHN_16BIT) { itss.flags |= 0x02; flags = (psmp->flags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S; } id = nsmp; fwrite(&id, 1, sizeof(id), f); itss.samplepointer = NULL; fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f); id = WriteSample(NULL, psmp, flags); fwrite(&id, 1, sizeof(id), f); WriteSample(f, psmp, flags); } }
void MP4File::MakeIsmaCompliant(bool addIsmaComplianceSdp) { ProtectWriteOperation("MP4MakeIsmaCompliant"); if (m_useIsma) { // already done return; } m_useIsma = true; // find first audio and/or video tracks MP4TrackId audioTrackId = MP4_INVALID_TRACK_ID; try { audioTrackId = FindTrackId(0, MP4_AUDIO_TRACK_TYPE); } catch (MP4Error* e) { delete e; } MP4TrackId videoTrackId = MP4_INVALID_TRACK_ID; try { videoTrackId = FindTrackId(0, MP4_VIDEO_TRACK_TYPE); } catch (MP4Error* e) { delete e; } u_int64_t fileMsDuration = ConvertFromMovieDuration(GetDuration(), MP4_MSECS_TIME_SCALE); // delete any existing OD track if (m_odTrackId != MP4_INVALID_TRACK_ID) { DeleteTrack(m_odTrackId); } AddODTrack(); SetODProfileLevel(0xFF); if (audioTrackId != MP4_INVALID_TRACK_ID) { AddTrackToOd(audioTrackId); } if (videoTrackId != MP4_INVALID_TRACK_ID) { AddTrackToOd(videoTrackId); } // delete any existing scene track MP4TrackId sceneTrackId = MP4_INVALID_TRACK_ID; try { sceneTrackId = FindTrackId(0, MP4_SCENE_TRACK_TYPE); } catch (MP4Error *e) { delete e; } if (sceneTrackId != MP4_INVALID_TRACK_ID) { DeleteTrack(sceneTrackId); } // add scene track sceneTrackId = AddSceneTrack(); SetSceneProfileLevel(0xFF); SetGraphicsProfileLevel(0xFF); SetTrackIntegerProperty(sceneTrackId, "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.objectTypeId", MP4SystemsV2ObjectType); SetTrackESConfiguration(sceneTrackId, BifsV2Config, sizeof(BifsV2Config)); u_int8_t* pBytes = NULL; u_int64_t numBytes = 0; // write OD Update Command CreateIsmaODUpdateCommandFromFileForFile( m_odTrackId, audioTrackId, videoTrackId, &pBytes, &numBytes); WriteSample(m_odTrackId, pBytes, numBytes, fileMsDuration); MP4Free(pBytes); pBytes = NULL; // write BIFS Scene Replace Command CreateIsmaSceneCommand( MP4_IS_VALID_TRACK_ID(audioTrackId), MP4_IS_VALID_TRACK_ID(videoTrackId), &pBytes, &numBytes); WriteSample(sceneTrackId, pBytes, numBytes, fileMsDuration); MP4Free(pBytes); pBytes = NULL; // add session level sdp CreateIsmaIodFromFile( m_odTrackId, sceneTrackId, audioTrackId, videoTrackId, &pBytes, &numBytes); char* iodBase64 = MP4ToBase64(pBytes, numBytes); char* sdpBuf = (char*)MP4Calloc(strlen(iodBase64) + 256); if (addIsmaComplianceSdp) { strcpy(sdpBuf, "a=isma-compliance:1,1.0,1\015\012"); } sprintf(&sdpBuf[strlen(sdpBuf)], "a=mpeg4-iod: \042data:application/mpeg4-iod;base64,%s\042\015\012", iodBase64); SetSessionSdp(sdpBuf); VERBOSE_ISMA(GetVerbosity(), printf("IOD SDP = %s\n", sdpBuf)); MP4Free(iodBase64); iodBase64 = NULL; MP4Free(pBytes); pBytes = NULL; MP4Free(sdpBuf); sdpBuf = NULL; }