1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2007 libmkv
6 * Authors: Mike Matsnev
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 *****************************************************************************/
27 /* TODO: Figure out what can actually fail without damaging the track. */
31 mk_Track
*mk_createTrack(mk_Writer
*w
, mk_TrackConfig
*tc
)
35 mk_Track
*track
= calloc(1, sizeof(*track
));
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
)
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
) {
49 if ((w
->tracks
= mk_createContext(w
, w
->root
, MATROSKA_ID_TRACKS
)) == NULL
)
54 if ((ti
= mk_createContext(w
, w
->tracks
, MATROSKA_ID_TRACKENTRY
)) == NULL
)
57 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKNUMBER
, track
->track_id
) < 0)
60 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKUID
, tc
->trackUID
) < 0) /* TrackUID */
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
;
71 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKUID
, track_uid
) < 0) /* TrackUID */
74 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKTYPE
, tc
->trackType
) < 0) /* TrackType */
76 track
->track_type
= tc
->trackType
;
78 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKFLAGLACING
, tc
->flagLacing
) < 0)
80 if (mk_writeStr(ti
, MATROSKA_ID_CODECID
, tc
->codecID
) < 0) /* CodecID */
82 if (tc
->codecPrivateSize
&& (tc
->codecPrivate
!= NULL
)) {
84 if (mk_writeBin(ti
, MATROSKA_ID_CODECPRIVATE
, tc
->codecPrivate
, tc
->codecPrivateSize
) < 0)
87 if (tc
->defaultDuration
) {
89 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKDEFAULTDURATION
, tc
->defaultDuration
) < 0)
91 track
->default_duration
= tc
->defaultDuration
;
95 if (mk_writeStr(ti
, MATROSKA_ID_TRACKLANGUAGE
, tc
->language
) < 0)
98 if (tc
->flagEnabled
!= 1) {
100 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKFLAGENABLED
, tc
->flagEnabled
) < 0)
104 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKFLAGDEFAULT
, tc
->flagDefault
) < 0)
106 if (tc
->flagForced
) {
108 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKFLAGFORCED
, tc
->flagForced
) < 0)
113 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKMINCACHE
, tc
->minCache
) < 0)
117 /* FIXME: this won't handle NULL values, which signals that the cache is disabled. */
120 if (mk_writeUInt(ti
, MATROSKA_ID_TRACKMAXCACHE
, tc
->maxCache
) < 0)
124 switch (tc
->trackType
) {
127 if ((v
= mk_createContext(w
, ti
, MATROSKA_ID_TRACKVIDEO
)) == 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)
143 if (mk_writeUInt(v
, MATROSKA_ID_VIDEOPIXELWIDTH
, tc
->extra
.video
.pixelWidth
) < 0)
146 if (mk_writeUInt(v
, MATROSKA_ID_VIDEOPIXELHEIGHT
, tc
->extra
.video
.pixelHeight
) < 0)
149 if (mk_writeUInt(v
, MATROSKA_ID_VIDEODISPLAYWIDTH
, tc
->extra
.video
.displayWidth
) < 0)
152 if (mk_writeUInt(v
, MATROSKA_ID_VIDEODISPLAYHEIGHT
, tc
->extra
.video
.displayHeight
) < 0)
154 if (tc
->extra
.video
.displayUnit
) {
156 if (mk_writeUInt(v
, MATROSKA_ID_VIDEODISPLAYUNIT
, tc
->extra
.video
.displayUnit
) < 0)
159 if (tc
->extra
.video
.aspectRatioType
!= MK_ASPECTRATIO_FREE
) {
160 /* AspectRatioType */
161 if (mk_writeUInt(v
, MATROSKA_ID_VIDEOASPECTRATIOTYPE
, tc
->extra
.video
.aspectRatioType
) < 0)
167 if ((v
= mk_createContext(w
, ti
, MATROSKA_ID_TRACKAUDIO
)) == NULL
)
169 /* SamplingFrequency */
170 if (mk_writeFloat(v
, MATROSKA_ID_AUDIOSAMPLINGFREQ
, tc
->extra
.audio
.samplingFreq
) < 0)
173 if (mk_writeUInt(v
, MATROSKA_ID_AUDIOCHANNELS
, tc
->extra
.audio
.channels
) < 0)
175 if (tc
->extra
.audio
.bitDepth
) {
177 if (mk_writeUInt(v
, MATROSKA_ID_AUDIOBITDEPTH
, tc
->extra
.audio
.bitDepth
) < 0)
181 default: /* Other track types
182 * TODO: Implement other valid track types.
187 if (mk_closeContext(v
, 0) < 0)
189 if (mk_closeContext(ti
, 0) < 0)
195 int mk_writeTracks(mk_Writer
*w
, mk_Context
*tracks
)
197 w
->seek_data
.tracks
= w
->root
->d_cur
;
199 CHECK(mk_closeContext(w
->tracks
, 0));