Mercurial > libavformat.hg
comparison movenc.c @ 4941:45a08facad6f libavformat
write 'stps' for mpeg-2 open gop in .mov
author | bcoudurier |
---|---|
date | Fri, 15 May 2009 06:11:53 +0000 |
parents | 14cb663f11c3 |
children | 1b3487b81ac7 |
comparison
equal
deleted
inserted
replaced
4940:9bc9feb36557 | 4941:45a08facad6f |
---|---|
49 unsigned int samplesInChunk; | 49 unsigned int samplesInChunk; |
50 unsigned int entries; | 50 unsigned int entries; |
51 int cts; | 51 int cts; |
52 int64_t dts; | 52 int64_t dts; |
53 #define MOV_SYNC_SAMPLE 0x0001 | 53 #define MOV_SYNC_SAMPLE 0x0001 |
54 #define MOV_PARTIAL_SYNC_SAMPLE 0x0002 | |
54 uint32_t flags; | 55 uint32_t flags; |
55 } MOVIentry; | 56 } MOVIentry; |
56 | 57 |
57 typedef struct MOVIndex { | 58 typedef struct MOVIndex { |
58 int mode; | 59 int mode; |
61 long time; | 62 long time; |
62 int64_t trackDuration; | 63 int64_t trackDuration; |
63 long sampleCount; | 64 long sampleCount; |
64 long sampleSize; | 65 long sampleSize; |
65 int hasKeyframes; | 66 int hasKeyframes; |
66 int hasBframes; | 67 #define MOV_TRACK_CTTS 0x0001 |
68 #define MOV_TRACK_STPS 0x0002 | |
69 uint32_t flags; | |
67 int language; | 70 int language; |
68 int trackID; | 71 int trackID; |
69 int tag; ///< stsd fourcc | 72 int tag; ///< stsd fourcc |
70 AVCodecContext *enc; | 73 AVCodecContext *enc; |
71 | 74 |
186 | 189 |
187 return updateSize(pb, pos); | 190 return updateSize(pb, pos); |
188 } | 191 } |
189 | 192 |
190 /* Sync sample atom */ | 193 /* Sync sample atom */ |
191 static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack *track) | 194 static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack *track, uint32_t flag) |
192 { | 195 { |
193 int64_t curpos, entryPos; | 196 int64_t curpos, entryPos; |
194 int i, index = 0; | 197 int i, index = 0; |
195 int64_t pos = url_ftell(pb); | 198 int64_t pos = url_ftell(pb); |
196 put_be32(pb, 0); // size | 199 put_be32(pb, 0); // size |
197 put_tag(pb, "stss"); | 200 put_tag(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps"); |
198 put_be32(pb, 0); // version & flags | 201 put_be32(pb, 0); // version & flags |
199 entryPos = url_ftell(pb); | 202 entryPos = url_ftell(pb); |
200 put_be32(pb, track->entry); // entry count | 203 put_be32(pb, track->entry); // entry count |
201 for (i=0; i<track->entry; i++) { | 204 for (i=0; i<track->entry; i++) { |
202 if (track->cluster[i].flags & MOV_SYNC_SAMPLE) { | 205 if (track->cluster[i].flags & flag) { |
203 put_be32(pb, i+1); | 206 put_be32(pb, i+1); |
204 index++; | 207 index++; |
205 } | 208 } |
206 } | 209 } |
207 curpos = url_ftell(pb); | 210 curpos = url_ftell(pb); |
912 put_tag(pb, "stbl"); | 915 put_tag(pb, "stbl"); |
913 mov_write_stsd_tag(pb, track); | 916 mov_write_stsd_tag(pb, track); |
914 mov_write_stts_tag(pb, track); | 917 mov_write_stts_tag(pb, track); |
915 if (track->enc->codec_type == CODEC_TYPE_VIDEO && | 918 if (track->enc->codec_type == CODEC_TYPE_VIDEO && |
916 track->hasKeyframes && track->hasKeyframes < track->entry) | 919 track->hasKeyframes && track->hasKeyframes < track->entry) |
917 mov_write_stss_tag(pb, track); | 920 mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); |
921 if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS) | |
922 mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE); | |
918 if (track->enc->codec_type == CODEC_TYPE_VIDEO && | 923 if (track->enc->codec_type == CODEC_TYPE_VIDEO && |
919 track->hasBframes) | 924 track->flags & MOV_TRACK_CTTS) |
920 mov_write_ctts_tag(pb, track); | 925 mov_write_ctts_tag(pb, track); |
921 mov_write_stsc_tag(pb, track); | 926 mov_write_stsc_tag(pb, track); |
922 mov_write_stsz_tag(pb, track); | 927 mov_write_stsz_tag(pb, track); |
923 mov_write_stco_tag(pb, track); | 928 mov_write_stco_tag(pb, track); |
924 return updateSize(pb, pos); | 929 return updateSize(pb, pos); |
1171 { | 1176 { |
1172 int64_t pos = url_ftell(pb); | 1177 int64_t pos = url_ftell(pb); |
1173 put_be32(pb, 0); /* size */ | 1178 put_be32(pb, 0); /* size */ |
1174 put_tag(pb, "trak"); | 1179 put_tag(pb, "trak"); |
1175 mov_write_tkhd_tag(pb, track, st); | 1180 mov_write_tkhd_tag(pb, track, st); |
1176 if (track->mode == MODE_PSP || track->hasBframes) | 1181 if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS) |
1177 mov_write_edts_tag(pb, track); // PSP Movies require edts box | 1182 mov_write_edts_tag(pb, track); // PSP Movies require edts box |
1178 mov_write_mdia_tag(pb, track); | 1183 mov_write_mdia_tag(pb, track); |
1179 if (track->mode == MODE_PSP) | 1184 if (track->mode == MODE_PSP) |
1180 mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box | 1185 mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box |
1181 return updateSize(pb, pos); | 1186 return updateSize(pb, pos); |
1800 error: | 1805 error: |
1801 av_freep(&mov->tracks); | 1806 av_freep(&mov->tracks); |
1802 return -1; | 1807 return -1; |
1803 } | 1808 } |
1804 | 1809 |
1810 static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags) | |
1811 { | |
1812 uint32_t c = -1; | |
1813 int i, closed_gop = 0; | |
1814 | |
1815 for (i = 0; i < pkt->size - 4; i++) { | |
1816 c = (c<<8) + pkt->data[i]; | |
1817 if (c == 0x1b8) { // gop | |
1818 closed_gop = pkt->data[i+4]>>6 & 0x01; | |
1819 } else if (c == 0x100) { // pic | |
1820 int temp_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6); | |
1821 if (!temp_ref || closed_gop) // I picture is not reordered | |
1822 *flags = MOV_SYNC_SAMPLE; | |
1823 else | |
1824 *flags = MOV_PARTIAL_SYNC_SAMPLE; | |
1825 break; | |
1826 } | |
1827 } | |
1828 return 0; | |
1829 } | |
1830 | |
1805 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) | 1831 static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) |
1806 { | 1832 { |
1807 MOVMuxContext *mov = s->priv_data; | 1833 MOVMuxContext *mov = s->priv_data; |
1808 ByteIOContext *pb = s->pb; | 1834 ByteIOContext *pb = s->pb; |
1809 MOVTrack *trk = &mov->tracks[pkt->stream_index]; | 1835 MOVTrack *trk = &mov->tracks[pkt->stream_index]; |
1874 if (pkt->pts == AV_NOPTS_VALUE) { | 1900 if (pkt->pts == AV_NOPTS_VALUE) { |
1875 av_log(s, AV_LOG_WARNING, "pts has no value\n"); | 1901 av_log(s, AV_LOG_WARNING, "pts has no value\n"); |
1876 pkt->pts = pkt->dts; | 1902 pkt->pts = pkt->dts; |
1877 } | 1903 } |
1878 if (pkt->dts != pkt->pts) | 1904 if (pkt->dts != pkt->pts) |
1879 trk->hasBframes = 1; | 1905 trk->flags |= MOV_TRACK_CTTS; |
1880 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts; | 1906 trk->cluster[trk->entry].cts = pkt->pts - pkt->dts; |
1907 trk->cluster[trk->entry].flags = 0; | |
1881 if (pkt->flags & PKT_FLAG_KEY) { | 1908 if (pkt->flags & PKT_FLAG_KEY) { |
1882 trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE; | 1909 if (mov->mode == MODE_MOV && enc->codec_id == CODEC_ID_MPEG2VIDEO) { |
1883 trk->hasKeyframes++; | 1910 mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags); |
1911 if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE) | |
1912 trk->flags |= MOV_TRACK_STPS; | |
1913 } else { | |
1914 trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE; | |
1915 } | |
1916 if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE) | |
1917 trk->hasKeyframes++; | |
1884 } | 1918 } |
1885 trk->entry++; | 1919 trk->entry++; |
1886 trk->sampleCount += samplesInChunk; | 1920 trk->sampleCount += samplesInChunk; |
1887 mov->mdat_size += size; | 1921 mov->mdat_size += size; |
1888 | 1922 |