Ticket #2573: xdcam.patch

File xdcam.patch, 4.2 KB (added by rmk, 13 years ago)

Hack that fixes the behaviour for this case

  • libavformat/movenc.c

    diff --git a/libavformat/movenc.c b/libavformat/movenc.c
    index 3296762..165da39 100644
    a b static int mov_write_stsd_tag(AVIOContext *pb, MOVTrack *track)  
    13161316    return update_size(pb, pos);
    13171317}
    13181318
     1319static int compute_track_delay(MOVTrack *track) {
     1320    int i;
     1321    int64_t first_pts, key_frame_pts;
     1322    MOVIentry *key_frame = NULL;
     1323
     1324    // search for the first keyframe within this track
     1325    for (i = 0; i < track->entry; i++) {
     1326        if (track->cluster[i].flags & (MOV_SYNC_SAMPLE|MOV_PARTIAL_SYNC_SAMPLE)) {
     1327            key_frame = &track->cluster[i];
     1328            break;
     1329        }
     1330    }
     1331    if (!key_frame) {
     1332        // no keyframe found
     1333        return 0;
     1334    }
     1335
     1336    // check if after this first keyframe are entries with 'earlier' pts,
     1337    // which means entries are reordered
     1338    // we assume entries to be in decoding order
     1339    first_pts = key_frame_pts = key_frame->dts + key_frame->cts;
     1340    for (i++; i < track->entry; i++) {
     1341        int64_t pts = track->cluster[i].dts + track->cluster[i].cts;
     1342        if (pts >= key_frame_pts)
     1343            break;
     1344        first_pts = FFMIN(pts, first_pts);
     1345    }
     1346    // diff between pts of the first shown frame and the dts of the first decoded
     1347    // frame (which is not necessarily equal to 0) is the delay of this track
     1348    return first_pts - key_frame->dts;
     1349}
     1350
     1351
    13191352static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track)
    13201353{
    13211354    MOVStts *ctts_entries;
    13221355    uint32_t entries = 0;
    13231356    uint32_t atom_size;
    1324     int i;
     1357    int i, track_delay = 0;
     1358
     1359    if(track->mode == MODE_MOV)
     1360        track_delay = compute_track_delay(track);
    13251361
    13261362    ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */
    13271363    ctts_entries[0].count = 1;
    static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track)  
    13431379    avio_wb32(pb, entries); /* entry count */
    13441380    for (i = 0; i < entries; i++) {
    13451381        avio_wb32(pb, ctts_entries[i].count);
    1346         avio_wb32(pb, ctts_entries[i].duration);
     1382        avio_wb32(pb, ctts_entries[i].duration - track_delay);
    13471383    }
    13481384    av_free(ctts_entries);
    13491385    return atom_size;
    static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track)  
    18101846    int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE,
    18111847                                      track->timescale, AV_ROUND_UP);
    18121848    int version = duration < INT32_MAX ? 0 : 1;
    1813     int entry_size, entry_count, size;
     1849    int entry_size, entry_count, size, idx = 0;
    18141850    int64_t delay, start_ct = track->cluster[0].cts;
    1815     delay = av_rescale_rnd(track->cluster[0].dts + start_ct, MOV_TIMESCALE,
     1851
     1852    // compute delay, which is the pts of the first shown frame (not necessarily 0)
     1853    // as frames might be reordered, we have to iterate
     1854    delay = track->cluster[0].dts + track->cluster[0].cts;
     1855    for(int i = 1; i < track->entry; i++) {
     1856        int64_t pts = track->cluster[i].dts + track->cluster[i].cts;
     1857        if(pts >= track->cluster[0].dts + track->cluster[0].cts)
     1858            break;
     1859        if(pts < delay) {
     1860            delay = pts;
     1861            start_ct = pts;
     1862            idx = i;
     1863        }
     1864    }
     1865
     1866    delay = av_rescale_rnd(delay, MOV_TIMESCALE,
    18161867                           track->timescale, AV_ROUND_DOWN);
    18171868    version |= delay < INT32_MAX ? 0 : 1;
    18181869
    static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track)  
    18291880    avio_wb24(pb, 0); /* flags */
    18301881
    18311882    avio_wb32(pb, entry_count);
     1883
    18321884    if (delay > 0) { /* add an empty edit to delay presentation */
    18331885        if (version == 1) {
    18341886            avio_wb64(pb, delay);
    static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track)  
    18391891        }
    18401892        avio_wb32(pb, 0x00010000);
    18411893    } else {
    1842         av_assert0(av_rescale_rnd(track->cluster[0].dts, MOV_TIMESCALE, track->timescale, AV_ROUND_DOWN) <= 0);
    1843         start_ct  = -FFMIN(track->cluster[0].dts, 0); //FFMIN needed due to rounding
     1894        av_assert0(av_rescale_rnd(track->cluster[idx].dts + track->cluster[idx].cts, MOV_TIMESCALE, track->timescale, AV_ROUND_DOWN) <= 0);
     1895        start_ct  = -FFMIN(track->cluster[idx].dts + track->cluster[idx].cts, 0); //FFMIN needed due to rounding
    18441896        duration += delay;
    18451897    }
    18461898