Handle subtitle tracks.
[libmkv.git] / src / tracks.c
blob95e7b3982570731580b70abcb6be51667431a3c8
1 /*****************************************************************************
2 * tracks.c:
3 *****************************************************************************
4 * Copyright (C) 2007 libmkv
5 * $Id: $
7 * Authors: Mike Matsnev
8 * Nathan Caldwell
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
24 #include "config.h"
25 #include "libmkv.h"
26 #include "matroska.h"
28 /* TODO: Figure out what can actually fail without damaging the track. */
30 mk_Track *mk_createTrack(mk_Writer *w, mk_TrackConfig *tc)
32 mk_Context *ti, *v;
33 int i;
34 mk_Track *track = calloc(1, sizeof(*track));
35 if (track == NULL)
36 return NULL;
38 if ((w->tracks_arr = realloc(w->tracks_arr, (w->num_tracks + 1) * sizeof(mk_Track *))) == NULL)
39 return NULL; // FIXME
40 w->tracks_arr[w->num_tracks] = track;
41 track->track_id = ++w->num_tracks;
43 if (w->tracks == NULL)
45 if ((w->tracks = mk_createContext(w, w->root, 0x1654ae6b)) == NULL) // tracks
46 return NULL;
49 if ((ti = mk_createContext(w, w->tracks, 0xae)) == NULL) // TrackEntry
50 return NULL;
51 if (mk_writeUInt(ti, 0xd7, track->track_id) < 0) // TrackNumber
52 return NULL;
53 if (tc->trackUID) {
54 if (mk_writeUInt(ti, 0x73c5, tc->trackUID) < 0) /* TrackUID */
55 return NULL;
56 } else {
58 * If we aren't given a UID, randomly generate one.
59 * NOTE: It would probably be better to CRC32 some unique track information
60 * in place of something completely random.
62 unsigned long track_uid;
63 track_uid = random();
65 if (mk_writeUInt(ti, 0x73c5, track_uid) < 0) /* TrackUID */
66 return NULL;
68 if (mk_writeUInt(ti, 0x83, tc->trackType) < 0) // TrackType
69 return NULL;
70 track->track_type = tc->trackType;
71 if (mk_writeUInt(ti, 0x9c, tc->flagLacing) < 0) // FlagLacing
72 return NULL;
73 if (mk_writeStr(ti, 0x86, tc->codecID) < 0) // CodecID
74 return NULL;
75 if (tc->codecPrivateSize && (tc->codecPrivate != NULL))
76 if (mk_writeBin(ti, 0x63a2, tc->codecPrivate, tc->codecPrivateSize) < 0) // CodecPrivate
77 return NULL;
78 if (tc->defaultDuration) {
79 if (mk_writeUInt(ti, 0x23e383, tc->defaultDuration) < 0)
80 return NULL;
81 track->default_duration = tc->defaultDuration;
83 if (tc->language)
84 if (mk_writeStr(ti, 0x22b59c, tc->language) < 0) // Language
85 return NULL;
86 if (tc->flagEnabled != 1)
87 if (mk_writeUInt(ti, 0xb9, tc->flagEnabled) < 0) // FlagEnabled
88 return NULL;
89 if (mk_writeUInt(ti, 0x88, tc->flagDefault) < 0) // FlagDefault
90 return NULL;
91 if (tc->flagForced)
92 if (mk_writeUInt(ti, 0x55aa, tc->flagForced) < 0) // FlagForced
93 return NULL;
94 if (tc->minCache)
95 if (mk_writeUInt(ti, 0x6de7, tc->minCache) < 0) // MinCache
96 return NULL;
97 /* FIXME: this won't handle NULL values, which signals that the cache is disabled. */
98 if (tc->maxCache)
99 if (mk_writeUInt(ti, 0x6df8, tc->maxCache) < 0) // MaxCache
100 return NULL;
102 switch (tc->trackType)
104 case MK_TRACK_VIDEO: // Video
105 if ((v = mk_createContext(w, ti, 0xe0)) == NULL)
106 return NULL;
107 if (tc->extra.video.pixelCrop[0] != 0 || tc->extra.video.pixelCrop[1] != 0 || tc->extra.video.pixelCrop[2] != 0 || tc->extra.video.pixelCrop[3] != 0) {
108 for (i = 0; i < 4; i++) {
109 if (mk_writeUInt(v, 0x54aa + (i * 0x11), tc->extra.video.pixelCrop[i]) < 0) // PixelCrop
110 return NULL;
113 if (mk_writeUInt(v, 0xb0, tc->extra.video.pixelWidth) < 0) // PixelWidth
114 return NULL;
115 if (mk_writeUInt(v, 0xba, tc->extra.video.pixelHeight) < 0 ) // PixelHeight
116 return NULL;
117 if (mk_writeUInt(v, 0x54b0, tc->extra.video.displayWidth) < 0) // DisplayWidth
118 return NULL;
119 if (mk_writeUInt(v, 0x54ba, tc->extra.video.displayHeight) < 0) // DisplayHeight
120 return NULL;
121 if (tc->extra.video.displayUnit)
122 if (mk_writeUInt(v, 0x54b2, tc->extra.video.displayUnit) < 0) // DisplayUnit
123 return NULL;
124 if (mk_closeContext(v, 0) < 0)
125 return NULL;
126 break;
127 case MK_TRACK_AUDIO: // Audio
128 if ((v = mk_createContext(w, ti, 0xe1)) == NULL)
129 return NULL;
130 if (mk_writeFloat(v, 0xb5, tc->extra.audio.samplingFreq) < 0) // SamplingFrequency
131 return NULL;
132 if (mk_writeUInt(v, 0x9f, tc->extra.audio.channels) < 0) // Channels
133 return NULL;
134 if (tc->extra.audio.bitDepth)
135 if (mk_writeUInt(v, 0x6264, tc->extra.audio.bitDepth) < 0) // BitDepth
136 return NULL;
137 if (mk_closeContext(v, 0) < 0)
138 return NULL;
139 break;
140 case MK_TRACK_SUBTITLE: // Subtitles
141 break;
142 default: // Other TODO: Implement other track types.
143 return NULL;
146 if (mk_closeContext(ti, 0) < 0)
147 return NULL;
149 return track;
152 int mk_writeTracks(mk_Writer *w, mk_Context *tracks)
154 w->seek_data.tracks = w->root->d_cur;
156 CHECK(mk_closeContext(w->tracks, 0));
158 return 0;