Revision 69dde1ad libavformat/movenc.c

View differences:

libavformat/movenc.c
1 1
/*
2 2
 * MOV, 3GP, MP4 encoder.
3 3
 * Copyright (c) 2003 Thomas Raivio.
4
 * Enhancements by Gildas Bazin <gbazin@netcourrier.com>
4
 * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>.
5 5
 *
6 6
 * This library is free software; you can redistribute it and/or
7 7
 * modify it under the terms of the GNU Lesser General Public
......
27 27
#define MOV_INDEX_CLUSTER_SIZE 16384
28 28
#define globalTimescale 1000
29 29

  
30
#define MODE_MP4 0
31
#define MODE_MOV 1
32
#define MODE_3GP 2
33

  
30 34
typedef struct MOVIentry {
31 35
    unsigned int flags, pos, size;
32 36
    unsigned int samplesInChunk;
......
35 39
} MOVIentry;
36 40

  
37 41
typedef struct MOVIndex {
42
    int         mode;
38 43
    int         entry;
39 44
    int         mdat_size;
40 45
    int         ents_allocated;
......
53 58
} MOVTrack;
54 59

  
55 60
typedef struct {
61
    int     mode;
56 62
    long    time;
57 63
    int     nb_streams;
58 64
    int     mdat_written;
59 65
    offset_t mdat_pos;
60
    offset_t movi_list;
61 66
    long    timescale;
62 67
    MOVTrack tracks[MAX_STREAMS];
63 68
} MOVContext;
......
204 209
    return 0x11;
205 210
}
206 211

  
212
static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack* track)
213
{
214
    int pos = url_ftell(pb);
215

  
216
    put_be32(pb, 0);     /* size */
217
    put_tag(pb, "wave");
218

  
219
    put_be32(pb, 12);    /* size */
220
    put_tag(pb, "frma");
221
    put_tag(pb, "mp4a");
222

  
223
    put_be32(pb, 12);    /* size */
224
    put_tag(pb, "mp4a");
225
    put_be32(pb, 0);
226

  
227
    mov_write_esds_tag(pb, track);
228

  
229
    put_be32(pb, 12);    /* size */
230
    put_tag(pb, "srcq");
231
    put_be32(pb, 0x40);
232

  
233
    put_be32(pb, 8);     /* size */
234
    put_be32(pb, 0);     /* null tag */
235

  
236
    return updateSize (pb, pos);
237
}
238

  
207 239
static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track)
208 240
{
209 241
    int pos = url_ftell(pb);
......
229 261
    put_be32(pb, 0); /* Reserved */
230 262
    put_be16(pb, 0); /* Reserved */
231 263
    put_be16(pb, 1); /* Data-reference index, XXX  == 1 */
264

  
232 265
    /* SoundDescription */
233
    put_be16(pb, 0); /* Version */
266
    if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)
267
        put_be16(pb, 1); /* Version 1 */
268
    else
269
        put_be16(pb, 0); /* Version 0 */
234 270
    put_be16(pb, 0); /* Revision level */
235 271
    put_be32(pb, 0); /* Reserved */
236 272

  
......
238 274
    /* TODO: Currently hard-coded to 16-bit, there doesn't seem
239 275
                 to be a good way to get number of bits of audio */
240 276
    put_be16(pb, 0x10); /* Reserved */
241
    put_be16(pb, 0); /* compression ID (= 0) */
242
    put_be16(pb, 0); /* packet size (= 0) */
277
    put_be16(pb, 0xfffe); /* compression ID (= 0) */
278
    put_be16(pb, 0xac); /* packet size (= 0) */
243 279
    put_be16(pb, track->timescale); /* Time scale */
244 280
    put_be16(pb, 0); /* Reserved */
245 281

  
246
    if(track->enc->codec_id == CODEC_ID_AAC)
247
        mov_write_esds_tag(pb, track);
282
    if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC)
283
    {
284
        /* SoundDescription V1 extended info */
285
        put_be32(pb, track->enc->frame_size); /* Samples per packet  */
286
        put_be32(pb, 1536); /* Bytes per packet */
287
        put_be32(pb, 2); /* Bytes per frame */
288
        put_be32(pb, 2); /* Bytes per sample */
289
    }
290

  
291
    if(track->enc->codec_id == CODEC_ID_AAC) {
292
        if( track->mode == MODE_MOV ) mov_write_wave_tag(pb, track);
293
        else mov_write_esds_tag(pb, track);
294
    }
248 295
    if(track->enc->codec_id == CODEC_ID_AMR_NB)
249 296
        mov_write_damr_tag(pb);
250 297
    return updateSize (pb, pos);
......
608 655

  
609 656
    /* Track width and height, for visual only */
610 657
    if(track->enc->codec_type == CODEC_TYPE_VIDEO) {
611
        put_be32(pb, track->enc->width*0x10000);
658
        double sample_aspect_ratio = av_q2d(track->enc->sample_aspect_ratio);
659
        if( !sample_aspect_ratio ) sample_aspect_ratio = 1;
660
        put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
612 661
        put_be32(pb, track->enc->height*0x10000);
613 662
    }
614 663
    else {
......
691 740
    return 0x6c;
692 741
}
693 742

  
694
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov)
743
static int mov_write_udta_tag(ByteIOContext *pb, MOVContext* mov,
744
                              AVFormatContext *s)
745
{
746
    int pos = url_ftell(pb);
747
    int i;
748

  
749
    put_be32(pb, 0); /* size */
750
    put_tag(pb, "udta");
751

  
752
    /* Requirements */
753
    for (i=0; i<MAX_STREAMS; i++) {
754
        if(mov->tracks[i].entry <= 0) continue;
755
        if (mov->tracks[i].enc->codec_id == CODEC_ID_AAC ||
756
            mov->tracks[i].enc->codec_id == CODEC_ID_MPEG4) {
757
            int pos = url_ftell(pb);
758
            put_be32(pb, 0); /* size */
759
            put_tag(pb, "\251req");
760
            put_be16(pb, sizeof("QuickTime 6.0 or greater") - 1);
761
            put_be16(pb, 0);
762
            put_buffer(pb, "QuickTime 6.0 or greater",
763
                       sizeof("QuickTime 6.0 or greater") - 1);
764
            updateSize(pb, pos);
765
            break;
766
        }
767
    }
768

  
769
    /* Encoder */
770
    {
771
        int pos = url_ftell(pb);
772
        put_be32(pb, 0); /* size */
773
        put_tag(pb, "\251enc");
774
        put_be16(pb, sizeof(LIBAVFORMAT_IDENT) - 1); /* string length */
775
        put_be16(pb, 0);
776
        put_buffer(pb, LIBAVFORMAT_IDENT, sizeof(LIBAVFORMAT_IDENT) - 1);
777
        updateSize(pb, pos);
778
    }
779

  
780
    if( s->title[0] )
781
    {
782
        int pos = url_ftell(pb);
783
        put_be32(pb, 0); /* size */
784
        put_tag(pb, "\251nam");
785
        put_be16(pb, strlen(s->title)); /* string length */
786
        put_be16(pb, 0);
787
        put_buffer(pb, s->title, strlen(s->title));
788
        updateSize(pb, pos);
789
    }
790

  
791
    if( s->author[0] )
792
    {
793
        int pos = url_ftell(pb);
794
        put_be32(pb, 0); /* size */
795
        put_tag(pb, /*"\251aut"*/ "\251day" );
796
        put_be16(pb, strlen(s->author)); /* string length */
797
        put_be16(pb, 0);
798
        put_buffer(pb, s->author, strlen(s->author));
799
        updateSize(pb, pos);
800
    }
801

  
802
    if( s->comment[0] )
803
    {
804
        int pos = url_ftell(pb);
805
        put_be32(pb, 0); /* size */
806
        put_tag(pb, "\251des");
807
        put_be16(pb, strlen(s->comment)); /* string length */
808
        put_be16(pb, 0);
809
        put_buffer(pb, s->comment, strlen(s->comment));
810
        updateSize(pb, pos);
811
    }
812

  
813
    return updateSize(pb, pos);
814
}
815

  
816
static int mov_write_moov_tag(ByteIOContext *pb, MOVContext *mov,
817
                              AVFormatContext *s)
695 818
{
696 819
    int pos, i;
697 820
    pos = url_ftell(pb);
......
732 855
        }
733 856
    }
734 857

  
858
    mov_write_udta_tag(pb, mov, s);
859

  
735 860
    return updateSize(pb, pos);
736 861
}
737 862

  
......
746 871
/* TODO: This needs to be more general */
747 872
int mov_write_ftyp_tag(ByteIOContext *pb, AVFormatContext *s)
748 873
{
874
    MOVContext *mov = s->priv_data;
875

  
749 876
    put_be32(pb, 0x14 ); /* size */
750 877
    put_tag(pb, "ftyp");
751 878

  
752
    if (!strcmp("3gp", s->oformat->name))
879
    if ( mov->mode == MODE_3GP )
753 880
        put_tag(pb, "3gp4");
754 881
    else
755 882
        put_tag(pb, "isom");
756 883

  
757 884
    put_be32(pb, 0x200 );
758 885

  
759
    if (!strcmp("3gp", s->oformat->name))
886
    if ( mov->mode == MODE_3GP )
760 887
        put_tag(pb, "3gp4");
761 888
    else
762 889
        put_tag(pb, "mp41");
......
767 894
static int mov_write_header(AVFormatContext *s)
768 895
{
769 896
    ByteIOContext *pb = &s->pb;
897
    MOVContext *mov = s->priv_data;
898
    int i;
770 899

  
771
    if(s->oformat != NULL) {
772
    if(!strcmp("3gp", s->oformat->name) || !strcmp("mp4", s->oformat->name))
773
        mov_write_ftyp_tag(pb,s);
900
    /* Default mode == MP4 */
901
    mov->mode = MODE_MP4;
902

  
903
    if (s->oformat != NULL) {
904
        if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
905
        else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
906

  
907
        if ( mov->mode == MODE_3GP || mov->mode == MODE_MP4 )
908
            mov_write_ftyp_tag(pb,s);
909
    }
910

  
911
    for (i=0; i<MAX_STREAMS; i++) {
912
        mov->tracks[i].mode = mov->mode;
774 913
    }
775 914

  
776 915
    put_flush_packet(pb);
......
845 984
        mov->time = Timestamp();
846 985
    }
847 986

  
848
    trk->cluster[cl][id].pos = url_ftell(pb) - mov->movi_list;
987
    trk->cluster[cl][id].pos = url_ftell(pb);
849 988
    trk->cluster[cl][id].samplesInChunk = samplesInChunk;
850 989
    trk->cluster[cl][id].size = size;
851 990
    trk->cluster[cl][id].entries = samplesInChunk;
......
871 1010
    ByteIOContext *pb = &s->pb;
872 1011
    int res = 0;
873 1012
    int i, j;
874
    offset_t file_size;
875 1013

  
876
    file_size = url_ftell(pb);
877
    j = 0;
1014
    offset_t moov_pos = url_ftell(pb);
878 1015

  
879 1016
    /* Write size of mdat tag */
880
    for (i=0; i<MAX_STREAMS; i++) {
1017
    for (i=0, j=0; i<MAX_STREAMS; i++) {
881 1018
        if(mov->tracks[i].ents_allocated > 0) {
882 1019
            j += mov->tracks[i].mdat_size;
883 1020
        }
884 1021
    }
885 1022
    url_fseek(pb, mov->mdat_pos, SEEK_SET);
886 1023
    put_be32(pb, j+8);
887
    url_fseek(pb, file_size, SEEK_SET);
1024
    url_fseek(pb, moov_pos, SEEK_SET);
888 1025

  
889
    mov_write_moov_tag(pb, mov);
1026
    mov_write_moov_tag(pb, mov, s);
890 1027

  
891 1028
    for (i=0; i<MAX_STREAMS; i++) {
892 1029
        for (j=0; j<mov->tracks[i].ents_allocated/MOV_INDEX_CLUSTER_SIZE; j++) {
......
898 1035
        mov->tracks[i].cluster = NULL;
899 1036
        mov->tracks[i].ents_allocated = mov->tracks[i].entry = 0;
900 1037
    }
1038

  
901 1039
    put_flush_packet(pb);
902 1040

  
903 1041
    return res;
......
909 1047
    NULL,
910 1048
    "mov",
911 1049
    sizeof(MOVContext),
912
    CODEC_ID_PCM_ALAW,
1050
    CODEC_ID_AAC,
913 1051
    CODEC_ID_MPEG4,
914 1052
    mov_write_header,
915 1053
    mov_write_packet,

Also available in: Unified diff