comparison movenc.c @ 298:0b2eed7b1210 libavformat

movenc patch by (Gildas Bazin <gbazin at altern dot org>)
author michael
date Mon, 03 Nov 2003 21:51:07 +0000
parents eccf0c3e3289
children 5ee1aa8cc0ea
comparison
equal deleted inserted replaced
297:85d558a18134 298:0b2eed7b1210
1 /* 1 /*
2 * MOV, 3GP, MP4 encoder. 2 * MOV, 3GP, MP4 encoder.
3 * Copyright (c) 2003 Thomas Raivio. 3 * Copyright (c) 2003 Thomas Raivio.
4 * Enhancements by Gildas Bazin <gbazin@netcourrier.com>
4 * 5 *
5 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public 7 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either 8 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 9 * version 2 of the License, or (at your option) any later version.
26 27
27 #define MOV_INDEX_CLUSTER_SIZE 16384 28 #define MOV_INDEX_CLUSTER_SIZE 16384
28 #define globalTimescale 1000 29 #define globalTimescale 1000
29 30
30 typedef struct MOVIentry { 31 typedef struct MOVIentry {
31 unsigned int flags, pos, len; 32 unsigned int flags, pos, size;
32 unsigned int chunkSize; 33 unsigned int samplesInChunk;
33 char key_frame; 34 char key_frame;
34 unsigned int entries; 35 unsigned int entries;
35 } MOVIentry; 36 } MOVIentry;
36 37
37 typedef struct MOVIndex { 38 typedef struct MOVIndex {
38 int entry; 39 int entry;
39 int samples;
40 int mdat_size; 40 int mdat_size;
41 int ents_allocated; 41 int ents_allocated;
42 long timescale; 42 long timescale;
43 long time; 43 long time;
44 long frameCount;
45 long trackDuration; 44 long trackDuration;
46 long sampleDelta; 45 long sampleCount;
46 long sampleDuration;
47 int hasKeyframes; 47 int hasKeyframes;
48 int trackID; 48 int trackID;
49 AVCodecContext *enc; 49 AVCodecContext *enc;
50 50
51 int vosLen; 51 int vosLen;
61 offset_t movi_list; 61 offset_t movi_list;
62 long timescale; 62 long timescale;
63 MOVTrack tracks[MAX_STREAMS]; 63 MOVTrack tracks[MAX_STREAMS];
64 } MOVContext; 64 } MOVContext;
65 65
66 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);
67
66 //FIXME supprt 64bit varaint with wide placeholders 68 //FIXME supprt 64bit varaint with wide placeholders
67 static int updateSize (ByteIOContext *pb, int pos) 69 static int updateSize (ByteIOContext *pb, int pos)
68 { 70 {
69 long curpos = url_ftell(pb); 71 long curpos = url_ftell(pb);
70 url_fseek(pb, pos, SEEK_SET); 72 url_fseek(pb, pos, SEEK_SET);
72 url_fseek(pb, curpos, SEEK_SET); 74 url_fseek(pb, curpos, SEEK_SET);
73 75
74 return curpos - pos; 76 return curpos - pos;
75 } 77 }
76 78
79 /* Chunk offset atom */
77 static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track) 80 static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
78 { 81 {
79 int i; 82 int i;
80 int pos = url_ftell(pb); 83 int pos = url_ftell(pb);
81 put_be32(pb, 0); /* size */ 84 put_be32(pb, 0); /* size */
88 put_be32(pb, track->cluster[cl][id].pos); 91 put_be32(pb, track->cluster[cl][id].pos);
89 } 92 }
90 return updateSize (pb, pos); 93 return updateSize (pb, pos);
91 } 94 }
92 95
96 /* Sample size atom */
93 static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track) 97 static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track)
94 { 98 {
95 int equalChunks = 1; 99 int equalChunks = 1;
96 int i, tst = -1, oldtst = -1; 100 int i, j, entries = 0, tst = -1, oldtst = -1;
97 101
98 int pos = url_ftell(pb); 102 int pos = url_ftell(pb);
99 put_be32(pb, 0); /* size */ 103 put_be32(pb, 0); /* size */
100 put_tag(pb, "stsz"); 104 put_tag(pb, "stsz");
101 put_be32(pb, 0); /* version & flags */ 105 put_be32(pb, 0); /* version & flags */
102 106
103 for (i=0; i<track->entry; i++) { 107 for (i=0; i<track->entry; i++) {
104 int cl = i / MOV_INDEX_CLUSTER_SIZE; 108 int cl = i / MOV_INDEX_CLUSTER_SIZE;
105 int id = i % MOV_INDEX_CLUSTER_SIZE; 109 int id = i % MOV_INDEX_CLUSTER_SIZE;
106 tst = track->cluster[cl][id].len; 110 tst = track->cluster[cl][id].size/track->cluster[cl][id].entries;
107 if(oldtst != -1 && tst != oldtst) { 111 if(oldtst != -1 && tst != oldtst) {
108 equalChunks = 0; 112 equalChunks = 0;
109 break;
110 } 113 }
111 oldtst = tst; 114 oldtst = tst;
112 } 115 entries += track->cluster[cl][id].entries;
113 if(equalChunks || 116 }
114 track->enc->codec_type == CODEC_TYPE_AUDIO) { 117 if (equalChunks) {
115 //int sSize = track->cluster[0][0].len/track->cluster[0][0].entries; 118 int sSize = track->cluster[0][0].size/track->cluster[0][0].entries;
116 int sSize = track->cluster[0][0].len;
117 put_be32(pb, sSize); // sample size 119 put_be32(pb, sSize); // sample size
118 put_be32(pb, track->samples/track->enc->channels); // sample count 120 put_be32(pb, entries); // sample count
119 } 121 }
120 else { 122 else {
121 put_be32(pb, 0); // sample size 123 put_be32(pb, 0); // sample size
122 put_be32(pb, track->entry); // sample count 124 put_be32(pb, entries); // sample count
123 for (i=0; i<track->entry; i++) { 125 for (i=0; i<track->entry; i++) {
124 int cl = i / MOV_INDEX_CLUSTER_SIZE; 126 int cl = i / MOV_INDEX_CLUSTER_SIZE;
125 int id = i % MOV_INDEX_CLUSTER_SIZE; 127 int id = i % MOV_INDEX_CLUSTER_SIZE;
126 put_be32(pb, track->cluster[cl][id].len); 128 for ( j=0; j<track->cluster[cl][id].entries; j++) {
129 put_be32(pb, track->cluster[cl][id].size /
130 track->cluster[cl][id].entries);
131 }
127 } 132 }
128 } 133 }
129 return updateSize (pb, pos); 134 return updateSize (pb, pos);
130 } 135 }
131 136
137 /* Sample to chunk atom */
132 static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track) 138 static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
133 { 139 {
134 int index = 0, oldval = -1, i, entryPos, curpos; 140 int index = 0, oldval = -1, i, entryPos, curpos;
135 141
136 int pos = url_ftell(pb); 142 int pos = url_ftell(pb);
140 entryPos = url_ftell(pb); 146 entryPos = url_ftell(pb);
141 put_be32(pb, track->entry); // entry count 147 put_be32(pb, track->entry); // entry count
142 for (i=0; i<track->entry; i++) { 148 for (i=0; i<track->entry; i++) {
143 int cl = i / MOV_INDEX_CLUSTER_SIZE; 149 int cl = i / MOV_INDEX_CLUSTER_SIZE;
144 int id = i % MOV_INDEX_CLUSTER_SIZE; 150 int id = i % MOV_INDEX_CLUSTER_SIZE;
145 if(oldval != track->cluster[cl][id].chunkSize) 151 if(oldval != track->cluster[cl][id].samplesInChunk)
146 { 152 {
147 put_be32(pb, i+1); // first chunk 153 put_be32(pb, i+1); // first chunk
148 put_be32(pb, track->cluster[cl][id].chunkSize); 154 put_be32(pb, track->cluster[cl][id].samplesInChunk); // samples per chunk
149 put_be32(pb, 0x1); // sample description index 155 put_be32(pb, 0x1); // sample description index
150 oldval = track->cluster[cl][id].chunkSize; 156 oldval = track->cluster[cl][id].samplesInChunk;
151 index++; 157 index++;
152 } 158 }
153 } 159 }
154 curpos = url_ftell(pb); 160 curpos = url_ftell(pb);
155 url_fseek(pb, entryPos, SEEK_SET); 161 url_fseek(pb, entryPos, SEEK_SET);
157 url_fseek(pb, curpos, SEEK_SET); 163 url_fseek(pb, curpos, SEEK_SET);
158 164
159 return updateSize (pb, pos); 165 return updateSize (pb, pos);
160 } 166 }
161 167
168 /* Sync sample atom */
162 static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track) 169 static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track)
163 { 170 {
164 long curpos; 171 long curpos;
165 int i, index = 0, entryPos; 172 int i, index = 0, entryPos;
166 int pos = url_ftell(pb); 173 int pos = url_ftell(pb);
221 put_tag(pb, " "); 228 put_tag(pb, " ");
222 229
223 put_be32(pb, 0); /* Reserved */ 230 put_be32(pb, 0); /* Reserved */
224 put_be16(pb, 0); /* Reserved */ 231 put_be16(pb, 0); /* Reserved */
225 put_be16(pb, 1); /* Data-reference index, XXX == 1 */ 232 put_be16(pb, 1); /* Data-reference index, XXX == 1 */
226 put_be32(pb, 0); /* Reserved */ 233 /* SoundDescription */
234 put_be16(pb, 0); /* Version */
235 put_be16(pb, 0); /* Revision level */
227 put_be32(pb, 0); /* Reserved */ 236 put_be32(pb, 0); /* Reserved */
228 237
229 put_be16(pb, track->enc->channels); /* Number of channels */ 238 put_be16(pb, track->enc->channels); /* Number of channels */
230 /* TODO: Currently hard-coded to 16-bit, there doesn't seem 239 /* TODO: Currently hard-coded to 16-bit, there doesn't seem
231 to be a good way to get number of bits of audio */ 240 to be a good way to get number of bits of audio */
232 put_be16(pb, 0x10); /* Reserved */ 241 put_be16(pb, 0x10); /* Reserved */
233 put_be16(pb, 0); /* compression ID (= 0) */ 242 put_be16(pb, 0); /* compression ID (= 0) */
234 put_be16(pb, 0); /* packet size (= 0) */ 243 put_be16(pb, 0); /* packet size (= 0) */
235 put_be16(pb, track->timescale); /* Time scale */ 244 put_be16(pb, track->timescale); /* Time scale */
236 put_be16(pb, 0); /* Reserved */ 245 put_be16(pb, 0); /* Reserved */
237 246
247 if(track->enc->codec_id == CODEC_ID_AAC)
248 mov_write_esds_tag(pb, track);
238 if(track->enc->codec_id == CODEC_ID_AMR_NB) 249 if(track->enc->codec_id == CODEC_ID_AMR_NB)
239 mov_write_damr_tag(pb); 250 mov_write_damr_tag(pb);
240 return updateSize (pb, pos); 251 return updateSize (pb, pos);
241 } 252 }
242 253
261 put_be32(pb, 0xc0000000); 272 put_be32(pb, 0xc0000000);
262 put_byte(pb, 0); 273 put_byte(pb, 0);
263 return 0x15; 274 return 0x15;
264 } 275 }
265 276
266 static unsigned int esdsLength(unsigned int len) 277 static unsigned int descrLength(unsigned int len)
267 { 278 {
268 unsigned int result = 0; 279 if (len < 0x00000080)
269 unsigned char b = len & 0x7f; 280 return 2 + len;
270 result += b; 281 else if (len < 0x00004000)
271 b = (len >> 8) & 0x7f; 282 return 3 + len;
272 result += (b + 0x80) << 8; 283 else if(len < 0x00200000)
273 b = (len >> 16) & 0x7f; 284 return 4 + len;
274 result += (b + 0x80) << 16; 285 else
275 b = (len >> 24) & 0x7f; 286 return 5 + len;
276 result += (b + 0x80) << 24; 287 }
277 return result; 288
289 static void putDescr(ByteIOContext *pb, int tag, int size)
290 {
291 uint32_t len;
292 uint8_t vals[4];
293
294 len = size;
295 vals[3] = (uint8_t)(len & 0x7f);
296 len >>= 7;
297 vals[2] = (uint8_t)((len & 0x7f) | 0x80);
298 len >>= 7;
299 vals[1] = (uint8_t)((len & 0x7f) | 0x80);
300 len >>= 7;
301 vals[0] = (uint8_t)((len & 0x7f) | 0x80);
302
303 put_byte(pb, tag); // DescriptorTag
304
305 if (size < 0x00000080)
306 {
307 put_byte(pb, vals[3]);
308 }
309 else if (size < 0x00004000)
310 {
311 put_byte(pb, vals[2]);
312 put_byte(pb, vals[3]);
313 }
314 else if (size < 0x00200000)
315 {
316 put_byte(pb, vals[1]);
317 put_byte(pb, vals[2]);
318 put_byte(pb, vals[3]);
319 }
320 else if (size < 0x10000000)
321 {
322 put_byte(pb, vals[0]);
323 put_byte(pb, vals[1]);
324 put_byte(pb, vals[2]);
325 put_byte(pb, vals[3]);
326 }
278 } 327 }
279 328
280 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic 329 static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
281 { 330 {
282 put_be32(pb, track->vosLen+18+14+17); 331 int decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
332 int pos = url_ftell(pb);
333
334 put_be32(pb, 0); // size
283 put_tag(pb, "esds"); 335 put_tag(pb, "esds");
284 put_be32(pb, 0); // Version 336 put_be32(pb, 0); // Version
285 337
286 put_byte(pb, 0x03); // tag = ES_DescriptorTag 338 // ES descriptor
287 put_be32(pb, esdsLength(track->vosLen+18+14)); // Length 339 putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) +
288 put_be16(pb, 0x0001); // ID (= 1) 340 descrLength(1));
341 put_be16(pb, 0x0001); // ID (= 1)
289 put_byte(pb, 0x00); // flags (= no flags) 342 put_byte(pb, 0x00); // flags (= no flags)
290 343
291 // Decoderconfigdescriptor = 4 344 // DecoderConfig descriptor
292 put_byte(pb, 0x04); // tag = DecoderConfigDescriptor 345 putDescr(pb, 0x04, 13 + decoderSpecificInfoLen);
293 put_be32(pb, esdsLength(track->vosLen+18)); // Length 346
294 put_byte(pb, 0x20); // Object type indication (Visual 14496-2) 347 if(track->enc->codec_id == CODEC_ID_AAC)
295 put_byte(pb, 0x11); // flags (= Visualstream) 348 put_byte(pb, 0x40); // Object type indication
349 else if(track->enc->codec_id == CODEC_ID_MPEG4)
350 put_byte(pb, 0x20); // Object type indication (Visual 14496-2)
351
352 if(track->enc->codec_type == CODEC_TYPE_AUDIO)
353 put_byte(pb, 0x15); // flags (= Audiostream)
354 else
355 put_byte(pb, 0x11); // flags (= Visualstream)
356
296 put_byte(pb, 0x0); // Buffersize DB (24 bits) 357 put_byte(pb, 0x0); // Buffersize DB (24 bits)
297 put_be16(pb, 0x0dd2); // Buffersize DB 358 put_be16(pb, 0x0dd2); // Buffersize DB
298 359
299 // TODO: find real values for these 360 // TODO: find real values for these
300 put_be32(pb, 0x0002e918); // maxbitrate 361 put_be32(pb, 0x0002e918); // maxbitrate
301 put_be32(pb, 0x00017e6b); // avg bitrate 362 put_be32(pb, 0x00017e6b); // avg bitrate
302 363
303 // Decoderspecific info Tag = 5 364 if (track->vosLen)
304 put_byte(pb, 0x05); // tag = Decoderspecific info 365 {
305 put_be32(pb, esdsLength(track->vosLen)); // length 366 // DecoderSpecific info descriptor
306 put_buffer(pb, track->vosData, track->vosLen); 367 putDescr(pb, 0x05, track->vosLen);
307 368 put_buffer(pb, track->vosData, track->vosLen);
308 put_byte(pb, 0x06); 369 }
309 put_be32(pb, esdsLength(1)); // length 370
371 // SL descriptor
372 putDescr(pb, 0x06, descrLength(1));
310 put_byte(pb, 0x02); 373 put_byte(pb, 0x02);
311 return track->vosLen+18+14+17; 374 return updateSize (pb, pos);
312 } 375 }
313 376
314 static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track) 377 static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
315 { 378 {
316 int pos = url_ftell(pb); 379 int pos = url_ftell(pb);
374 mov_write_audio_tag(pb, track); 437 mov_write_audio_tag(pb, track);
375 return updateSize(pb, pos); 438 return updateSize(pb, pos);
376 } 439 }
377 440
378 /* TODO?: Currently all samples/frames seem to have same duration */ 441 /* TODO?: Currently all samples/frames seem to have same duration */
442 /* Time to sample atom */
379 static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track) 443 static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
380 { 444 {
381 put_be32(pb, 0x18); /* size */ 445 put_be32(pb, 0x18); /* size */
382 put_tag(pb, "stts"); 446 put_tag(pb, "stts");
383 put_be32(pb, 0); /* version & flags */ 447 put_be32(pb, 0); /* version & flags */
384 put_be32(pb, 1); /* entry count */ 448 put_be32(pb, 1); /* entry count */
385 449
386 put_be32(pb, track->frameCount); /* sample count */ 450 put_be32(pb, track->sampleCount); /* sample count */
387 put_be32(pb, track->sampleDelta); /* sample delta */ 451 put_be32(pb, track->sampleDuration); /* sample duration */
388 return 0x18; 452 return 0x18;
389 } 453 }
390 454
391 static int mov_write_dref_tag(ByteIOContext *pb) 455 static int mov_write_dref_tag(ByteIOContext *pb)
392 { 456 {
489 put_be32(pb, 32); /* size */ 553 put_be32(pb, 32); /* size */
490 put_tag(pb, "mdhd"); 554 put_tag(pb, "mdhd");
491 put_be32(pb, 0); /* Version & flags */ 555 put_be32(pb, 0); /* Version & flags */
492 put_be32(pb, track->time); /* creation time */ 556 put_be32(pb, track->time); /* creation time */
493 put_be32(pb, track->time); /* modification time */ 557 put_be32(pb, track->time); /* modification time */
494 if(track->enc->codec_type == CODEC_TYPE_VIDEO) { 558 put_be32(pb, track->timescale); /* time scale (sample rate for audio) */
495 int64_t rate = track->enc->frame_rate; 559 put_be32(pb, track->trackDuration); /* duration */
496 put_be32(pb, rate);
497 put_be32(pb, rate*(int64_t)track->trackDuration/(int64_t)globalTimescale); // duration
498 }
499 else {
500 put_be32(pb, track->timescale); /* time scale (sample rate for audio) */
501 put_be32(pb, track->trackDuration); /* duration */
502 }
503 put_be16(pb, 0); /* language, 0 = english */ 560 put_be16(pb, 0); /* language, 0 = english */
504 put_be16(pb, 0); /* reserved (quality) */ 561 put_be16(pb, 0); /* reserved (quality) */
505 return 32; 562 return 32;
506 } 563 }
507 564
642 put_be32(pb, 0); /* size placeholder*/ 699 put_be32(pb, 0); /* size placeholder*/
643 put_tag(pb, "moov"); 700 put_tag(pb, "moov");
644 mov->timescale = globalTimescale; 701 mov->timescale = globalTimescale;
645 702
646 for (i=0; i<MAX_STREAMS; i++) { 703 for (i=0; i<MAX_STREAMS; i++) {
647 if(mov->tracks[i].entry > 0) { 704 if(mov->tracks[i].entry <= 0) continue;
648 if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) { 705
649 mov->tracks[i].timescale = globalTimescale; 706 if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
650 mov->tracks[i].sampleDelta = mov->tracks[i].enc->frame_rate_base; 707 mov->tracks[i].timescale = mov->tracks[i].enc->frame_rate;
651 mov->tracks[i].frameCount = mov->tracks[i].samples; 708 mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_rate_base;
652 mov->tracks[i].trackDuration = (int64_t)((int64_t)mov->tracks[i].entry* 709 }
653 (int64_t)globalTimescale*(int64_t)mov->tracks[i].enc->frame_rate_base)/(int64_t)mov->tracks[i].enc->frame_rate; 710 else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
711 /* If AMR, track timescale = 8000, AMR_WB = 16000 */
712 if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
713 mov->tracks[i].sampleDuration = 160; // Bytes per chunk
714 mov->tracks[i].timescale = 8000;
654 } 715 }
655 else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) { 716 else {
656 long trackDuration = 0; 717 mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
657 /* If AMR, track timescale = 8000, AMR_WB = 16000 */ 718 mov->tracks[i].sampleDuration = mov->tracks[i].enc->frame_size;
658 if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
659 int j;
660 for (j=0; j<mov->tracks[i].samples; j++) {
661 int cl = j / MOV_INDEX_CLUSTER_SIZE;
662 int id = j % MOV_INDEX_CLUSTER_SIZE;
663 trackDuration += mov->tracks[i].cluster[cl][id].entries;
664 }
665 mov->tracks[i].sampleDelta = 160; // Bytes per chunk
666 mov->tracks[i].frameCount = mov->tracks[i].samples;
667 mov->tracks[i].trackDuration =
668 mov->tracks[i].samples * mov->tracks[i].sampleDelta; //trackDuration
669 mov->tracks[i].timescale = 8000;
670 }
671 else {
672 int j;
673 for (j=0; j<=mov->tracks[i].entry; j++) {
674 int cl = j / MOV_INDEX_CLUSTER_SIZE;
675 int id = j % MOV_INDEX_CLUSTER_SIZE;
676 trackDuration += mov->tracks[i].cluster[cl][id].len;
677 }
678 mov->tracks[i].frameCount = trackDuration;
679 mov->tracks[i].timescale = mov->tracks[i].enc->sample_rate;
680 mov->tracks[i].sampleDelta = 1;
681 mov->tracks[i].trackDuration = trackDuration;
682 }
683 } 719 }
684 mov->tracks[i].time = mov->time; 720 }
685 mov->tracks[i].trackID = i+1; 721
686 } 722 mov->tracks[i].trackDuration =
723 mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
724 mov->tracks[i].time = mov->time;
725 mov->tracks[i].trackID = i+1;
687 } 726 }
688 727
689 mov_write_mvhd_tag(pb, mov); 728 mov_write_mvhd_tag(pb, mov);
690 //mov_write_iods_tag(pb, mov); 729 //mov_write_iods_tag(pb, mov);
691 for (i=0; i<MAX_STREAMS; i++) { 730 for (i=0; i<MAX_STREAMS; i++) {
704 put_tag(pb, "mdat"); 743 put_tag(pb, "mdat");
705 return 0; 744 return 0;
706 } 745 }
707 746
708 /* TODO: This needs to be more general */ 747 /* TODO: This needs to be more general */
709 int mov_write_ftyp_tag(ByteIOContext *pb) 748 int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
710 { 749 {
711 put_be32(pb, 0x14 ); /* size */ 750 put_be32(pb, 0x14 ); /* size */
712 put_tag(pb, "ftyp"); 751 put_tag(pb, "ftyp");
713 put_tag(pb, "3gp4"); 752
753 if (!strcmp("3gp", s->oformat->name))
754 put_tag(pb, "3gp4");
755 else
756 put_tag(pb, "isom");
757
714 put_be32(pb, 0x200 ); 758 put_be32(pb, 0x200 );
715 put_tag(pb, "3gp4"); 759
760 if (!strcmp("3gp", s->oformat->name))
761 put_tag(pb, "3gp4");
762 else
763 put_tag(pb, "mp41");
764
716 return 0x14; 765 return 0x14;
717 } 766 }
718 767
719 static int mov_write_header(AVFormatContext *s) 768 static int mov_write_header(AVFormatContext *s)
720 { 769 {
721 ByteIOContext *pb = &s->pb; 770 ByteIOContext *pb = &s->pb;
722 771
723 if(s->oformat != NULL) { 772 if(s->oformat != NULL) {
724 if(!strcmp("3gp", s->oformat->name)) 773 if(!strcmp("3gp", s->oformat->name) || !strcmp("mp4", s->oformat->name))
725 mov_write_ftyp_tag(pb); 774 mov_write_ftyp_tag(pb,s);
726 } 775 }
727 776
728 put_flush_packet(pb); 777 put_flush_packet(pb);
729 778
730 return 0; 779 return 0;
739 static int mov_write_packet(AVFormatContext *s, int stream_index, 788 static int mov_write_packet(AVFormatContext *s, int stream_index,
740 const uint8_t *buf, int size, int64_t pts) 789 const uint8_t *buf, int size, int64_t pts)
741 { 790 {
742 MOVContext *mov = s->priv_data; 791 MOVContext *mov = s->priv_data;
743 ByteIOContext *pb = &s->pb; 792 ByteIOContext *pb = &s->pb;
744 AVCodecContext *enc; 793 AVCodecContext *enc = &s->streams[stream_index]->codec;
794 MOVTrack* trk = &mov->tracks[stream_index];
745 int cl, id; 795 int cl, id;
746 796 unsigned int samplesInChunk = 0;
747 enc = &s->streams[stream_index]->codec; 797
748 if (!url_is_streamed(&s->pb)) { 798 if (url_is_streamed(&s->pb)) return 0; /* Can't handle that */
749 MOVTrack* trk = &mov->tracks[stream_index]; 799 if (!size) return 0; /* Discard 0 sized packets */
750 int sampleCount = 0; 800
751 unsigned int chunkSize = 0; 801 if (enc->codec_type == CODEC_TYPE_VIDEO ) {
752 802 samplesInChunk = 1;
753 if(enc->codec_type == CODEC_TYPE_AUDIO) { 803 }
804 else if (enc->codec_type == CODEC_TYPE_AUDIO ) {
805 if( enc->codec_id == CODEC_ID_AMR_NB) {
754 /* We must find out how many AMR blocks there are in one packet */ 806 /* We must find out how many AMR blocks there are in one packet */
755 if(enc->codec_id == CODEC_ID_AMR_NB) { 807 static uint16_t packed_size[16] =
756 static uint16_t packed_size[16] = {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0}; 808 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};
757 int len = 0; 809 int len = 0;
758 810
759 while(len < size && sampleCount < 100) { 811 while (len < size && samplesInChunk < 100) {
760 len += packed_size[(buf[len] >> 3) & 0x0F]; 812 len += packed_size[(buf[len] >> 3) & 0x0F];
761 sampleCount++; 813 samplesInChunk++;
762 }
763 chunkSize = 1;
764 } 814 }
765 else { 815 }
766 sampleCount = size; 816 else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
767 chunkSize = size/enc->channels; 817 samplesInChunk = size/enc->channels;
768 } 818 }
769 } 819 else {
770 else if(enc->codec_type == CODEC_TYPE_VIDEO) { 820 samplesInChunk = 1;
771 if(enc->codec_id == CODEC_ID_MPEG4 && 821 }
772 trk->vosLen == 0) 822 }
773 { 823
774 assert(enc->extradata_size); 824 if ((enc->codec_id == CODEC_ID_MPEG4 || enc->codec_id == CODEC_ID_AAC)
775 825 && trk->vosLen == 0) {
776 trk->vosLen = enc->extradata_size; 826 assert(enc->extradata_size);
777 trk->vosData = av_malloc(trk->vosLen); 827
778 memcpy(trk->vosData, enc->extradata, trk->vosLen); 828 trk->vosLen = enc->extradata_size;
779 } 829 trk->vosData = av_malloc(trk->vosLen);
780 chunkSize = 1; 830 memcpy(trk->vosData, enc->extradata, trk->vosLen);
781 } 831 }
782 832
783 cl = trk->entry / MOV_INDEX_CLUSTER_SIZE; 833 cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
784 id = trk->entry % MOV_INDEX_CLUSTER_SIZE; 834 id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
785 835
786 if (trk->ents_allocated <= trk->entry) { 836 if (trk->ents_allocated <= trk->entry) {
787 trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*)); 837 trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*));
788 if (!trk->cluster) 838 if (!trk->cluster)
789 return -1; 839 return -1;
790 trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry)); 840 trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
791 if (!trk->cluster[cl]) 841 if (!trk->cluster[cl])
792 return -1; 842 return -1;
793 trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE; 843 trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
794 } 844 }
795 if(mov->mdat_written == 0) { 845 if (mov->mdat_written == 0) {
796 mov_write_mdat_tag(pb, mov); 846 mov_write_mdat_tag(pb, mov);
797 mov->mdat_written = 1; 847 mov->mdat_written = 1;
798 mov->time = Timestamp(); 848 mov->time = Timestamp();
799 } 849 }
800 850
801 trk->cluster[cl][id].pos = url_ftell(pb) - mov->movi_list; 851 trk->cluster[cl][id].pos = url_ftell(pb) - mov->movi_list;
802 trk->cluster[cl][id].chunkSize = chunkSize; 852 trk->cluster[cl][id].samplesInChunk = samplesInChunk;
803 if(enc->channels > 1) 853 trk->cluster[cl][id].size = size;
804 trk->cluster[cl][id].len = size/enc->channels; 854 trk->cluster[cl][id].entries = samplesInChunk;
805 else 855 if(enc->codec_type == CODEC_TYPE_VIDEO) {
806 trk->cluster[cl][id].len = size; 856 trk->cluster[cl][id].key_frame = enc->coded_frame->key_frame;
807 trk->cluster[cl][id].entries = sampleCount; 857 if(enc->coded_frame->pict_type == FF_I_TYPE)
808 if(enc->codec_type == CODEC_TYPE_VIDEO) {
809 trk->cluster[cl][id].key_frame = enc->coded_frame->key_frame;
810 if(enc->coded_frame->pict_type == FF_I_TYPE)
811 trk->hasKeyframes = 1; 858 trk->hasKeyframes = 1;
812 } 859 }
813 trk->enc = enc; 860 trk->enc = enc;
814 trk->entry++; 861 trk->entry++;
815 if(sampleCount == 0) 862 trk->sampleCount += samplesInChunk;
816 trk->samples++; 863 trk->mdat_size += size;
817 else 864
818 trk->samples += sampleCount;
819 trk->mdat_size += size;
820 }
821 put_buffer(pb, buf, size); 865 put_buffer(pb, buf, size);
822 866
823 put_flush_packet(pb); 867 put_flush_packet(pb);
824 return 0; 868 return 0;
825 } 869 }