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