Permalink
Browse files

Distrust all packet durations in flv, parse headers a bit more

Seems to help with audio sync in flv

git-svn-id: https://svn.perian.org/trunk@1538 621663c8-3916-0410-8f58-edc14a8543d5
  • Loading branch information...
astrange
astrange committed Jan 23, 2013
1 parent 720494c commit 97f93eb6fd493ff6370df5c7090c95ad865703c4
Showing with 47 additions and 21 deletions.
  1. +19 −1 ff_MovieImport.c
  2. +26 −16 ff_private.c
  3. +2 −4 ff_private.h
@@ -453,12 +453,22 @@ ComponentResult FFAvi_MovieImportDataRef(ff_global_ptr storage, Handle dataRef,
*outFlags |= movieImportResultUsedMultipleTracks;
/* The usedTrack parameter. Count the number of Tracks and set usedTrack if we operated
* on a single track. Note that this requires the media to be set by track counting above*/
* on a single track. Note that this requires the media to be set by track counting above */
if(usedTrack && count == 1 && media)
*usedTrack = GetMediaTrack(media);
*addedDuration = 0;
// Force libavformat to not parse apart frames. QT needs position/size info instead of importing from memory.
// This means we need decoder side support for anything that needs to be parsed.
for(j = 0; j < storage->map_count; j++) {
NCStream *ncstream = &storage->stream_map[j];
if (ncstream->str->need_parsing != AVSTREAM_PARSE_NONE) {
ncstream->str->need_parsing = AVSTREAM_PARSE_HEADERS;
}
}
//attempt to import using indexes.
result = import_using_index(storage, &hadIndex, addedDuration);
require_noerr(result, bail);
@@ -504,6 +514,10 @@ ComponentResult FFAvi_MovieImportDataRef(ff_global_ptr storage, Handle dataRef,
if (ic)
avformat_free_context(ic);
if (result != noErr) {
Codecprintf(NULL, "ImportDataRef err %ld\n", result);
}
return result;
} /* FFAvi_MovieImportDataRef */
@@ -530,6 +544,10 @@ ComponentResult FFAvi_MovieImportIdle(ff_global_ptr storage, long inFlags, long
err = import_with_idle(storage, inFlags | movieImportWithIdle, outFlags, 0, 1000, addSamples);
storage->lastIdleTime = currentIdleTime;
if (err != noErr) {
Codecprintf(NULL, "ImportIdle err %ld\n", err);
}
return err;
}
@@ -924,22 +924,18 @@ ComponentResult import_with_idle(ff_global_ptr storage, long inFlags, long *outF
}
}
for(i = 0; i < storage->map_count; i++)
firstPts[i] = -1;
// record stream durations before we add any samples so that we know what to tell InsertMediaIntoTrack later
// also, tell ffmpeg that we don't want them parsing because their parsers screw up the position/size data!!!
for(i = 0; i < storage->map_count; i++) {
ncstream = &storage->stream_map[i];
Media media = ncstream->media;
firstPts[i] = -1;
if(media && ncstream->duration == -1)
ncstream->duration = GetMediaDuration(media);
ncstream->str->need_parsing = AVSTREAM_PARSE_NONE;
}
while((readResult = av_read_frame(formatContext, &packet)) == 0) {
while((readResult = av_read_frame(formatContext, &packet)) == 0) {
bool trustPacketDuration = true;
int64_t dts = packet.dts;
ncstream = &storage->stream_map[packet.stream_index];
stream = ncstream->str;
codecContext = stream->codec;
@@ -952,15 +948,17 @@ ComponentResult import_with_idle(ff_global_ptr storage, long inFlags, long *outF
flags |= mediaSampleNotSync;
if(IS_NUV(storage->componentType) && codecContext->codec_id == CODEC_ID_MP3) trustPacketDuration = false;
if(IS_FLV(storage->componentType) && codecContext->codec_id == CODEC_ID_H264) trustPacketDuration = false;
if(IS_FLV(storage->componentType) && codecContext->codec_type == AVMEDIA_TYPE_AUDIO) trustPacketDuration = false;
if(IS_FLV(storage->componentType)) trustPacketDuration = false;
memset(&sampleRec, 0, sizeof(sampleRec));
sampleRec.dataOffset.hi = packet.pos >> 32;
sampleRec.dataOffset.lo = (uint32_t)packet.pos;
sampleRec.dataSize = packet.size;
sampleRec.sampleFlags = flags;
if (packet.pos <= 0)
continue;
if(firstPts[packet.stream_index] < 0)
firstPts[packet.stream_index] = packet.pts;
@@ -978,22 +976,34 @@ ComponentResult import_with_idle(ff_global_ptr storage, long inFlags, long *outF
//add any samples waiting to be added
if(ncstream->lastSample.numberOfSamples > 0) {
//calculate the duration of the sample before adding it
ncstream->lastSample.durationPerSample = (packet.dts - ncstream->lastdts) * ncstream->base.num;
ncstream->lastSample.durationPerSample = (dts - ncstream->lastdts) * ncstream->base.num;
AddMediaSampleReferences64(ncstream->media, ncstream->sampleHdl, 1, &ncstream->lastSample, NULL);
}
#if 0
if (0) {
Codecprintf(NULL, "Stream:%d Pts:%lld Dts:%lld DtsUsed:%lld Pos:%lld Size:%d\n", packet.stream_index, packet.pts, packet.dts, dts, packet.pos, packet.size);
Codecprintf(NULL, "Stream:%d Nsamples:%ld RealDuration:%d CalcDuration:%ld TimeDts:%lld TimeDurations:%lld FrameDts:%d FrameGuess:%lld\n",
packet.stream_index, sampleRec.numberOfSamples, packet.duration, ncstream->lastSample.durationPerSample,
packet.dts, ncstream->timeByDurations, (int)((packet.dts * stream->time_base.num * ncstream->asbd.mSampleRate) / stream->time_base.den),
ncstream->timeByFrames);
ncstream->timeByDurations += packet.duration;
ncstream->timeByFrames += ncstream->asbd.mFramesPerPacket;
}
#endif
ncstream->lastSample = sampleRec;
ncstream->lastdts = packet.dts;
// If this is a nuv file, then we want to set the duration to zero.
// This is because the nuv container doesn't have the framesize info
// for audio.
// for audio.
if(packet.duration == 0 || !trustPacketDuration) {
//no duration, we'll have to wait for the next packet to calculate it
// keep the duration of the last sample, so we can use it if it's the last frame
sampleRec.durationPerSample = ncstream->lastSample.durationPerSample;
ncstream->lastSample = sampleRec;
ncstream->lastdts = packet.dts;
} else {
ncstream->lastSample.numberOfSamples = 0;
@@ -40,6 +40,8 @@ struct _NCStream {
SampleReference64Ptr sampleTable;
SampleReference64Record lastSample;
TimeValue duration;
int64_t timeByDurations, timeByFrames;
};
typedef struct _NCStream NCStream;
@@ -112,10 +114,6 @@ Handle create_strf_ext(AVCodecContext *codec);
void set_track_clean_aperture_ext(ImageDescriptionHandle imgDesc, Fixed displayW, Fixed displayH, Fixed pixelW, Fixed pixelH);
void set_track_colorspace_ext(ImageDescriptionHandle imgDescHandle, Fixed displayW, Fixed displayH);
uint8_t *write_int32(uint8_t *target, int32_t data);
uint8_t *write_int16(uint8_t *target, int16_t data);
uint8_t *write_data(uint8_t *target, uint8_t* data, int32_t data_size);
#define BSWAP(a) ( (((a)&0xff) << 24) | (((a)&0xff00) << 8) | (((a)&0xff0000) >> 8) | (((a) >> 24) & 0xff) )
#define IS_AVI(x) (x == 'AVI ' || x == 'VfW ' || x == 'VFW ' || x == 'DIVX' || x == 'GVI ' || x == 'VP6 ')

0 comments on commit 97f93eb

Please sign in to comment.