1 /*******************************************************************************
2  elst.c
3 
4  libquicktime - A library for reading and writing quicktime/avi/mp4 files.
5  http://libquicktime.sourceforge.net
6 
7  Copyright (C) 2002 Heroine Virtual Ltd.
8  Copyright (C) 2002-2011 Members of the libquicktime project.
9 
10  This library is free software; you can redistribute it and/or modify it under
11  the terms of the GNU Lesser General Public License as published by the Free
12  Software Foundation; either version 2.1 of the License, or (at your option)
13  any later version.
14 
15  This library is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18  details.
19 
20  You should have received a copy of the GNU Lesser General Public License along
21  with this library; if not, write to the Free Software Foundation, Inc., 51
22  Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *******************************************************************************/
24 
25 #include "lqt_private.h"
26 #include <stdlib.h>
27 #include <string.h>
28 
quicktime_elst_table_init(quicktime_elst_table_t * table)29 void quicktime_elst_table_init(quicktime_elst_table_t *table)
30   {
31   table->duration = 0;
32   table->time = 0;
33   table->rate = 1;
34   }
35 
quicktime_elst_table_delete(quicktime_elst_table_t * table)36 void quicktime_elst_table_delete(quicktime_elst_table_t *table)
37   {
38   }
39 
quicktime_read_elst_table(quicktime_t * file,quicktime_elst_table_t * table)40 void quicktime_read_elst_table(quicktime_t *file, quicktime_elst_table_t *table)
41   {
42   table->duration = quicktime_read_int32(file);
43   table->time = quicktime_read_int32(file);
44   table->rate = quicktime_read_fixed32(file);
45   }
46 
quicktime_write_elst_table(quicktime_t * file,quicktime_elst_table_t * table)47 void quicktime_write_elst_table(quicktime_t *file, quicktime_elst_table_t *table)
48   {
49   quicktime_write_int32(file, table->duration);
50   quicktime_write_int32(file, table->time);
51   quicktime_write_fixed32(file, table->rate);
52   }
53 
quicktime_elst_table_dump(quicktime_elst_table_t * table)54 void quicktime_elst_table_dump(quicktime_elst_table_t *table)
55   {
56   lqt_dump("    edit list table\n");
57   lqt_dump("     duration %d\n", table->duration);
58   lqt_dump("     time %d\n", table->time);
59   lqt_dump("     rate %f\n", table->rate);
60   }
61 
quicktime_elst_init(quicktime_elst_t * elst)62 void quicktime_elst_init(quicktime_elst_t *elst)
63   {
64   elst->version = 0;
65   elst->flags = 0;
66   elst->total_entries = 0;
67   elst->table = 0;
68   }
69 
quicktime_elst_init_all(quicktime_elst_t * elst)70 void quicktime_elst_init_all(quicktime_elst_t *elst)
71   {
72   if(!elst->total_entries)
73     {
74     elst->total_entries = 1;
75     elst->table = realloc(NULL, sizeof(*elst->table) * elst->total_entries);
76     quicktime_elst_table_init(&elst->table[0]);
77     }
78   }
79 
quicktime_elst_fix_counts(quicktime_elst_t * elst,int moov_scale,quicktime_trak_t * trak,int timescale)80 void quicktime_elst_fix_counts(quicktime_elst_t *elst,
81                                int moov_scale, quicktime_trak_t * trak, int timescale)
82   {
83   int64_t offset_scaled;
84   offset_scaled = (int64_t)((double)trak->pts_offset / timescale * moov_scale + 0.5);
85   elst->table[0].duration = trak->tkhd.duration;
86 
87   if(trak->pts_offset < 0)
88     {
89     elst->table[0].time = -trak->pts_offset;
90     }
91   else if(offset_scaled > 0)
92     {
93     /* Insert empty edit */
94     elst->total_entries++;
95     elst->table = realloc(elst->table, sizeof(*elst->table) * elst->total_entries);
96     memmove(elst->table + 1, elst->table, sizeof(*elst->table) * (elst->total_entries-1));
97     elst->table[0].time = -1;
98     elst->table[0].duration = offset_scaled;
99     elst->table[0].rate = 1.0;
100     }
101   }
102 
quicktime_elst_get_pts_offset(quicktime_elst_t * elst,int moov_scale,int timescale)103 int64_t quicktime_elst_get_pts_offset(quicktime_elst_t *elst,
104                                       int moov_scale, int timescale)
105   {
106   if(elst->total_entries == 1)
107     {
108     if(elst->table[0].time > 0)
109       return - elst->table[0].time;
110     }
111   /* Detect empty edit */
112   else if((elst->total_entries == 2) &&
113           (elst->table[0].time == -1))
114     return (int64_t)((double)elst->table[0].duration / moov_scale * timescale + 0.5);
115   return 0;
116   }
117 
quicktime_elst_delete(quicktime_elst_t * elst)118 void quicktime_elst_delete(quicktime_elst_t *elst)
119   {
120   int i;
121   if(elst->total_entries)
122     {
123     for(i = 0; i < elst->total_entries; i++)
124       quicktime_elst_table_delete(&elst->table[i]);
125     free(elst->table);
126     }
127   elst->total_entries = 0;
128   }
129 
quicktime_elst_dump(quicktime_elst_t * elst)130 void quicktime_elst_dump(quicktime_elst_t *elst)
131   {
132   int i;
133   lqt_dump("   edit list (elst)\n");
134   lqt_dump("    version %d\n", elst->version);
135   lqt_dump("    flags %ld\n", elst->flags);
136   lqt_dump("    total_entries %ld\n", elst->total_entries);
137 
138   for(i = 0; i < elst->total_entries; i++)
139     {
140     quicktime_elst_table_dump(&elst->table[i]);
141     }
142   }
143 
quicktime_read_elst(quicktime_t * file,quicktime_elst_t * elst)144 void quicktime_read_elst(quicktime_t *file, quicktime_elst_t *elst)
145   {
146   int i;
147 
148   elst->version = quicktime_read_char(file);
149   elst->flags = quicktime_read_int24(file);
150   elst->total_entries = quicktime_read_int32(file);
151   elst->table = (quicktime_elst_table_t*)calloc(1, sizeof(quicktime_elst_table_t) * elst->total_entries);
152   for(i = 0; i < elst->total_entries; i++)
153     {
154     quicktime_elst_table_init(&elst->table[i]);
155     quicktime_read_elst_table(file, &elst->table[i]);
156     }
157   }
158 
quicktime_write_elst(quicktime_t * file,quicktime_elst_t * elst)159 void quicktime_write_elst(quicktime_t *file, quicktime_elst_t *elst)
160   {
161   quicktime_atom_t atom;
162   int i;
163   quicktime_atom_write_header(file, &atom, "elst");
164 
165   quicktime_write_char(file, elst->version);
166   quicktime_write_int24(file, elst->flags);
167   quicktime_write_int32(file, elst->total_entries);
168   for(i = 0; i < elst->total_entries; i++)
169     quicktime_write_elst_table(file, &elst->table[i]);
170   quicktime_atom_write_footer(file, &atom);
171   }
172