23487fd2e4eb0dd7d2c8f6beece34971049619b2
[vlc.git] / plugins / mp4 / mp4.h
1 /*****************************************************************************
2  * mp4.h : MP4 file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: mp4.h,v 1.2 2002/07/21 15:13:19 fenrir Exp $
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23
24
25 /*****************************************************************************
26  * Structure needed for ffmpeg decoder
27  *****************************************************************************/
28
29 typedef struct bitmapinfoheader_s
30 {
31     u32 i_size; /* size of header */
32     u32 i_width;
33     u32 i_height;
34     u16 i_planes;
35     u16 i_bitcount;
36     u32 i_compression;
37     u32 i_sizeimage;
38     u32 i_xpelspermeter;
39     u32 i_ypelspermeter;
40     u32 i_clrused;
41     u32 i_clrimportant;
42 } bitmapinfoheader_t;
43
44
45
46 /*****************************************************************************
47  * Contain all information about a chunk
48  *****************************************************************************/
49 typedef struct chunk_data_mp4_s
50 {
51     u64     i_offset; /* absolute position of this chunk in the file */
52     u32     i_sample_description_index; /* index for SampleEntry to use */
53     u32     i_sample_count; /* how many samples in this chunk */
54     u32     i_sample_first; /* index of the first sample in this chunk */
55
56     /* now provide way to calculate pts, dts, and offset without to 
57         much memory and with fast acces */
58
59     /* with this we can calculate dts/pts without waste memory */
60     u64     i_first_dts;
61     u32     *p_sample_count_dts;
62     u32     *p_sample_delta_dts; /* dts delta */
63
64     /* TODO if needed add pts 
65         but quickly *add* support for edts and seeking */
66     
67 } chunk_data_mp4_t;
68
69
70 /*****************************************************************************
71  * Contain all needed information for read all track with vlc
72  *****************************************************************************/
73 typedef struct track_data_mp4_s
74 {
75     int b_ok;           /* The track is usable */
76     int i_track_ID;     /* this should be unique */
77     int b_enable;       /* is the trak enable by default */
78
79     int i_cat;          /* Type of the track, VIDEO_ES, AUDIO_ES, UNKNOWN_ES  ... */
80     char        i_language[3];
81
82     /* display size only ! */
83     int         i_width;
84     int         i_height;
85  
86     /* more internal data */    
87     u64         i_timescale;  /* time scale for this track only */
88
89     /* give the next sample to read, i_chunk is to find quickly where 
90       the sample is located */
91     u32         i_sample;       /* next sample to read */
92     u32         i_chunk;        /* chunk where next sample is stored */
93     /* total count of chunk and sample */
94     u32         i_chunk_count;  
95     u32         i_sample_count;
96     
97     chunk_data_mp4_t    *chunk; /* always defined  for each chunk */
98     
99     /* sample size, p_sample_size defined only if i_sample_size == 0 
100         else i_sample_size is size for all sample */
101     u32         i_sample_size;
102     u32         *p_sample_size; /* XXX perhaps add file offset if take 
103                                     too much time to do sumations each time*/
104     
105     es_descriptor_t *p_es; /* vlc es for this track */
106     data_packet_t   *p_data_init; /* send this with the first packet, 
107                                         and then discarded it*/
108
109     MP4_Box_t *p_stbl;  /* will contain all timing information */
110     MP4_Box_t *p_stsd;  /* will contain all data to initialize decoder */
111     
112     MP4_Box_t *p_sample; /* actual SampleEntry to make life simpler */
113 } track_data_mp4_t;
114
115
116 /*****************************************************************************
117  *
118  *****************************************************************************/
119 typedef struct demux_data_mp4_s
120 {
121
122     MP4_Box_t   box_root;       /* container for the hole file */
123
124     mtime_t     i_pcr;
125     
126     u64         i_time;         /* time position of the presentation in movie timescale */
127     u64         i_timescale;    /* movie time scale */
128     
129     int i_tracks;               /* number of track */  
130     track_data_mp4_t *track; /* array of track */
131     
132   
133 } demux_data_mp4_t;
134
135 static inline u64 MP4_GetTrackPos( track_data_mp4_t *p_track )
136 {
137     int i_sample;
138     u64 i_pos;
139
140
141     i_pos = p_track->chunk[p_track->i_chunk].i_offset;
142
143     if( p_track->i_sample_size )
144     {
145         i_pos += ( p_track->i_sample - 
146                         p_track->chunk[p_track->i_chunk].i_sample_first ) *
147                                 p_track->i_sample_size;
148     }
149     else
150     {
151         for( i_sample = p_track->chunk[p_track->i_chunk].i_sample_first; 
152                 i_sample < p_track->i_sample; i_sample++ )
153         {
154             i_pos += p_track->p_sample_size[i_sample];
155         }
156
157     }
158     return( i_pos );
159 }
160
161 /* Return time in ┬Ás of a track */
162 static inline mtime_t MP4_GetTrackPTS( track_data_mp4_t *p_track )
163 {
164     int i_sample;
165     int i_index;
166     u64 i_dts;
167     
168     i_sample = p_track->i_sample - p_track->chunk[p_track->i_chunk].i_sample_first;
169     i_dts = p_track->chunk[p_track->i_chunk].i_first_dts;
170     i_index = 0;
171     while( i_sample > 0 )
172     {
173         if( i_sample > p_track->chunk[p_track->i_chunk].p_sample_count_dts[i_index] )
174         {
175             i_dts += p_track->chunk[p_track->i_chunk].p_sample_count_dts[i_index] * 
176                         p_track->chunk[p_track->i_chunk].p_sample_delta_dts[i_index];
177             i_sample -= p_track->chunk[p_track->i_chunk].p_sample_count_dts[i_index];
178             i_index++;
179         }
180         else
181         {
182             i_dts += i_sample * 
183                         p_track->chunk[p_track->i_chunk].p_sample_delta_dts[i_index];
184             i_sample = 0;
185             break;
186         }
187     }
188     return( (mtime_t)( 
189                 (mtime_t)1000000 *
190                 (mtime_t)i_dts / 
191                 (mtime_t)p_track->i_timescale ) );
192 }
193
194 static inline mtime_t MP4_GetMoviePTS(demux_data_mp4_t *p_demux )
195 {
196     return( (mtime_t)(
197                 (mtime_t)1000000 *
198                 (mtime_t)p_demux->i_time /
199                 (mtime_t)p_demux->i_timescale )
200           );
201 }
202     
203 static struct
204 {
205     u32 i_fourcc;
206     int i_codec;
207     char *psz_name;
208 } MP4_Codecs [] = {
209     /* Video codec */
210     { FOURCC_vide,  UNKNOWN_ES,     "Generic VisualSampleEntry" },
211     { FOURCC_DIVX,  MPEG4_VIDEO_ES, "DIVX SampleEntry (MPEG-4)" },
212     { FOURCC_h263,  H263_VIDEO_ES,  "H263 SampleEntry" },
213     { FOURCC_SVQ1,  SVQ1_VIDEO_ES,  "SVQ1 SampleEntry (Sorenson Video v1" },
214     { FOURCC_mp4v,  MPEG4_VIDEO_ES, "MP4VisualSampleEntry (MPEG-4)" },
215     { FOURCC_3IV1,  UNKNOWN_ES,     "3IV1 SampleEntry" },
216     { FOURCC_cvid,  CINEPAK_VIDEO_ES,"cvid SampleEntry (Cinepak Video Codec)" },
217
218     /* Audio codec */
219     { FOURCC_soun,  UNKNOWN_ES,     "Generic AudioSampleEntry" },
220     { FOURCC_mp4a,  UNKNOWN_ES,     "MP4AudioSampleEntry (AAC)" },
221     { FOURCC__mp3,  MPEG2_AUDIO_ES, ".mp3 SampleEntry (MPEG-I/II layer 3)" },
222     
223     /* Last entry with fourcc == 0 */
224     { 0,            UNKNOWN_ES,     "Unknown SampleEntry" }
225 };
226
227 static int MP4_GetCodec( u32  i_fourcc,
228                          int  *pi_codec,
229                          char **ppsz_name )
230 {
231    int i;
232
233     for( i = 0; ; i++ )
234     {
235         if( ( MP4_Codecs[i].i_fourcc == i_fourcc )||
236             ( MP4_Codecs[i].i_fourcc == 0) )
237         {
238             break;
239         }
240     }
241
242     if( pi_codec )
243         *pi_codec = MP4_Codecs[i].i_codec;
244     
245     if( ppsz_name )
246         *ppsz_name = MP4_Codecs[i].psz_name;
247
248     return( MP4_Codecs[i].i_codec == UNKNOWN_ES ? 0 : 1 );
249 }
250