~ubuntu-branches/ubuntu/edgy/gstreamer0.10-ffmpeg/edgy

« back to all changes in this revision

Viewing changes to gst-libs/ext/ffmpeg/libavformat/movenc.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2006-04-01 16:13:43 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20060401161343-n621cgjlujio0otg
Tags: upstream-0.10.1
Import upstream version 0.10.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *
16
16
 * You should have received a copy of the GNU Lesser General Public
17
17
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
19
 */
20
20
#include "avformat.h"
21
21
#include "avi.h"
22
22
#include "avio.h"
 
23
#include "mov.h"
23
24
 
24
25
#undef NDEBUG
25
26
#include <assert.h>
30
31
#define MODE_MP4 0
31
32
#define MODE_MOV 1
32
33
#define MODE_3GP 2
33
 
#define MODE_PSP 3 // example working PSP command line: 
 
34
#define MODE_PSP 3 // example working PSP command line:
34
35
// ffmpeg -i testinput.avi  -f psp -r 14.985 -s 320x240 -b 768 -ar 24000 -ab 32 M4V00001.MP4
35
36
#define MODE_3G2 4
36
37
 
37
38
typedef struct MOVIentry {
38
 
    unsigned int flags, pos, size;
 
39
    unsigned int flags, size;
 
40
    uint64_t     pos;
39
41
    unsigned int samplesInChunk;
40
42
    char         key_frame;
41
43
    unsigned int entries;
44
46
typedef struct MOVIndex {
45
47
    int         mode;
46
48
    int         entry;
47
 
    int         mdat_size;
 
49
    uint64_t    mdat_size;
48
50
    int         ents_allocated;
49
51
    long        timescale;
50
52
    long        time;
52
54
    long        sampleCount;
53
55
    long        sampleDuration;
54
56
    int         hasKeyframes;
 
57
    int         language;
55
58
    int         trackID;
56
59
    AVCodecContext *enc;
57
60
 
72
75
 
73
76
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track);
74
77
 
75
 
const CodecTag ff_mov_obj_type[] = {
76
 
    { CODEC_ID_MPEG4     ,  32 },
77
 
    { CODEC_ID_AAC       ,  64 },
78
 
    { CODEC_ID_MPEG1VIDEO, 106 },
79
 
    { CODEC_ID_MPEG2VIDEO,  96 },//mpeg2 profiles
80
 
    { CODEC_ID_MP2       , 107 },//FIXME mpeg2 mpeg audio -> 105
81
 
    { CODEC_ID_MP3       , 107 },//FIXME mpeg2 mpeg audio -> 105
82
 
    { CODEC_ID_H264      ,  33 },
83
 
    { CODEC_ID_H263      , 242 },
84
 
    { CODEC_ID_H261      , 243 },
85
 
    { CODEC_ID_MJPEG     , 108 },
86
 
    { CODEC_ID_PCM_S16LE , 224 },
87
 
    { CODEC_ID_VORBIS    , 225 },
88
 
    { CODEC_ID_AC3       , 226 },
89
 
    { CODEC_ID_PCM_ALAW  , 227 },
90
 
    { CODEC_ID_PCM_MULAW , 228 },
91
 
    { CODEC_ID_PCM_S16BE , 230 },
92
 
    { 0,0  },
93
 
};
 
78
/* output language code from iso639 language name */
 
79
extern int ff_mov_iso639_to_lang(const char *lang, int mp4);
94
80
 
95
81
//FIXME supprt 64bit varaint with wide placeholders
96
 
static int updateSize (ByteIOContext *pb, int pos)
 
82
static offset_t updateSize (ByteIOContext *pb, offset_t pos)
97
83
{
98
 
    long curpos = url_ftell(pb);
 
84
    offset_t curpos = url_ftell(pb);
99
85
    url_fseek(pb, pos, SEEK_SET);
100
86
    put_be32(pb, curpos - pos); /* rewrite size */
101
87
    url_fseek(pb, curpos, SEEK_SET);
107
93
static int mov_write_stco_tag(ByteIOContext *pb, MOVTrack* track)
108
94
{
109
95
    int i;
110
 
    int pos = url_ftell(pb);
 
96
    int mode64 = 0; //   use 32 bit size variant if possible
 
97
    offset_t pos = url_ftell(pb);
111
98
    put_be32(pb, 0); /* size */
112
 
    put_tag(pb, "stco");
 
99
    if (pos > UINT32_MAX) {
 
100
        mode64 = 1;
 
101
        put_tag(pb, "co64");
 
102
    } else
 
103
        put_tag(pb, "stco");
113
104
    put_be32(pb, 0); /* version & flags */
114
105
    put_be32(pb, track->entry); /* entry count */
115
106
    for (i=0; i<track->entry; i++) {
116
107
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
117
108
        int id = i % MOV_INDEX_CLUSTER_SIZE;
118
 
        put_be32(pb, track->cluster[cl][id].pos);
 
109
        if(mode64 == 1)
 
110
            put_be64(pb, track->cluster[cl][id].pos);
 
111
        else
 
112
            put_be32(pb, track->cluster[cl][id].pos);
119
113
    }
120
114
    return updateSize (pb, pos);
121
115
}
126
120
    int equalChunks = 1;
127
121
    int i, j, entries = 0, tst = -1, oldtst = -1;
128
122
 
129
 
    int pos = url_ftell(pb);
 
123
    offset_t pos = url_ftell(pb);
130
124
    put_be32(pb, 0); /* size */
131
125
    put_tag(pb, "stsz");
132
126
    put_be32(pb, 0); /* version & flags */
143
137
    }
144
138
    if (equalChunks) {
145
139
        int sSize = track->cluster[0][0].size/track->cluster[0][0].entries;
146
 
        put_be32(pb, sSize); // sample size 
 
140
        put_be32(pb, sSize); // sample size
147
141
        put_be32(pb, entries); // sample count
148
142
    }
149
143
    else {
150
 
        put_be32(pb, 0); // sample size 
151
 
        put_be32(pb, entries); // sample count 
 
144
        put_be32(pb, 0); // sample size
 
145
        put_be32(pb, entries); // sample count
152
146
        for (i=0; i<track->entry; i++) {
153
147
            int cl = i / MOV_INDEX_CLUSTER_SIZE;
154
148
            int id = i % MOV_INDEX_CLUSTER_SIZE;
164
158
/* Sample to chunk atom */
165
159
static int mov_write_stsc_tag(ByteIOContext *pb, MOVTrack* track)
166
160
{
167
 
    int index = 0, oldval = -1, i, entryPos, curpos;
 
161
    int index = 0, oldval = -1, i;
 
162
    offset_t entryPos, curpos;
168
163
 
169
 
    int pos = url_ftell(pb);
 
164
    offset_t pos = url_ftell(pb);
170
165
    put_be32(pb, 0); /* size */
171
166
    put_tag(pb, "stsc");
172
 
    put_be32(pb, 0); // version & flags 
 
167
    put_be32(pb, 0); // version & flags
173
168
    entryPos = url_ftell(pb);
174
 
    put_be32(pb, track->entry); // entry count 
 
169
    put_be32(pb, track->entry); // entry count
175
170
    for (i=0; i<track->entry; i++) {
176
171
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
177
172
        int id = i % MOV_INDEX_CLUSTER_SIZE;
178
173
        if(oldval != track->cluster[cl][id].samplesInChunk)
179
174
        {
180
 
            put_be32(pb, i+1); // first chunk 
 
175
            put_be32(pb, i+1); // first chunk
181
176
            put_be32(pb, track->cluster[cl][id].samplesInChunk); // samples per chunk
182
 
            put_be32(pb, 0x1); // sample description index 
 
177
            put_be32(pb, 0x1); // sample description index
183
178
            oldval = track->cluster[cl][id].samplesInChunk;
184
179
            index++;
185
180
        }
186
181
    }
187
182
    curpos = url_ftell(pb);
188
183
    url_fseek(pb, entryPos, SEEK_SET);
189
 
    put_be32(pb, index); // rewrite size 
 
184
    put_be32(pb, index); // rewrite size
190
185
    url_fseek(pb, curpos, SEEK_SET);
191
186
 
192
187
    return updateSize (pb, pos);
195
190
/* Sync sample atom */
196
191
static int mov_write_stss_tag(ByteIOContext *pb, MOVTrack* track)
197
192
{
198
 
    long curpos;
199
 
    int i, index = 0, entryPos;
200
 
    int pos = url_ftell(pb);
201
 
    put_be32(pb, 0); // size 
 
193
    offset_t curpos, entryPos;
 
194
    int i, index = 0;
 
195
    offset_t pos = url_ftell(pb);
 
196
    put_be32(pb, 0); // size
202
197
    put_tag(pb, "stss");
203
 
    put_be32(pb, 0); // version & flags 
 
198
    put_be32(pb, 0); // version & flags
204
199
    entryPos = url_ftell(pb);
205
 
    put_be32(pb, track->entry); // entry count 
 
200
    put_be32(pb, track->entry); // entry count
206
201
    for (i=0; i<track->entry; i++) {
207
202
        int cl = i / MOV_INDEX_CLUSTER_SIZE;
208
203
        int id = i % MOV_INDEX_CLUSTER_SIZE;
213
208
    }
214
209
    curpos = url_ftell(pb);
215
210
    url_fseek(pb, entryPos, SEEK_SET);
216
 
    put_be32(pb, index); // rewrite size 
 
211
    put_be32(pb, index); // rewrite size
217
212
    url_fseek(pb, curpos, SEEK_SET);
218
213
    return updateSize (pb, pos);
219
214
}
234
229
 
235
230
static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack* track)
236
231
{
237
 
    int pos = url_ftell(pb);
 
232
    offset_t pos = url_ftell(pb);
238
233
 
239
234
    put_be32(pb, 0);     /* size */
240
235
    put_tag(pb, "wave");
276
271
 
277
272
static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
278
273
{
279
 
    int pos = url_ftell(pb);
 
274
    offset_t pos = url_ftell(pb);
280
275
    int tag;
281
 
    
 
276
 
282
277
    put_be32(pb, 0); /* size */
283
278
 
284
279
    tag = track->enc->codec_tag;
287
282
    // if no mac fcc found, try with Microsoft tags
288
283
    if (!tag)
289
284
    {
290
 
        int tmp = codec_get_tag(codec_wav_tags, track->enc->codec_id);
 
285
        int tmp = codec_get_tag(codec_wav_tags, track->enc->codec_id);
291
286
        tag = MKTAG('m', 's', ((tmp >> 8) & 0xff), (tmp & 0xff));
292
287
    }
293
288
    put_le32(pb, tag); // store it byteswapped
359
354
    put_be32(pb, 0x5);
360
355
    put_be32(pb, 0xe2c0211d);
361
356
    put_be32(pb, 0xc0000000);
362
 
    put_byte(pb, 0);   
 
357
    put_byte(pb, 0);
363
358
    return 0x15;
364
359
}
365
360
 
383
378
    len = size;
384
379
    vals[3] = (uint8_t)(len & 0x7f);
385
380
    len >>= 7;
386
 
    vals[2] = (uint8_t)((len & 0x7f) | 0x80); 
 
381
    vals[2] = (uint8_t)((len & 0x7f) | 0x80);
387
382
    len >>= 7;
388
 
    vals[1] = (uint8_t)((len & 0x7f) | 0x80); 
 
383
    vals[1] = (uint8_t)((len & 0x7f) | 0x80);
389
384
    len >>= 7;
390
385
    vals[0] = (uint8_t)((len & 0x7f) | 0x80);
391
386
 
418
413
static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic
419
414
{
420
415
    int decoderSpecificInfoLen;
421
 
    int pos = url_ftell(pb);
422
 
    void *vosDataBackup=track->vosData;
423
 
    int vosLenBackup=track->vosLen;
424
 
    
425
 
    // we should be able to have these passed in, via vosData, then we wouldn't need to attack this routine at all
426
 
    static const char PSPAACData[]={0x13,0x10};
427
 
    static const char PSPMP4Data[]={0x00,0x00,0x01,0xB0,0x03,0x00,0x00,0x01,0xB5,0x09,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x20,0x00,0x84,0x5D,0x4C,0x28,0x50,0x20,0xF0,0xA3,0x1F };
428
 
    
429
 
    
430
 
    if (track->mode == MODE_PSP)  // fails on psp if this is not here
431
 
    {
432
 
        if (track->enc->codec_id == CODEC_ID_AAC)
433
 
        {
434
 
            track->vosLen = 2;
435
 
            track->vosData = (uint8_t *) PSPAACData;
436
 
        }
437
 
 
438
 
        if (track->enc->codec_id == CODEC_ID_MPEG4)
439
 
        {
440
 
            track->vosLen = 28;
441
 
            track->vosData = (uint8_t *) PSPMP4Data;
442
 
        }
443
 
    }
 
416
    offset_t pos = url_ftell(pb);
444
417
 
445
418
    decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0;
446
419
 
483
456
        put_buffer(pb, track->vosData, track->vosLen);
484
457
    }
485
458
 
486
 
    track->vosData = vosDataBackup;
487
 
    track->vosLen = vosLenBackup;
488
459
 
489
460
    // SL descriptor
490
461
    putDescr(pb, 0x06, 1);
504
475
 
505
476
static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track)
506
477
{
507
 
    int pos = url_ftell(pb);
 
478
    offset_t pos = url_ftell(pb);
508
479
    char compressor_name[32];
509
480
    int tag;
510
481
 
515
486
    tag = codec_get_tag(codec_movvideo_tags, track->enc->codec_id);
516
487
    // if no mac fcc found, try with Microsoft tags
517
488
    if (!tag)
518
 
        tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
 
489
        tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id);
519
490
    put_le32(pb, tag); // store it byteswapped
520
491
 
521
492
    put_be32(pb, 0); /* Reserved */
538
509
    put_be32(pb, 0x00480000); /* Vertical resolution 72dpi */
539
510
    put_be32(pb, 0); /* Data size (= 0) */
540
511
    put_be16(pb, 1); /* Frame count (= 1) */
541
 
    
 
512
 
542
513
    memset(compressor_name,0,32);
543
514
    if (track->enc->codec && track->enc->codec->name)
544
515
        strncpy(compressor_name,track->enc->codec->name,31);
545
516
    put_byte(pb, strlen(compressor_name));
546
517
    put_buffer(pb, compressor_name, 31);
547
 
    
 
518
 
548
519
    put_be16(pb, 0x18); /* Reserved */
549
520
    put_be16(pb, 0xffff); /* Reserved */
550
521
    if(track->enc->codec_id == CODEC_ID_MPEG4)
552
523
    else if(track->enc->codec_id == CODEC_ID_H263)
553
524
        mov_write_d263_tag(pb);
554
525
    else if(track->enc->codec_id == CODEC_ID_SVQ3)
555
 
        mov_write_svq3_tag(pb);    
 
526
        mov_write_svq3_tag(pb);
556
527
 
557
528
    return updateSize (pb, pos);
558
529
}
559
530
 
560
531
static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack* track)
561
532
{
562
 
    int pos = url_ftell(pb);
 
533
    offset_t pos = url_ftell(pb);
563
534
    put_be32(pb, 0); /* size */
564
535
    put_tag(pb, "stsd");
565
536
    put_be32(pb, 0); /* version & flags */
601
572
 
602
573
static int mov_write_stbl_tag(ByteIOContext *pb, MOVTrack* track)
603
574
{
604
 
    int pos = url_ftell(pb);
 
575
    offset_t pos = url_ftell(pb);
605
576
    put_be32(pb, 0); /* size */
606
577
    put_tag(pb, "stbl");
607
578
    mov_write_stsd_tag(pb, track);
617
588
 
618
589
static int mov_write_dinf_tag(ByteIOContext *pb)
619
590
{
620
 
    int pos = url_ftell(pb);
 
591
    offset_t pos = url_ftell(pb);
621
592
    put_be32(pb, 0); /* size */
622
593
    put_tag(pb, "dinf");
623
594
    mov_write_dref_tag(pb);
646
617
static int mov_write_hdlr_tag(ByteIOContext *pb, MOVTrack* track)
647
618
{
648
619
    char *descr, *hdlr, *hdlr_type;
649
 
    int pos = url_ftell(pb);
650
 
    
 
620
    offset_t pos = url_ftell(pb);
 
621
 
651
622
    if (!track) { /* no media --> data handler */
652
 
        hdlr = "dhlr";
653
 
        hdlr_type = "url ";
654
 
        descr = "DataHandler";
 
623
        hdlr = "dhlr";
 
624
        hdlr_type = "url ";
 
625
        descr = "DataHandler";
655
626
    } else {
656
 
        hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
657
 
        if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
658
 
            hdlr_type = "vide";
659
 
            descr = "VideoHandler";
660
 
        } else {
661
 
            hdlr_type = "soun";
662
 
            descr = "SoundHandler";
663
 
        }
 
627
        hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
 
628
        if (track->enc->codec_type == CODEC_TYPE_VIDEO) {
 
629
            hdlr_type = "vide";
 
630
            descr = "VideoHandler";
 
631
        } else {
 
632
            hdlr_type = "soun";
 
633
            descr = "SoundHandler";
 
634
        }
664
635
    }
665
 
    
 
636
 
666
637
    put_be32(pb, 0); /* size */
667
638
    put_tag(pb, "hdlr");
668
639
    put_be32(pb, 0); /* Version & flags */
678
649
 
679
650
static int mov_write_minf_tag(ByteIOContext *pb, MOVTrack* track)
680
651
{
681
 
    int pos = url_ftell(pb);
 
652
    offset_t pos = url_ftell(pb);
682
653
    put_be32(pb, 0); /* size */
683
654
    put_tag(pb, "minf");
684
655
    if(track->enc->codec_type == CODEC_TYPE_VIDEO)
699
670
    put_be32(pb, 0); /* Version & flags */
700
671
    put_be32(pb, track->time); /* creation time */
701
672
    put_be32(pb, track->time); /* modification time */
702
 
    put_be32(pb, track->timescale); /* time scale (sample rate for audio) */ 
 
673
    put_be32(pb, track->timescale); /* time scale (sample rate for audio) */
703
674
    put_be32(pb, track->trackDuration); /* duration */
704
 
    put_be16(pb, 0); /* language, 0 = english */
 
675
    put_be16(pb, track->language); /* language */
705
676
    put_be16(pb, 0); /* reserved (quality) */
706
677
    return 32;
707
678
}
708
679
 
709
680
static int mov_write_mdia_tag(ByteIOContext *pb, MOVTrack* track)
710
681
{
711
 
    int pos = url_ftell(pb);
 
682
    offset_t pos = url_ftell(pb);
712
683
    put_be32(pb, 0); /* size */
713
684
    put_tag(pb, "mdia");
714
685
    mov_write_mdhd_tag(pb, track);
801
772
 
802
773
static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack* track)
803
774
{
804
 
    int pos = url_ftell(pb);
 
775
    offset_t pos = url_ftell(pb);
805
776
    put_be32(pb, 0); /* size */
806
777
    put_tag(pb, "trak");
807
778
    mov_write_tkhd_tag(pb, track);
808
 
    if (track->mode == MODE_PSP) 
 
779
    if (track->mode == MODE_PSP)
809
780
        mov_write_edts_tag(pb, track);  // PSP Movies require edts box
810
781
    mov_write_mdia_tag(pb, track);
811
 
    if (track->mode == MODE_PSP) 
 
782
    if (track->mode == MODE_PSP)
812
783
        mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
813
784
    return updateSize(pb, pos);
814
785
}
831
802
 
832
803
static int mov_write_mvhd_tag(ByteIOContext *pb, MOVContext *mov)
833
804
{
834
 
    int maxTrackID = 1, maxTrackLen = 0, i;
835
 
    int64_t maxTrackLenTemp;
 
805
    int maxTrackID = 1, i;
 
806
    int64_t maxTrackLenTemp, maxTrackLen = 0;
836
807
 
837
808
    put_be32(pb, 0x6c); /* size (always 0x6c) */
838
809
    put_tag(pb, "mvhd");
881
852
static int mov_write_itunes_hdlr_tag(ByteIOContext *pb, MOVContext* mov,
882
853
                                     AVFormatContext *s)
883
854
{
884
 
    int pos = url_ftell(pb);
 
855
    offset_t pos = url_ftell(pb);
885
856
    put_be32(pb, 0); /* size */
886
857
    put_tag(pb, "hdlr");
887
858
    put_be32(pb, 0);
898
869
static int mov_write_string_data_tag(ByteIOContext *pb, MOVContext* mov,
899
870
                                     AVFormatContext *s, const char *data)
900
871
{
901
 
    int pos = url_ftell(pb);
 
872
    offset_t pos = url_ftell(pb);
902
873
    put_be32(pb, 0); /* size */
903
874
    put_tag(pb, "data");
904
875
    put_be32(pb, 1);
913
884
{
914
885
    int size = 0;
915
886
    if ( s->title[0] ) {
916
 
        int pos = url_ftell(pb);
 
887
        offset_t pos = url_ftell(pb);
917
888
        put_be32(pb, 0); /* size */
918
889
        put_tag(pb, "\251nam");
919
890
        mov_write_string_data_tag(pb, mov, s, s->title);
928
899
{
929
900
    int size = 0;
930
901
    if ( s->author[0] ) {
931
 
        int pos = url_ftell(pb);
 
902
        offset_t pos = url_ftell(pb);
932
903
        put_be32(pb, 0); /* size */
933
904
        put_tag(pb, "\251ART");
934
905
        // we use the author here as this is the only thing that we have...
944
915
{
945
916
    int size = 0;
946
917
    if ( s->author[0] ) {
947
 
        int pos = url_ftell(pb);
 
918
        offset_t pos = url_ftell(pb);
948
919
        put_be32(pb, 0); /* size */
949
920
        put_tag(pb, "\251wrt");
950
921
        mov_write_string_data_tag(pb, mov, s, s->author);
959
930
{
960
931
    int size = 0;
961
932
    if ( s->album[0] ) {
962
 
        int pos = url_ftell(pb);
 
933
        offset_t pos = url_ftell(pb);
963
934
        put_be32(pb, 0); /* size */
964
935
        put_tag(pb, "\251alb");
965
936
        mov_write_string_data_tag(pb, mov, s, s->album);
975
946
    char year[5];
976
947
    int size = 0;
977
948
    if ( s->year ) {
978
 
        int pos = url_ftell(pb);
 
949
        offset_t pos = url_ftell(pb);
979
950
        put_be32(pb, 0); /* size */
980
951
        put_tag(pb, "\251day");
981
952
        snprintf(year, 5, "%04d", s->year);
989
960
static int mov_write_too_tag(ByteIOContext *pb, MOVContext* mov,
990
961
                             AVFormatContext *s)
991
962
{
992
 
    int pos = url_ftell(pb);
 
963
    offset_t pos = url_ftell(pb);
993
964
    put_be32(pb, 0); /* size */
994
965
    put_tag(pb, "\251too");
995
966
    mov_write_string_data_tag(pb, mov, s, LIBAVFORMAT_IDENT);
1002
973
{
1003
974
    int size = 0;
1004
975
    if ( s->comment[0] ) {
1005
 
        int pos = url_ftell(pb);
 
976
        offset_t pos = url_ftell(pb);
1006
977
        put_be32(pb, 0); /* size */
1007
978
        put_tag(pb, "\251cmt");
1008
979
        mov_write_string_data_tag(pb, mov, s, s->comment);
1017
988
{
1018
989
    int size = 0;
1019
990
    if ( s->genre[0] ) {
1020
 
        int pos = url_ftell(pb);
 
991
        offset_t pos = url_ftell(pb);
1021
992
        put_be32(pb, 0); /* size */
1022
993
        put_tag(pb, "\251gen");
1023
994
        mov_write_string_data_tag(pb, mov, s, s->genre);
1032
1003
{
1033
1004
    int size = 0;
1034
1005
    if ( s->track ) {
1035
 
        int pos = url_ftell(pb);
 
1006
        offset_t pos = url_ftell(pb);
1036
1007
        put_be32(pb, 0); /* size */
1037
1008
        put_tag(pb, "trkn");
1038
1009
        {
1039
 
            int pos = url_ftell(pb);
 
1010
            offset_t pos = url_ftell(pb);
1040
1011
            put_be32(pb, 0); /* size */
1041
1012
            put_tag(pb, "data");
1042
1013
            put_be32(pb, 0);        // 8 bytes empty
1056
1027
static int mov_write_ilst_tag(ByteIOContext *pb, MOVContext* mov,
1057
1028
                              AVFormatContext *s)
1058
1029
{
1059
 
    int pos = url_ftell(pb);
 
1030
    offset_t pos = url_ftell(pb);
1060
1031
    put_be32(pb, 0); /* size */
1061
1032
    put_tag(pb, "ilst");
1062
1033
    mov_write_nam_tag(pb, mov, s);
1078
1049
    int size = 0;
1079
1050
 
1080
1051
    // only save meta tag if required
1081
 
    if ( s->title[0] || s->author[0] || s->album[0] || s->year || 
 
1052
    if ( s->title[0] || s->author[0] || s->album[0] || s->year ||
1082
1053
         s->comment[0] || s->genre[0] || s->track ) {
1083
 
        int pos = url_ftell(pb);
 
1054
        offset_t pos = url_ftell(pb);
1084
1055
        put_be32(pb, 0); /* size */
1085
1056
        put_tag(pb, "meta");
1086
1057
        put_be32(pb, 0);
1090
1061
    }
1091
1062
    return size;
1092
1063
}
1093
 
    
 
1064
 
1094
1065
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
1095
1066
                              AVFormatContext *s)
1096
1067
{
1097
 
    int pos = url_ftell(pb);
 
1068
    offset_t pos = url_ftell(pb);
1098
1069
    int i;
1099
1070
 
1100
1071
    put_be32(pb, 0); /* size */
1108
1079
        if(mov->tracks[i].entry <= 0) continue;
1109
1080
        if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
1110
1081
            mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
1111
 
            int pos = url_ftell(pb);
 
1082
            offset_t pos = url_ftell(pb);
1112
1083
            put_be32(pb, 0); /* size */
1113
1084
            put_tag(pb, "\251req");
1114
1085
            put_be16(pb, sizeof("QuickTime 6.0 or greater") - 1);
1123
1094
    /* Encoder */
1124
1095
    if(mov->tracks[0].enc && !(mov->tracks[0].enc->flags & CODEC_FLAG_BITEXACT))
1125
1096
    {
1126
 
        int pos = url_ftell(pb);
 
1097
        offset_t pos = url_ftell(pb);
1127
1098
        put_be32(pb, 0); /* size */
1128
1099
        put_tag(pb, "\251enc");
1129
1100
        put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
1134
1105
 
1135
1106
    if( s->title[0] )
1136
1107
    {
1137
 
        int pos = url_ftell(pb);
 
1108
        offset_t pos = url_ftell(pb);
1138
1109
        put_be32(pb, 0); /* size */
1139
1110
        put_tag(pb, "\251nam");
1140
1111
        put_be16(pb, strlen(s->title)); /* string length */
1145
1116
 
1146
1117
    if( s->author[0] )
1147
1118
    {
1148
 
        int pos = url_ftell(pb);
 
1119
        offset_t pos = url_ftell(pb);
1149
1120
        put_be32(pb, 0); /* size */
1150
1121
        put_tag(pb, /*"\251aut"*/ "\251day" );
1151
1122
        put_be16(pb, strlen(s->author)); /* string length */
1156
1127
 
1157
1128
    if( s->comment[0] )
1158
1129
    {
1159
 
        int pos = url_ftell(pb);
 
1130
        offset_t pos = url_ftell(pb);
1160
1131
        put_be32(pb, 0); /* size */
1161
1132
        put_tag(pb, "\251des");
1162
1133
        put_be16(pb, strlen(s->comment)); /* string length */
1168
1139
    return updateSize(pb, pos);
1169
1140
}
1170
1141
 
 
1142
 
 
1143
static size_t ascii_to_wc (ByteIOContext *pb, char *b, size_t n)
 
1144
{
 
1145
    size_t i;
 
1146
    unsigned char c;
 
1147
    for (i = 0; i < n - 1; i++) {
 
1148
        c = b[i];
 
1149
        if (! (0x20 <= c && c <= 0x7f ))
 
1150
            c = 0x3f;  /* '?' */
 
1151
        put_be16(pb, c);
 
1152
    }
 
1153
    put_be16(pb, 0x00);
 
1154
    return 2*n;
 
1155
}
 
1156
 
 
1157
static uint16_t language_code (char *str)
 
1158
{
 
1159
    return ((((str[0]-'a') & 0x1F)<<10) + (((str[1]-'a') & 0x1F)<<5) + ((str[2]-'a') & 0x1F));
 
1160
}
 
1161
 
 
1162
static int mov_write_uuidusmt_tag (ByteIOContext *pb, AVFormatContext *s)
 
1163
{
 
1164
    size_t len, size;
 
1165
    offset_t pos, curpos;
 
1166
 
 
1167
    size = 0;
 
1168
    if (s->title[0]) {
 
1169
        pos = url_ftell(pb);
 
1170
        put_be32(pb, 0); /* size placeholder*/
 
1171
        put_tag(pb, "uuid");
 
1172
        put_tag(pb, "USMT");
 
1173
        put_be32(pb, 0x21d24fce ); /* 96 bit UUID */
 
1174
        put_be32(pb, 0xbb88695c );
 
1175
        put_be32(pb, 0xfac9c740 );
 
1176
        size += 24;
 
1177
 
 
1178
        put_be32(pb, 0); /* size placeholder*/
 
1179
        put_tag(pb, "MTDT");
 
1180
        put_be16(pb, 1);
 
1181
        size += 10;
 
1182
 
 
1183
        // Title
 
1184
        len = strlen(s->title)+1;
 
1185
        put_be16(pb, len*2+10);             /* size */
 
1186
        put_be32(pb, 0x01);                 /* type */
 
1187
        put_be16(pb, language_code("und")); /* language */
 
1188
        put_be16(pb, 0x01);                 /* ? */
 
1189
        ascii_to_wc (pb, s->title, len);
 
1190
        size += len*2+10;
 
1191
 
 
1192
        // size
 
1193
        curpos = url_ftell(pb);
 
1194
        url_fseek(pb, pos, SEEK_SET);
 
1195
        put_be32(pb, size);
 
1196
        url_fseek(pb, pos+24, SEEK_SET);
 
1197
        put_be32(pb, size-24);
 
1198
        url_fseek(pb, curpos, SEEK_SET);
 
1199
    }
 
1200
 
 
1201
    return size;
 
1202
}
 
1203
 
1171
1204
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
1172
1205
                              AVFormatContext *s)
1173
1206
{
1174
 
    int pos, i;
1175
 
    pos = url_ftell(pb);
 
1207
    int i;
 
1208
    offset_t pos = url_ftell(pb);
1176
1209
    put_be32(pb, 0); /* size placeholder*/
1177
1210
    put_tag(pb, "moov");
1178
1211
    mov->timescale = globalTimescale;
1196
1229
            }
1197
1230
        }
1198
1231
 
1199
 
        mov->tracks[i].trackDuration = 
 
1232
        mov->tracks[i].trackDuration =
1200
1233
            mov->tracks[i].sampleCount * mov->tracks[i].sampleDuration;
1201
1234
        mov->tracks[i].time = mov->time;
1202
1235
        mov->tracks[i].trackID = i+1;
1210
1243
        }
1211
1244
    }
1212
1245
 
 
1246
    if (mov->mode == MODE_PSP)
 
1247
        mov_write_uuidusmt_tag(pb, s);
 
1248
    else
1213
1249
    mov_write_udta_tag(pb, mov, s);
1214
1250
 
1215
1251
    return updateSize(pb, pos);
1217
1253
 
1218
1254
int mov_write_mdat_tag(ByteIOContext *pb, MOVContext* mov)
1219
1255
{
1220
 
    mov->mdat_pos = url_ftell(pb); 
 
1256
    put_be32(pb, 8);    // placeholder for extended size field (64 bit)
 
1257
    put_tag(pb, "wide");
 
1258
 
 
1259
    mov->mdat_pos = url_ftell(pb);
1221
1260
    put_be32(pb, 0); /* size placeholder*/
1222
1261
    put_tag(pb, "mdat");
1223
1262
    return 0;
1224
1263
}
1225
1264
 
1226
1265
/* TODO: This needs to be more general */
1227
 
int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
 
1266
static void mov_write_ftyp_tag (ByteIOContext *pb, AVFormatContext *s)
1228
1267
{
1229
1268
    MOVContext *mov = s->priv_data;
1230
1269
 
1250
1289
        put_tag(pb, "MSNV");
1251
1290
    else
1252
1291
        put_tag(pb, "mp41");
1253
 
 
1254
 
    return 0x14;
1255
1292
}
1256
1293
 
1257
1294
static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
1258
1295
{
1259
 
    int AudioRate = s->streams[1]->codec->sample_rate;
1260
 
    int FrameRate = ((s->streams[0]->codec->time_base.den) * (0x10000))/ (s->streams[0]->codec->time_base.num);
1261
 
 
1262
 
    //printf("audiorate = %d\n",AudioRate);
1263
 
    //printf("framerate = %d / %d = 0x%x\n",s->streams[0]->codec->time_base.den,s->streams[0]->codec->time_base.num,FrameRate);
 
1296
    AVCodecContext *VideoCodec = s->streams[0]->codec;
 
1297
    AVCodecContext *AudioCodec = s->streams[1]->codec;
 
1298
    int AudioRate = AudioCodec->sample_rate;
 
1299
    int FrameRate = ((VideoCodec->time_base.den) * (0x10000))/ (VideoCodec->time_base.num);
1264
1300
 
1265
1301
    put_be32(pb, 0x94 ); /* size */
1266
1302
    put_tag(pb, "uuid");
1282
1318
    put_be32(pb, 0x2c );  /* size */
1283
1319
    put_tag(pb, "APRF");   /* audio */
1284
1320
    put_be32(pb, 0x0 );
1285
 
    put_be32(pb, 0x2 );
 
1321
    put_be32(pb, 0x2 );   /* TrackID */
1286
1322
    put_tag(pb, "mp4a");
1287
1323
    put_be32(pb, 0x20f );
1288
1324
    put_be32(pb, 0x0 );
1289
 
    put_be32(pb, 0x40 );
1290
 
    put_be32(pb, 0x40 );
1291
 
    put_be32(pb, AudioRate ); //24000   ... audio rate?
1292
 
    put_be32(pb, 0x2 );
 
1325
    put_be32(pb, AudioCodec->bit_rate / 1000);
 
1326
    put_be32(pb, AudioCodec->bit_rate / 1000);
 
1327
    put_be32(pb, AudioRate );
 
1328
    put_be32(pb, AudioCodec->channels );
1293
1329
 
1294
1330
    put_be32(pb, 0x34 );  /* size */
1295
1331
    put_tag(pb, "VPRF");   /* video */
1296
1332
    put_be32(pb, 0x0 );
1297
 
    put_be32(pb, 0x1 );
 
1333
    put_be32(pb, 0x1 );    /* TrackID */
1298
1334
    put_tag(pb, "mp4v");
1299
1335
    put_be32(pb, 0x103 );
1300
1336
    put_be32(pb, 0x0 );
1301
 
    put_be32(pb, 0xc0 );
1302
 
    put_be32(pb, 0xc0 );
1303
 
    put_be32(pb, FrameRate);  // was 0xefc29   
1304
 
    put_be32(pb, FrameRate );  // was 0xefc29
1305
 
    put_be16(pb, s->streams[0]->codec->width);
1306
 
    put_be16(pb, s->streams[0]->codec->height);
1307
 
    put_be32(pb, 0x010001 );
 
1337
    put_be32(pb, VideoCodec->bit_rate / 1000);
 
1338
    put_be32(pb, VideoCodec->bit_rate / 1000);
 
1339
    put_be32(pb, FrameRate);
 
1340
    put_be32(pb, FrameRate);
 
1341
    put_be16(pb, VideoCodec->width);
 
1342
    put_be16(pb, VideoCodec->height);
 
1343
    put_be32(pb, 0x010001); /* ? */
1308
1344
}
1309
1345
 
1310
1346
static int mov_write_header(AVFormatContext *s)
1331
1367
                    av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n");
1332
1368
            }
1333
1369
        }
 
1370
        /* don't know yet if mp4 or not */
 
1371
        mov->tracks[i].language = ff_mov_iso639_to_lang(s->streams[i]->language, 1);
1334
1372
    }
1335
1373
 
1336
1374
    /* Default mode == MP4 */
1394
1432
        else if(enc->codec_id == CODEC_ID_PCM_ALAW) {
1395
1433
            samplesInChunk = size/enc->channels;
1396
1434
        }
1397
 
        else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
1398
 
            samplesInChunk = size/(2*enc->channels);
1399
 
        }           
 
1435
        else if(enc->codec_id == CODEC_ID_PCM_S16BE || enc->codec_id == CODEC_ID_PCM_S16LE) {
 
1436
            samplesInChunk = size/(2*enc->channels);
 
1437
        }
1400
1438
        else {
1401
1439
            samplesInChunk = 1;
1402
1440
        }
1415
1453
    id = trk->entry % MOV_INDEX_CLUSTER_SIZE;
1416
1454
 
1417
1455
    if (trk->ents_allocated <= trk->entry) {
1418
 
        trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*)); 
 
1456
        trk->cluster = av_realloc(trk->cluster, (cl+1)*sizeof(void*));
1419
1457
        if (!trk->cluster)
1420
1458
            return -1;
1421
1459
        trk->cluster[cl] = av_malloc(MOV_INDEX_CLUSTER_SIZE*sizeof(MOVIentry));
1454
1492
    MOVContext *mov = s->priv_data;
1455
1493
    ByteIOContext *pb = &s->pb;
1456
1494
    int res = 0;
1457
 
    int i, j;
 
1495
    int i;
 
1496
    uint64_t j;
1458
1497
 
1459
1498
    offset_t moov_pos = url_ftell(pb);
1460
1499
 
1464
1503
            j += mov->tracks[i].mdat_size;
1465
1504
        }
1466
1505
    }
1467
 
    url_fseek(pb, mov->mdat_pos, SEEK_SET);
1468
 
    put_be32(pb, j+8);
 
1506
    if (j+8 <= UINT32_MAX) {
 
1507
        url_fseek(pb, mov->mdat_pos, SEEK_SET);
 
1508
        put_be32(pb, j+8);
 
1509
    } else {
 
1510
        /* overwrite 'wide' placeholder atom */
 
1511
        url_fseek(pb, mov->mdat_pos - 8, SEEK_SET);
 
1512
        put_be32(pb, 1); /* special value: real atom size will be 64 bit value after tag field */
 
1513
        put_tag(pb, "mdat");
 
1514
        put_be64(pb, j+16);
 
1515
    }
1469
1516
    url_fseek(pb, moov_pos, SEEK_SET);
1470
1517
 
1471
1518
    mov_write_moov_tag(pb, mov, s);
1539
1586
    mov_write_header,
1540
1587
    mov_write_packet,
1541
1588
    mov_write_trailer,
1542
 
//    .flags = AVFMT_GLOBALHEADER,
 
1589
    .flags = AVFMT_GLOBALHEADER,
1543
1590
};
1544
1591
 
1545
1592
static AVOutputFormat _3g2_oformat = {