Bump version to 0.6.4.1
[libmkv.git] / src / tracks.c
blobd9fc38b7f5576527d4eae1517c5d7c8b1e476a34
1 /*****************************************************************************
2 * tracks.c:
3 *****************************************************************************
4 * Copyright (C) 2007 libmkv
6 * Authors: Mike Matsnev
7 * Nathan Caldwell
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
23 #include "config.h"
24 #include "libmkv.h"
25 #include "matroska.h"
27 /* TODO: Figure out what can actually fail without damaging the track. */
29 #define TRACK_STEP 4
31 mk_Track *mk_createTrack(mk_Writer *w, mk_TrackConfig *tc)
33 mk_Context *ti, *v;
34 int i;
35 mk_Track *track = calloc(1, sizeof(*track));
36 if (track == NULL)
37 return NULL;
39 if (w->num_tracks + 1 > w->alloc_tracks) {
40 if ((w->tracks_arr = realloc(w->tracks_arr, (w->alloc_tracks + TRACK_STEP) * sizeof(mk_Track *))) == NULL)
41 return NULL; // FIXME
42 w->alloc_tracks += TRACK_STEP;
44 w->tracks_arr[w->num_tracks] = track;
45 track->track_id = ++w->num_tracks;
47 if (w->tracks == NULL) {
48 /* Tracks */
49 if ((w->tracks = mk_createContext(w, w->root, MATROSKA_ID_TRACKS)) == NULL)
50 return NULL;
53 /* TrackEntry */
54 if ((ti = mk_createContext(w, w->tracks, MATROSKA_ID_TRACKENTRY)) == NULL)
55 return NULL;
56 /* TrackNumber */
57 if (mk_writeUInt(ti, MATROSKA_ID_TRACKNUMBER, track->track_id) < 0)
58 return NULL;
59 if (tc->trackUID) {
60 if (mk_writeUInt(ti, MATROSKA_ID_TRACKUID, tc->trackUID) < 0) /* TrackUID */
61 return NULL;
62 } else {
64 * If we aren't given a UID, randomly generate one.
65 * NOTE: It would probably be better to CRC32 some unique track information
66 * in place of something completely random.
68 unsigned long track_uid;
69 track_uid = random();
71 if (mk_writeUInt(ti, MATROSKA_ID_TRACKUID, track_uid) < 0) /* TrackUID */
72 return NULL;
74 if (mk_writeUInt(ti, MATROSKA_ID_TRACKTYPE, tc->trackType) < 0) /* TrackType */
75 return NULL;
76 track->track_type = tc->trackType;
77 /* FlagLacing */
78 if (mk_writeUInt(ti, MATROSKA_ID_TRACKFLAGLACING, tc->flagLacing) < 0)
79 return NULL;
80 if (mk_writeStr(ti, MATROSKA_ID_CODECID, tc->codecID) < 0) /* CodecID */
81 return NULL;
82 if (tc->codecPrivateSize && (tc->codecPrivate != NULL)) {
83 /* CodecPrivate */
84 if (mk_writeBin(ti, MATROSKA_ID_CODECPRIVATE, tc->codecPrivate, tc->codecPrivateSize) < 0)
85 return NULL;
87 if (tc->defaultDuration) {
88 /* DefaultDuration */
89 if (mk_writeUInt(ti, MATROSKA_ID_TRACKDEFAULTDURATION, tc->defaultDuration) < 0)
90 return NULL;
91 track->default_duration = tc->defaultDuration;
93 if (tc->language) {
94 /* Language */
95 if (mk_writeStr(ti, MATROSKA_ID_TRACKLANGUAGE, tc->language) < 0)
96 return NULL;
98 if (tc->flagEnabled != 1) {
99 /* FlagEnabled */
100 if (mk_writeUInt(ti, MATROSKA_ID_TRACKFLAGENABLED, tc->flagEnabled) < 0)
101 return NULL;
103 /* FlagDefault */
104 if (mk_writeUInt(ti, MATROSKA_ID_TRACKFLAGDEFAULT, tc->flagDefault) < 0)
105 return NULL;
106 if (tc->flagForced) {
107 /* FlagForced */
108 if (mk_writeUInt(ti, MATROSKA_ID_TRACKFLAGFORCED, tc->flagForced) < 0)
109 return NULL;
111 if (tc->minCache){
112 /* MinCache */
113 if (mk_writeUInt(ti, MATROSKA_ID_TRACKMINCACHE, tc->minCache) < 0)
114 return NULL;
117 /* FIXME: this won't handle NULL values, which signals that the cache is disabled. */
118 if (tc->maxCache) {
119 /* MaxCache */
120 if (mk_writeUInt(ti, MATROSKA_ID_TRACKMAXCACHE, tc->maxCache) < 0)
121 return NULL;
124 switch (tc->trackType) {
125 case MK_TRACK_VIDEO:
126 /* Video */
127 if ((v = mk_createContext(w, ti, MATROSKA_ID_TRACKVIDEO)) == NULL)
128 return NULL;
129 if (tc->extra.video.pixelCrop[0] != 0
130 || tc->extra.video.pixelCrop[1] != 0
131 || tc->extra.video.pixelCrop[2] != 0
132 || tc->extra.video.pixelCrop[3] != 0) {
133 for (i = 0; i < 4; i++) {
134 /* Each pixel crop ID is 0x11 away from the next.
135 * In order from 0x54AA to 0x54DD they are bottom, top, left, right.
137 /* PixelCrop{Bottom,Top,Left,Right} */
138 if (mk_writeUInt(v, MATROSKA_ID_VIDEOPIXELCROPBOTTOM + (i * 0x11), tc->extra.video.pixelCrop[i]) < 0)
139 return NULL;
142 /* PixelWidth */
143 if (mk_writeUInt(v, MATROSKA_ID_VIDEOPIXELWIDTH, tc->extra.video.pixelWidth) < 0)
144 return NULL;
145 /* PixelHeight */
146 if (mk_writeUInt(v, MATROSKA_ID_VIDEOPIXELHEIGHT, tc->extra.video.pixelHeight) < 0)
147 return NULL;
148 /* DisplayWidth */
149 if (mk_writeUInt(v, MATROSKA_ID_VIDEODISPLAYWIDTH, tc->extra.video.displayWidth) < 0)
150 return NULL;
151 /* DisplayHeight */
152 if (mk_writeUInt(v, MATROSKA_ID_VIDEODISPLAYHEIGHT, tc->extra.video.displayHeight) < 0)
153 return NULL;
154 if (tc->extra.video.displayUnit) {
155 /* DisplayUnit */
156 if (mk_writeUInt(v, MATROSKA_ID_VIDEODISPLAYUNIT, tc->extra.video.displayUnit) < 0)
157 return NULL;
159 if (tc->extra.video.aspectRatioType != MK_ASPECTRATIO_FREE) {
160 /* AspectRatioType */
161 if (mk_writeUInt(v, MATROSKA_ID_VIDEOASPECTRATIOTYPE, tc->extra.video.aspectRatioType) < 0)
162 return NULL;
164 if (mk_closeContext(v, 0) < 0)
165 return NULL;
166 break;
167 case MK_TRACK_AUDIO:
168 /* Audio */
169 if ((v = mk_createContext(w, ti, MATROSKA_ID_TRACKAUDIO)) == NULL)
170 return NULL;
171 /* SamplingFrequency */
172 if (mk_writeFloat(v, MATROSKA_ID_AUDIOSAMPLINGFREQ, tc->extra.audio.samplingFreq) < 0)
173 return NULL;
174 /* Channels */
175 if (mk_writeUInt(v, MATROSKA_ID_AUDIOCHANNELS, tc->extra.audio.channels) < 0)
176 return NULL;
177 if (tc->extra.audio.bitDepth) {
178 /* BitDepth */
179 if (mk_writeUInt(v, MATROSKA_ID_AUDIOBITDEPTH, tc->extra.audio.bitDepth) < 0)
180 return NULL;
182 if (mk_closeContext(v, 0) < 0)
183 return NULL;
184 break;
185 case MK_TRACK_SUBTITLE:
186 /* Subtitles */
187 break;
188 default: /* Other track types
189 * TODO: Implement other valid track types.
191 return NULL;
194 if (mk_closeContext(ti, 0) < 0)
195 return NULL;
197 return track;
200 int mk_writeTracks(mk_Writer *w, mk_Context *tracks)
202 w->seek_data.tracks = w->root->d_cur;
204 CHECK(mk_closeContext(w->tracks, 0));
206 return 0;