Commit e1316b19 authored by Baptiste Coudurier's avatar Baptiste Coudurier

write 'stps' for mpeg-2 open gop in .mov

Originally committed as revision 18838 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 9d9a6239
...@@ -51,6 +51,7 @@ typedef struct MOVIentry { ...@@ -51,6 +51,7 @@ typedef struct MOVIentry {
int cts; int cts;
int64_t dts; int64_t dts;
#define MOV_SYNC_SAMPLE 0x0001 #define MOV_SYNC_SAMPLE 0x0001
#define MOV_PARTIAL_SYNC_SAMPLE 0x0002
uint32_t flags; uint32_t flags;
} MOVIentry; } MOVIentry;
...@@ -63,7 +64,9 @@ typedef struct MOVIndex { ...@@ -63,7 +64,9 @@ typedef struct MOVIndex {
long sampleCount; long sampleCount;
long sampleSize; long sampleSize;
int hasKeyframes; int hasKeyframes;
int hasBframes; #define MOV_TRACK_CTTS 0x0001
#define MOV_TRACK_STPS 0x0002
uint32_t flags;
int language; int language;
int trackID; int trackID;
int tag; ///< stsd fourcc int tag; ///< stsd fourcc
...@@ -188,18 +191,18 @@ static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack *track) ...@@ -188,18 +191,18 @@ static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack *track)
} }
/* Sync sample atom */ /* 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; int64_t curpos, entryPos;
int i, index = 0; int i, index = 0;
int64_t pos = url_ftell(pb); int64_t pos = url_ftell(pb);
put_be32(pb, 0); // size put_be32(pb, 0); // size
put_tag(pb, "stss"); put_tag(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps");
put_be32(pb, 0); // version & flags put_be32(pb, 0); // version & flags
entryPos = url_ftell(pb); entryPos = url_ftell(pb);
put_be32(pb, track->entry); // entry count put_be32(pb, track->entry); // entry count
for (i=0; i<track->entry; i++) { 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); put_be32(pb, i+1);
index++; index++;
} }
...@@ -914,9 +917,11 @@ static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack *track) ...@@ -914,9 +917,11 @@ static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack *track)
mov_write_stts_tag(pb, track); mov_write_stts_tag(pb, track);
if (track->enc->codec_type == CODEC_TYPE_VIDEO && if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
track->hasKeyframes && track->hasKeyframes < track->entry) 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 && if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
track->hasBframes) track->flags & MOV_TRACK_CTTS)
mov_write_ctts_tag(pb, track); mov_write_ctts_tag(pb, track);
mov_write_stsc_tag(pb, track); mov_write_stsc_tag(pb, track);
mov_write_stsz_tag(pb, track); mov_write_stsz_tag(pb, track);
...@@ -1173,7 +1178,7 @@ static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st) ...@@ -1173,7 +1178,7 @@ static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st)
put_be32(pb, 0); /* size */ put_be32(pb, 0); /* size */
put_tag(pb, "trak"); put_tag(pb, "trak");
mov_write_tkhd_tag(pb, track, st); 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_edts_tag(pb, track); // PSP Movies require edts box
mov_write_mdia_tag(pb, track); mov_write_mdia_tag(pb, track);
if (track->mode == MODE_PSP) if (track->mode == MODE_PSP)
...@@ -1802,6 +1807,27 @@ static int mov_write_header(AVFormatContext *s) ...@@ -1802,6 +1807,27 @@ static int mov_write_header(AVFormatContext *s)
return -1; 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) static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
{ {
MOVMuxContext *mov = s->priv_data; MOVMuxContext *mov = s->priv_data;
...@@ -1876,11 +1902,19 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1876,11 +1902,19 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
pkt->pts = pkt->dts; pkt->pts = pkt->dts;
} }
if (pkt->dts != pkt->pts) 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].cts = pkt->pts - pkt->dts;
trk->cluster[trk->entry].flags = 0;
if (pkt->flags & PKT_FLAG_KEY) { if (pkt->flags & PKT_FLAG_KEY) {
trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE; if (mov->mode == MODE_MOV && enc->codec_id == CODEC_ID_MPEG2VIDEO) {
trk->hasKeyframes++; 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->entry++;
trk->sampleCount += samplesInChunk; trk->sampleCount += samplesInChunk;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment