Mercurial > libavformat.hg
changeset 4941:45a08facad6f libavformat
write 'stps' for mpeg-2 open gop in .mov
author | bcoudurier |
---|---|
date | Fri, 15 May 2009 06:11:53 +0000 |
parents | 9bc9feb36557 |
children | 02e9151a011e |
files | movenc.c |
diffstat | 1 files changed, 44 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/movenc.c Fri May 15 05:33:05 2009 +0000 +++ b/movenc.c Fri May 15 06:11:53 2009 +0000 @@ -51,6 +51,7 @@ int cts; int64_t dts; #define MOV_SYNC_SAMPLE 0x0001 +#define MOV_PARTIAL_SYNC_SAMPLE 0x0002 uint32_t flags; } MOVIentry; @@ -63,7 +64,9 @@ long sampleCount; long sampleSize; int hasKeyframes; - int hasBframes; +#define MOV_TRACK_CTTS 0x0001 +#define MOV_TRACK_STPS 0x0002 + uint32_t flags; int language; int trackID; int tag; ///< stsd fourcc @@ -188,18 +191,18 @@ } /* Sync sample atom */ -static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack *track) +static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack *track, uint32_t flag) { int64_t curpos, entryPos; int i, index = 0; int64_t pos = url_ftell(pb); put_be32(pb, 0); // size - put_tag(pb, "stss"); + put_tag(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps"); put_be32(pb, 0); // version & flags entryPos = url_ftell(pb); put_be32(pb, track->entry); // entry count for (i=0; i<track->entry; i++) { - if (track->cluster[i].flags & MOV_SYNC_SAMPLE) { + if (track->cluster[i].flags & flag) { put_be32(pb, i+1); index++; } @@ -914,9 +917,11 @@ mov_write_stts_tag(pb, track); if (track->enc->codec_type == CODEC_TYPE_VIDEO && track->hasKeyframes && track->hasKeyframes < track->entry) - mov_write_stss_tag(pb, track); + mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); + if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS) + mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE); if (track->enc->codec_type == CODEC_TYPE_VIDEO && - track->hasBframes) + track->flags & MOV_TRACK_CTTS) mov_write_ctts_tag(pb, track); mov_write_stsc_tag(pb, track); mov_write_stsz_tag(pb, track); @@ -1173,7 +1178,7 @@ put_be32(pb, 0); /* size */ put_tag(pb, "trak"); mov_write_tkhd_tag(pb, track, st); - if (track->mode == MODE_PSP || track->hasBframes) + if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS) mov_write_edts_tag(pb, track); // PSP Movies require edts box mov_write_mdia_tag(pb, track); if (track->mode == MODE_PSP) @@ -1802,6 +1807,27 @@ return -1; } +static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags) +{ + uint32_t c = -1; + int i, closed_gop = 0; + + for (i = 0; i < pkt->size - 4; i++) { + c = (c<<8) + pkt->data[i]; + if (c == 0x1b8) { // gop + closed_gop = pkt->data[i+4]>>6 & 0x01; + } else if (c == 0x100) { // pic + int temp_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6); + if (!temp_ref || closed_gop) // I picture is not reordered + *flags = MOV_SYNC_SAMPLE; + else + *flags = MOV_PARTIAL_SYNC_SAMPLE; + break; + } + } + return 0; +} + static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) { MOVMuxContext *mov = s->priv_data; @@ -1876,11 +1902,19 @@ pkt->pts = pkt->dts; } if (pkt->dts != pkt->pts) - trk->hasBframes = 1; + trk->flags |= MOV_TRACK_CTTS; trk->cluster[trk->entry].cts = pkt->pts - pkt->dts; + trk->cluster[trk->entry].flags = 0; if (pkt->flags & PKT_FLAG_KEY) { - trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE; - trk->hasKeyframes++; + if (mov->mode == MODE_MOV && enc->codec_id == CODEC_ID_MPEG2VIDEO) { + mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags); + if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE) + trk->flags |= MOV_TRACK_STPS; + } else { + trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE; + } + if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE) + trk->hasKeyframes++; } trk->entry++; trk->sampleCount += samplesInChunk;