~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/libavformat/movenc.c

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2004-08-29 10:53:42 UTC
  • Revision ID: james.westby@ubuntu.com-20040829105342-qgmnry37eadfkoxx
Tags: upstream-1.1.3
ImportĀ upstreamĀ versionĀ 1.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * MOV, 3GP, MP4 encoder.
 
3
 * Copyright (c) 2003 Thomas Raivio.
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 */
 
19
#include "avformat.h"
 
20
#include "avio.h"
 
21
#include <time.h>
 
22
 
 
23
#undef NDEBUG
 
24
#include <assert.h>
 
25
 
 
26
/*
 
27
 * Limitations
 
28
 * - Currently supports h.263, MPEG4 video codecs, and AMR audio codec.
 
29
 */
 
30
 
 
31
#define MOV_INDEX_CLUSTER_SIZE 16384
 
32
#define globalTimescale 1000
 
33
 
 
34
typedef struct MOVIentry {
 
35
    unsigned int flags, pos, len;
 
36
    unsigned int entries;
 
37
} MOVIentry;
 
38
 
 
39
typedef struct MOVIndex {
 
40
    int         entry;
 
41
    int         samples;
 
42
    int         mdat_size;
 
43
    offset_t    mdat_pos;
 
44
    int         ents_allocated;
 
45
    long        timescale;
 
46
    long        time;
 
47
    long        frameDuration;
 
48
    long        sampleDelta;
 
49
    int         trackID;
 
50
    AVCodecContext *enc;
 
51
 
 
52
    int         vosLen;
 
53
    uint8_t     *vosData;
 
54
    MOVIentry** cluster;
 
55
} MOVTrack;
 
56
 
 
57
typedef struct {
 
58
    long    time;
 
59
    int     nb_streams;
 
60
    offset_t movi_list;
 
61
    long    timescale;
 
62
    MOVTrack tracks[MAX_STREAMS];
 
63
} MOVContext;
 
64
 
 
65
//FIXME supprt 64bit varaint with wide placeholders
 
66
static int updateSize (ByteIOContext *pb, int pos)
 
67
{
 
68
    long curpos = url_ftell(pb);
 
69
    url_fseek(pb, pos, SEEK_SET);
 
70
    put_be32(pb, curpos - pos); /* rewrite size */
 
71
    url_fseek(pb, curpos, SEEK_SET);
 
72
 
 
73
    return curpos - pos;
 
74
}
 
75
 
 
76
static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
 
77
{
 
78
    int i;
 
79
    put_be32(pb, 16+track->entry*4); /* size */
 
80
    put_tag(pb, "stco");
 
81
    put_be32(pb, 0); /* version & flags */
 
82
    put_be32(pb, track->entry); /* entry count */
 
83
    for (i=0; i<track->entry; i++) {
 
84
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
 
85
        int id = i % MOV_INDEX_CLUSTER_SIZE;
 
86
        put_be32(pb, track->cluster[cl][id].pos);
 
87
    }
 
88
    return 16+track->entry*4;
 
89
}
 
90
 
 
91
static int mov_write_stsz_tag(ByteIOContext *pb, MOVTrack* track)
 
92
{
 
93
    int i, size;
 
94
 
 
95
    if(track->cluster[0][0].entries != 0) 
 
96
        size = 20;
 
97
    else
 
98
        size = 20+track->samples*4;
 
99
    put_be32(pb, size); /* size */
 
100
    put_tag(pb, "stsz");
 
101
    put_be32(pb, 0); /* version & flags */
 
102
 
 
103
    /* TODO: Ugly (and false) assumption: if we have a chunk of samples, assume
 
104
     * all sizes are same */
 
105
    if(track->cluster[0][0].entries != 0)   {
 
106
        int sSize = track->cluster[0][0].len/track->cluster[0][0].entries;
 
107
        put_be32(pb, sSize); /* sample size */
 
108
        put_be32(pb, track->samples); /* sample count */
 
109
    }
 
110
    else 
 
111
    {
 
112
        put_be32(pb, 0); /* sample size */
 
113
        put_be32(pb, track->samples); /* sample count */
 
114
        for (i=0; i<track->samples; i++) {
 
115
            int cl = i / MOV_INDEX_CLUSTER_SIZE;
 
116
            int id = i % MOV_INDEX_CLUSTER_SIZE;
 
117
            put_be32(pb, track->cluster[cl][id].len);
 
118
        }
 
119
    }
 
120
    return size;
 
121
}
 
122
 
 
123
static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
 
124
{
 
125
    int size;
 
126
    if(track->cluster[0][0].entries != 0)
 
127
        size = 16+track->entry*4*3;
 
128
    else
 
129
        size = 0x1c;
 
130
    put_be32(pb, size); // size 
 
131
    put_tag(pb, "stsc");
 
132
    put_be32(pb, 0); // version & flags 
 
133
    if(track->cluster[0][0].entries != 0) {
 
134
        int i;
 
135
        put_be32(pb, track->entry); // entry count 
 
136
        for (i=0; i<track->entry; i++) {
 
137
            int cl = i / MOV_INDEX_CLUSTER_SIZE;
 
138
            int id = i % MOV_INDEX_CLUSTER_SIZE;
 
139
            put_be32(pb, i+1); // first chunk 
 
140
            put_be32(pb, track->cluster[cl][id].entries);
 
141
            put_be32(pb, 0x1); // sample description index 
 
142
        }
 
143
    }
 
144
    else {
 
145
        put_be32(pb, 1); // entry count 
 
146
        put_be32(pb, 0x1); // first chunk 
 
147
        put_be32(pb, 0x1); // samples per chunk 
 
148
        put_be32(pb, 0x1); // sample description index 
 
149
    }
 
150
 
 
151
    return size;
 
152
}
 
153
 
 
154
//FIXME keyframes?
 
155
static int mov_write_stss_tag(ByteIOContext *pb) //TRA OK
 
156
{
 
157
    put_be32(pb, 0x14); /* size */
 
158
    put_tag(pb, "stss");
 
159
    put_be32(pb, 0); /* version & flags */
 
160
    put_be32(pb, 1); /* entry count */
 
161
    put_be32(pb, 0x1); /* sample number */
 
162
    return 0x14;
 
163
}
 
164
 
 
165
static int mov_write_damr_tag(ByteIOContext *pb)
 
166
{
 
167
    put_be32(pb, 0x11); /* size */
 
168
    put_tag(pb, "damr");
 
169
    put_tag(pb, "FFMP");
 
170
    put_byte(pb, 0);
 
171
    put_be16(pb, 0x81ff); /* Mode set (all modes for AMR_NB) */
 
172
    put_be16(pb, 1); /* Mode change period (no restriction) */
 
173
    return 0x11;
 
174
}
 
175
 
 
176
static int mov_write_samr_tag(ByteIOContext *pb, MOVTrack* track)
 
177
{
 
178
    int pos = url_ftell(pb);
 
179
    put_be32(pb, 0); /* size */
 
180
    /* "samr" for AMR NB, "sawb" for AMR WB */
 
181
    put_tag(pb, "samr");
 
182
    put_be32(pb, 0); /* Reserved */
 
183
    put_be16(pb, 0); /* Reserved */
 
184
    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
 
185
    put_be32(pb, 0); /* Reserved */
 
186
    put_be32(pb, 0); /* Reserved */
 
187
 
 
188
    put_be16(pb, 2); /* Reserved */
 
189
    put_be16(pb, 0x10); /* Reserved */
 
190
    put_be32(pb, 0); /* Reserved */
 
191
    put_be16(pb, track->timescale); /* Time scale */
 
192
    put_be16(pb, 0); /* Reserved */
 
193
 
 
194
    mov_write_damr_tag(pb);
 
195
    return updateSize (pb, pos);
 
196
}
 
197
 
 
198
static int mov_write_d263_tag(ByteIOContext *pb)
 
199
{
 
200
    put_be32(pb, 0xf); /* size */
 
201
    put_tag(pb, "d263");
 
202
    put_tag(pb, "FFMP");
 
203
    put_be16(pb, 0x0a);
 
204
    put_byte(pb, 0);
 
205
    return 0xf;
 
206
}
 
207
 
 
208
static int mov_write_s263_tag(ByteIOContext *pb, MOVTrack* track)
 
209
{
 
210
    int pos = url_ftell(pb);
 
211
    put_be32(pb, 0); /* size */
 
212
    put_tag(pb, "s263");
 
213
    put_be32(pb, 0); /* Reserved */
 
214
    put_be16(pb, 0); /* Reserved */
 
215
    put_be16(pb, 1); /* Data-reference index */
 
216
    put_be32(pb, 0); /* Reserved */
 
217
    put_be32(pb, 0); /* Reserved */
 
218
    put_be32(pb, 0); /* Reserved */
 
219
    put_be32(pb, 0); /* Reserved */
 
220
    put_be16(pb, track->enc->width); /* Video width */
 
221
    put_be16(pb, track->enc->height); /* Video height */
 
222
    put_be32(pb, 0x00480000); /* Reserved */
 
223
    put_be32(pb, 0x00480000); /* Reserved */
 
224
    put_be32(pb, 0); /* Reserved */
 
225
    put_be16(pb, 1); /* Reserved */
 
226
    put_be32(pb, 0); /* Reserved */
 
227
    put_be32(pb, 0); /* Reserved */
 
228
    put_be32(pb, 0); /* Reserved */
 
229
    put_be32(pb, 0); /* Reserved */
 
230
    put_be32(pb, 0); /* Reserved */
 
231
    put_be32(pb, 0); /* Reserved */
 
232
    put_be32(pb, 0); /* Reserved */
 
233
    put_be32(pb, 0); /* Reserved */
 
234
    put_be16(pb, 0x18); /* Reserved */
 
235
    put_be16(pb, 0xffff); /* Reserved */
 
236
    mov_write_d263_tag(pb);
 
237
    return updateSize (pb, pos);
 
238
}
 
239
 
 
240
static unsigned int esdsLength(unsigned int len)
 
241
{
 
242
    unsigned int result = 0;
 
243
    unsigned char b = len & 0x7f;
 
244
    result += b;
 
245
    b = (len >> 8) & 0x7f;
 
246
    result += (b + 0x80) << 8;
 
247
    b = (len >> 16) & 0x7f;
 
248
    result += (b + 0x80) << 16;
 
249
    b = (len >> 24) & 0x7f;
 
250
    result += (b + 0x80) << 24;
 
251
    return result;
 
252
}
 
253
 
 
254
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
 
255
{
 
256
    put_be32(pb, track->vosLen+18+14+17);
 
257
    put_tag(pb, "esds");
 
258
    put_be32(pb, 0);              // Version
 
259
 
 
260
    put_byte(pb, 0x03);            // tag = ES_DescriptorTag
 
261
    put_be32(pb, esdsLength(track->vosLen+18+14));  // Length
 
262
    put_be16(pb, 0x0001);         // ID (= 1)
 
263
    put_byte(pb, 0x00);            // flags (= no flags)
 
264
 
 
265
// Decoderconfigdescriptor = 4
 
266
    put_byte(pb, 0x04);            // tag = DecoderConfigDescriptor
 
267
    put_be32(pb, esdsLength(track->vosLen+18));  // Length
 
268
    put_byte(pb, 0x20);            // Object type indication (Visual 14496-2)
 
269
    put_byte(pb, 0x11);            // flags (= Visualstream)
 
270
    put_byte(pb, 0x0);             // Buffersize DB (24 bits)
 
271
    put_be16(pb, 0x0dd2);          // Buffersize DB
 
272
 
 
273
    // TODO: find real values for these
 
274
    put_be32(pb, 0x0002e918);     // maxbitrate
 
275
    put_be32(pb, 0x00017e6b);     // avg bitrate
 
276
 
 
277
// Decoderspecific info Tag = 5
 
278
    put_byte(pb, 0x05);           // tag = Decoderspecific info
 
279
    put_be32(pb, esdsLength(track->vosLen));   // length
 
280
    put_buffer(pb, track->vosData, track->vosLen);
 
281
    
 
282
    put_byte(pb, 0x06);
 
283
    put_be32(pb, esdsLength(1));  // length
 
284
    put_byte(pb, 0x02);
 
285
    return track->vosLen+18+14+17;
 
286
}
 
287
 
 
288
static int mov_write_mp4v_tag(ByteIOContext *pb, MOVTrack* track) // Basic
 
289
{
 
290
    int pos = url_ftell(pb);
 
291
 
 
292
    put_be32(pb, 0);
 
293
    put_tag(pb, "mp4v");
 
294
    put_be32(pb, 0);  // Reserved
 
295
    put_be16(pb, 0);  // Reserved
 
296
    put_be16(pb, 1);  // Data-reference index
 
297
    put_be32(pb, 0);  // Reserved
 
298
    put_be32(pb, 0);  // Reserved
 
299
    put_be32(pb, 0);  // Reserved
 
300
    put_be32(pb, 0);  // Reserved
 
301
    put_be16(pb, track->enc->width);  // Width
 
302
    put_be16(pb, track->enc->height);  // Height
 
303
    put_be32(pb, 0x00480000);  // Reserved
 
304
    put_be32(pb, 0x00480000);  // Reserved
 
305
    put_be32(pb, 0);  // Reserved
 
306
    put_be16(pb, 1);  // Reserved
 
307
    put_be32(pb, 0);  // Reserved
 
308
    put_be32(pb, 0);  // Reserved
 
309
    put_be32(pb, 0);  // Reserved
 
310
    put_be32(pb, 0);  // Reserved
 
311
    put_be32(pb, 0);  // Reserved
 
312
    put_be32(pb, 0);  // Reserved
 
313
    put_be32(pb, 0);  // Reserved
 
314
    put_be32(pb, 0);  // Reserved
 
315
    put_be16(pb, 24); // Reserved
 
316
    put_be16(pb, 0xFFFF); // Reserved
 
317
    mov_write_esds_tag(pb, track);
 
318
    return updateSize(pb, pos);
 
319
}
 
320
 
 
321
static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
 
322
{
 
323
    int pos = url_ftell(pb);
 
324
    put_be32(pb, 0); /* size */
 
325
    put_tag(pb, "stsd");
 
326
    put_be32(pb, 0); /* version & flags */
 
327
    put_be32(pb, 1); /* entry count */
 
328
    if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
 
329
        if (track->enc->codec_id == CODEC_ID_H263) 
 
330
            mov_write_s263_tag(pb, track);
 
331
        else if (track->enc->codec_id == CODEC_ID_MPEG4) 
 
332
            mov_write_mp4v_tag(pb, track);
 
333
    }
 
334
    else if (track->enc->codec_type == CODEC_TYPE_AUDIO) {
 
335
        if (track->enc->codec_id == CODEC_ID_AMR_NB) 
 
336
            mov_write_samr_tag(pb, track);
 
337
    }
 
338
    return updateSize(pb, pos);
 
339
}
 
340
 
 
341
static int mov_write_stts_tag(ByteIOContext *pb, MOVTrack* track)
 
342
{
 
343
    put_be32(pb, 0x18); /* size */
 
344
    put_tag(pb, "stts");
 
345
    put_be32(pb, 0); /* version & flags */
 
346
    put_be32(pb, 1); /* entry count */
 
347
 
 
348
    put_be32(pb, track->samples); /* sample count */
 
349
    put_be32(pb, track->sampleDelta); /* sample delta */
 
350
    return 0x18;
 
351
}
 
352
 
 
353
static int mov_write_dref_tag(ByteIOContext *pb)
 
354
{
 
355
    put_be32(pb, 28); /* size */
 
356
    put_tag(pb, "dref");
 
357
    put_be32(pb, 0); /* version & flags */
 
358
    put_be32(pb, 1); /* entry count */
 
359
 
 
360
    put_be32(pb, 0xc); /* size */
 
361
    put_tag(pb, "url ");
 
362
    put_be32(pb, 1); /* version & flags */
 
363
 
 
364
    return 28;
 
365
}
 
366
 
 
367
static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
 
368
{
 
369
    int pos = url_ftell(pb);
 
370
    put_be32(pb, 0); /* size */
 
371
    put_tag(pb, "stbl");
 
372
    mov_write_stsd_tag(pb, track);
 
373
    mov_write_stts_tag(pb, track);
 
374
    if (track->enc->codec_type == CODEC_TYPE_VIDEO)
 
375
        mov_write_stss_tag(pb);
 
376
    mov_write_stsc_tag(pb, track);
 
377
    mov_write_stsz_tag(pb, track);
 
378
    mov_write_stco_tag(pb, track);
 
379
    return updateSize(pb, pos);
 
380
}
 
381
 
 
382
static int mov_write_dinf_tag(ByteIOContext *pb)
 
383
{
 
384
    int pos = url_ftell(pb);
 
385
    put_be32(pb, 0); /* size */
 
386
    put_tag(pb, "dinf");
 
387
    mov_write_dref_tag(pb);
 
388
    return updateSize(pb, pos);
 
389
}
 
390
 
 
391
static int mov_write_smhd_tag(ByteIOContext *pb)
 
392
{
 
393
    put_be32(pb, 16); /* size */
 
394
    put_tag(pb, "smhd");
 
395
    put_be32(pb, 0); /* version & flags */
 
396
    put_be16(pb, 0); /* reserved (balance, normally = 0) */
 
397
    put_be16(pb, 0); /* reserved */
 
398
    return 16;
 
399
}
 
400
 
 
401
static int mov_write_vmhd_tag(ByteIOContext *pb)
 
402
{
 
403
    put_be32(pb, 0x14); /* size (always 0x14) */
 
404
    put_tag(pb, "vmhd");
 
405
    put_be32(pb, 0x01); /* version & flags */
 
406
    put_be64(pb, 0); /* reserved (graphics mode = copy) */
 
407
    return 0x14;
 
408
}
 
409
 
 
410
static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
 
411
{
 
412
    int pos = url_ftell(pb);
 
413
    put_be32(pb, 0); /* size */
 
414
    put_tag(pb, "minf");
 
415
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
 
416
        mov_write_vmhd_tag(pb);
 
417
    else
 
418
        mov_write_smhd_tag(pb);
 
419
    mov_write_dinf_tag(pb);
 
420
    mov_write_stbl_tag(pb, track);
 
421
    return updateSize(pb, pos);
 
422
}
 
423
 
 
424
static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
 
425
{
 
426
    int size = 0;
 
427
    size = 45;
 
428
    put_be32(pb, size); /* size */
 
429
    put_tag(pb, "hdlr");
 
430
    put_be32(pb, 0); /* Version & flags */
 
431
    put_be32(pb, 0); /* reserved */
 
432
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
 
433
        put_tag(pb, "vide"); /* handler type */
 
434
    else
 
435
        put_tag(pb, "soun"); /* handler type */
 
436
    put_byte(pb, 0); /* reserved */
 
437
    put_byte(pb, 0); /* reserved */
 
438
    put_byte(pb, 0); /* reserved */
 
439
    put_byte(pb, 0); /* reserved */
 
440
    put_byte(pb, 0); /* reserved */
 
441
    put_byte(pb, 0); /* reserved */
 
442
    put_byte(pb, 0); /* reserved */
 
443
    put_byte(pb, 0); /* reserved */
 
444
    put_byte(pb, 0); /* reserved */
 
445
    put_byte(pb, 0); /* reserved */
 
446
    put_byte(pb, 0); /* reserved */
 
447
    put_byte(pb, 0); /* reserved */
 
448
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
 
449
        put_buffer(pb, "VideoHandler", 13);
 
450
    else
 
451
        put_buffer(pb, "SoundHandler", 13);
 
452
    return size;
 
453
}
 
454
 
 
455
static int mov_write_mdhd_tag(ByteIOContext *pb, MOVTrack* track)
 
456
{
 
457
    put_be32(pb, 32); /* size */
 
458
    put_tag(pb, "mdhd");
 
459
    put_be32(pb, 0); /* Version & flags */
 
460
    put_be32(pb, track->time); /* creation time */
 
461
    put_be32(pb, track->time); /* modification time */
 
462
    put_be32(pb, track->timescale); /* time scale */
 
463
 
 
464
    put_be32(pb, track->timescale*track->entry*track->frameDuration/globalTimescale); /* duration */
 
465
    put_be16(pb, 0); /* language, 0 = english */
 
466
    put_be16(pb, 0); /* reserved (quality) */
 
467
    return 32;
 
468
}
 
469
 
 
470
static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
 
471
{
 
472
    int pos = url_ftell(pb);
 
473
    put_be32(pb, 0); /* size */
 
474
    put_tag(pb, "mdia");
 
475
    mov_write_mdhd_tag(pb, track);
 
476
    mov_write_hdlr_tag(pb, track);
 
477
    mov_write_minf_tag(pb, track);
 
478
    return updateSize(pb, pos);
 
479
}
 
480
 
 
481
static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack* track)
 
482
{
 
483
    put_be32(pb, 0x5c); /* size (always 0x5c) */
 
484
    put_tag(pb, "tkhd");
 
485
    put_be32(pb, 1); /* version & flags (track enabled) */
 
486
    put_be32(pb, track->time); /* creation time */
 
487
    put_be32(pb, track->time); /* modification time */
 
488
    put_be32(pb, track->trackID); /* track-id */
 
489
    put_be32(pb, 0); /* reserved */
 
490
    put_be32(pb, track->entry*track->frameDuration); /* duration */
 
491
 
 
492
    put_be32(pb, 0); /* reserved */
 
493
    put_be32(pb, 0); /* reserved */
 
494
    put_be32(pb, 0x0); /* reserved (Layer & Alternate group) */
 
495
    /* Volume, only for audio */
 
496
    if(track->enc->codec_type == CODEC_TYPE_AUDIO)
 
497
        put_be16(pb, 0x0100);
 
498
    else
 
499
        put_be16(pb, 0);
 
500
    put_be16(pb, 0); /* reserved */
 
501
 
 
502
    /* Matrix structure */
 
503
    put_be32(pb, 0x00010000); /* reserved */
 
504
    put_be32(pb, 0x0); /* reserved */
 
505
    put_be32(pb, 0x0); /* reserved */
 
506
    put_be32(pb, 0x0); /* reserved */
 
507
    put_be32(pb, 0x00010000); /* reserved */
 
508
    put_be32(pb, 0x0); /* reserved */
 
509
    put_be32(pb, 0x0); /* reserved */
 
510
    put_be32(pb, 0x0); /* reserved */
 
511
    put_be32(pb, 0x40000000); /* reserved */
 
512
 
 
513
    /* Track width and height, for visual only */
 
514
    if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
 
515
        put_be32(pb, 0x01400000);
 
516
        put_be32(pb, 0x00f00000);
 
517
    }
 
518
    else {
 
519
        put_be32(pb, 0);
 
520
        put_be32(pb, 0);
 
521
    }
 
522
    return 0x5c;
 
523
}
 
524
 
 
525
static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
 
526
{
 
527
    int pos = url_ftell(pb);
 
528
    put_be32(pb, 0); /* size */
 
529
    put_tag(pb, "trak");
 
530
    mov_write_tkhd_tag(pb, track);
 
531
    mov_write_mdia_tag(pb, track);
 
532
    return updateSize(pb, pos);
 
533
}
 
534
 
 
535
/* TODO: Not sorted out, but not necessary either */
 
536
static int mov_write_iods_tag(ByteIOContext *pb, MOVContext *mov)
 
537
{
 
538
    put_be32(pb, 0x15); /* size */
 
539
    put_tag(pb, "iods");
 
540
    put_be32(pb, 0);    /* version & flags */
 
541
    put_be16(pb, 0x1007);
 
542
    put_byte(pb, 0);
 
543
    put_be16(pb, 0x4fff);
 
544
    put_be16(pb, 0xfffe);
 
545
    put_be16(pb, 0x01ff);
 
546
    return 0x15;
 
547
}
 
548
 
 
549
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
 
550
{
 
551
    int maxTrackID = 1, maxTrackLen = 0, i;
 
552
 
 
553
    put_be32(pb, 0x6c); /* size (always 0x6c) */
 
554
    put_tag(pb, "mvhd");
 
555
    put_be32(pb, 0); /* version & flags */
 
556
    put_be32(pb, mov->time); /* creation time */
 
557
    put_be32(pb, mov->time); /* modification time */
 
558
    put_be32(pb, mov->timescale); /* timescale */
 
559
    for (i=0; i<MAX_STREAMS; i++) {
 
560
        if(mov->tracks[i].entry > 0) {
 
561
            if(maxTrackLen < mov->tracks[i].entry*mov->tracks[i].frameDuration)
 
562
                maxTrackLen = mov->tracks[i].entry*mov->tracks[i].frameDuration;
 
563
            if(maxTrackID < mov->tracks[i].trackID)
 
564
                maxTrackID = mov->tracks[i].trackID;
 
565
        }
 
566
    }
 
567
    put_be32(pb, maxTrackLen); /* duration of longest track */
 
568
 
 
569
    put_be32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
 
570
    put_be16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
 
571
    put_be16(pb, 0); /* reserved */
 
572
    put_be32(pb, 0); /* reserved */
 
573
    put_be32(pb, 0); /* reserved */
 
574
 
 
575
    /* Matrix structure */
 
576
    put_be32(pb, 0x00010000); /* reserved */
 
577
    put_be32(pb, 0x0); /* reserved */
 
578
    put_be32(pb, 0x0); /* reserved */
 
579
    put_be32(pb, 0x0); /* reserved */
 
580
    put_be32(pb, 0x00010000); /* reserved */
 
581
    put_be32(pb, 0x0); /* reserved */
 
582
    put_be32(pb, 0x0); /* reserved */
 
583
    put_be32(pb, 0x0); /* reserved */
 
584
    put_be32(pb, 0x40000000); /* reserved */
 
585
 
 
586
    put_be32(pb, 0); /* reserved (preview time) */
 
587
    put_be32(pb, 0); /* reserved (preview duration) */
 
588
    put_be32(pb, 0); /* reserved (poster time) */
 
589
    put_be32(pb, 0); /* reserved (selection time) */
 
590
    put_be32(pb, 0); /* reserved (selection duration) */
 
591
    put_be32(pb, 0); /* reserved (current time) */
 
592
    put_be32(pb, maxTrackID+1); /* Next track id */
 
593
    return 0x6c;
 
594
}
 
595
 
 
596
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov)
 
597
{
 
598
    int pos, i;
 
599
    pos = url_ftell(pb);
 
600
    put_be32(pb, 0); /* size placeholder*/
 
601
    put_tag(pb, "moov");
 
602
    mov->timescale = globalTimescale;
 
603
 
 
604
    for (i=0; i<MAX_STREAMS; i++) {
 
605
        if(mov->tracks[i].entry > 0) {
 
606
            if(mov->tracks[i].enc->codec_type == CODEC_TYPE_VIDEO) {
 
607
                mov->tracks[i].timescale = globalTimescale;
 
608
                mov->tracks[i].sampleDelta = mov->tracks[i].frameDuration =
 
609
                    globalTimescale*mov->tracks[i].enc->frame_rate_base/mov->tracks[i].enc->frame_rate;
 
610
            }
 
611
            else if(mov->tracks[i].enc->codec_type == CODEC_TYPE_AUDIO) {
 
612
                /* If AMR, track timescale = 8000, AMR_WB = 16000 */
 
613
                if(mov->tracks[i].enc->codec_id == CODEC_ID_AMR_NB) {
 
614
                    mov->tracks[i].frameDuration = 20;
 
615
                    mov->tracks[i].sampleDelta = 160;
 
616
                    mov->tracks[i].timescale = 8000;
 
617
                }
 
618
                else {
 
619
                    mov->tracks[i].timescale = globalTimescale;
 
620
                    mov->tracks[i].frameDuration =
 
621
                    globalTimescale*mov->tracks[i].enc->frame_rate_base/mov->tracks[i].enc->frame_rate;
 
622
                }
 
623
            }
 
624
            mov->tracks[i].time = mov->time;
 
625
            mov->tracks[i].trackID = i+1;
 
626
        }
 
627
    }
 
628
 
 
629
    mov_write_mvhd_tag(pb, mov);
 
630
    //mov_write_iods_tag(pb, mov);
 
631
    for (i=0; i<MAX_STREAMS; i++) {
 
632
        if(mov->tracks[i].entry > 0) {
 
633
            mov_write_trak_tag(pb, &(mov->tracks[i]));
 
634
        }
 
635
    }
 
636
 
 
637
    return updateSize(pb, pos);
 
638
}
 
639
 
 
640
int mov_write_mdat_tag(ByteIOContext *pb, MOVTrack* track)
 
641
{
 
642
    track->mdat_pos = url_ftell(pb); 
 
643
    put_be32(pb, 0); /* size placeholder*/
 
644
    put_tag(pb, "mdat");
 
645
    return 0;
 
646
}
 
647
 
 
648
/* TODO: This needs to be more general */
 
649
int mov_write_ftyp_tag(ByteIOContext *pb)
 
650
{
 
651
    put_be32(pb, 0x14 ); /* size */
 
652
    put_tag(pb, "ftyp");
 
653
    put_tag(pb, "3gp4");
 
654
    put_be32(pb, 0x200 );
 
655
    put_tag(pb, "3gp4");
 
656
    return 0x14;
 
657
}
 
658
 
 
659
static int mov_write_header(AVFormatContext *s)
 
660
{
 
661
    ByteIOContext *pb = &s->pb;
 
662
 
 
663
    /* write ftyp */
 
664
    mov_write_ftyp_tag(pb);
 
665
    
 
666
    put_flush_packet(pb);
 
667
 
 
668
    return 0;
 
669
}
 
670
 
 
671
static int Timestamp() {
 
672
    time_t ltime;
 
673
    time ( &ltime );
 
674
    return ltime+(24107*86400);
 
675
}
 
676
 
 
677
static int mov_write_packet(AVFormatContext *s, int stream_index,
 
678
                            const uint8_t *buf, int size, int64_t pts)
 
679
{
 
680
    MOVContext *mov = s->priv_data;
 
681
    ByteIOContext *pb = &s->pb;
 
682
    AVCodecContext *enc;
 
683
    int cl, id;
 
684
 
 
685
    enc = &s->streams[stream_index]->codec;
 
686
    if (!url_is_streamed(&s->pb)) {
 
687
        MOVTrack* trk = &mov->tracks[stream_index];
 
688
        int sampleCount = 0;
 
689
 
 
690
        /* We must find out how many AMR blocks there are in one packet */
 
691
        if(enc->codec_id == CODEC_ID_AMR_NB) {
 
692
            static uint16_t packed_size[16] = {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 0};             
 
693
            int len = 0;
 
694
 
 
695
            while(len < size && sampleCount < 100) {
 
696
                len += packed_size[(buf[len] >> 3) & 0x0F];
 
697
                sampleCount++;
 
698
            }
 
699
        }
 
700
        
 
701
        if(enc->codec_id == CODEC_ID_MPEG4 &&
 
702
           trk->vosLen == 0)
 
703
        {
 
704
            assert(enc->extradata_size);
 
705
 
 
706
            trk->vosLen = enc->extradata_size;
 
707
            trk->vosData = av_malloc(trk->vosLen);
 
708
            memcpy(trk->vosData, enc->extradata, trk->vosLen);
 
709
        }
 
710
 
 
711
        cl = trk->entry / MOV_INDEX_CLUSTER_SIZE;
 
712
        id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
 
713
 
 
714
        if (trk->ents_allocated <= trk->entry) {
 
715
            trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*)); 
 
716
            if (!trk->cluster)
 
717
                return -1;
 
718
            trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
 
719
            if (!trk->cluster[cl])
 
720
                return -1;
 
721
            trk->ents_allocated += MOV_INDEX_CLUSTER_SIZE;
 
722
        }
 
723
        if(stream_index == 0 && trk->entry == 0) {
 
724
            mov_write_mdat_tag(pb, trk);
 
725
            mov->time = Timestamp();
 
726
        }
 
727
        
 
728
        trk->cluster[cl][id].pos = url_ftell(pb) - mov->movi_list;
 
729
        trk->cluster[cl][id].len = size;
 
730
        trk->cluster[cl][id].entries = sampleCount;
 
731
        trk->enc = enc;
 
732
        trk->entry++;
 
733
        if(sampleCount == 0)
 
734
            trk->samples++;
 
735
        else
 
736
            trk->samples += sampleCount;
 
737
        trk->mdat_size += size;
 
738
    }
 
739
    put_buffer(pb, buf, size);
 
740
 
 
741
    put_flush_packet(pb);
 
742
    return 0;
 
743
}
 
744
 
 
745
static int mov_write_trailer(AVFormatContext *s)
 
746
{
 
747
    MOVContext *mov = s->priv_data;
 
748
    ByteIOContext *pb = &s->pb;
 
749
    int res = 0;
 
750
    int i, j;
 
751
    offset_t file_size;
 
752
 
 
753
    file_size = url_ftell(pb);
 
754
    j = 0;
 
755
 
 
756
    /* Write size of mdat tag */
 
757
    for (i=0; i<MAX_STREAMS; i++) {
 
758
        if(mov->tracks[i].ents_allocated > 0) {
 
759
            j += mov->tracks[i].mdat_size;
 
760
        }
 
761
    }
 
762
    url_fseek(pb, mov->tracks[0].mdat_pos, SEEK_SET);
 
763
    put_be32(pb, j+8);
 
764
    url_fseek(pb, file_size, SEEK_SET);
 
765
 
 
766
    mov_write_moov_tag(pb, mov);
 
767
 
 
768
    for (i=0; i<MAX_STREAMS; i++) {
 
769
        for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
 
770
            av_free(mov->tracks[i].cluster[j]);
 
771
        }
 
772
        av_free(mov->tracks[i].cluster);
 
773
        mov->tracks[i].cluster = NULL;
 
774
        mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
 
775
    }
 
776
    put_flush_packet(pb);
 
777
 
 
778
    return res;
 
779
}
 
780
 
 
781
static AVOutputFormat mov_oformat = {
 
782
    "mov",
 
783
    "mov format",
 
784
    NULL,
 
785
    "mov",
 
786
    sizeof(MOVContext),
 
787
    CODEC_ID_MP2,
 
788
    CODEC_ID_MPEG4,
 
789
    mov_write_header,
 
790
    mov_write_packet,
 
791
    mov_write_trailer,
 
792
};
 
793
 
 
794
static AVOutputFormat _3gp_oformat = {
 
795
    "3gp",
 
796
    "3gp format",
 
797
    NULL,
 
798
    "3gp",
 
799
    sizeof(MOVContext),
 
800
    CODEC_ID_AMR_NB,
 
801
    CODEC_ID_H263,
 
802
    mov_write_header,
 
803
    mov_write_packet,
 
804
    mov_write_trailer,
 
805
};
 
806
 
 
807
static AVOutputFormat mp4_oformat = {
 
808
    "mp4",
 
809
    "mp4 format",
 
810
    NULL,
 
811
    "mp4",
 
812
    sizeof(MOVContext),
 
813
    CODEC_ID_AAC,
 
814
    CODEC_ID_MPEG4,
 
815
    mov_write_header,
 
816
    mov_write_packet,
 
817
    mov_write_trailer,
 
818
};
 
819
 
 
820
int movenc_init(void)
 
821
{
 
822
    av_register_output_format(&mov_oformat);
 
823
    av_register_output_format(&_3gp_oformat);
 
824
    av_register_output_format(&mp4_oformat);
 
825
    return 0;
 
826
}