aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/mkv_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/mkv_extractor.c')
-rw-r--r--src/plugins/mkv_extractor.c274
1 files changed, 120 insertions, 154 deletions
diff --git a/src/plugins/mkv_extractor.c b/src/plugins/mkv_extractor.c
index fc7489f..678b4de 100644
--- a/src/plugins/mkv_extractor.c
+++ b/src/plugins/mkv_extractor.c
@@ -48,7 +48,7 @@
48/** 48/**
49 * FIXME: document 49 * FIXME: document
50 */ 50 */
51enum 51enum MKV_TrackType
52{ 52{
53 MKV_Track_video = 1, 53 MKV_Track_video = 1,
54 MKV_Track_audio = 2, 54 MKV_Track_audio = 2,
@@ -135,12 +135,11 @@ VINTparse (const unsigned char *buffer, size_t start, size_t end,
135 135
136 136
137/** 137/**
138 * FIXME: 'unsigned int' or 'uint32_t' for ID?
139 * FIXME: document arguments, return value... 138 * FIXME: document arguments, return value...
140 */ 139 */
141static int 140static unsigned int
142elementRead (const unsigned char *buffer, size_t start, size_t end, 141elementRead (const unsigned char *buffer, size_t start, size_t end,
143 unsigned int *id, int64_t * size) 142 uint32_t *id, int64_t * size)
144{ 143{
145 int64_t tempID; 144 int64_t tempID;
146 int64_t tempsize; 145 int64_t tempsize;
@@ -155,7 +154,7 @@ elementRead (const unsigned char *buffer, size_t start, size_t end,
155 size_offset = VINTparse (buffer, start + id_offset, end, &tempsize, 1); 154 size_offset = VINTparse (buffer, start + id_offset, end, &tempsize, 1);
156 if (!size_offset) 155 if (!size_offset)
157 return 0; 156 return 0;
158 *id = (unsigned int) tempID; /*id must be <4 and must fit in uint */ 157 *id = (uint32_t) tempID;
159 *size = tempsize; 158 *size = tempsize;
160 return id_offset + size_offset; 159 return id_offset + size_offset;
161} 160}
@@ -173,15 +172,14 @@ getInt (const unsigned char *buffer, size_t start, size_t size)
173 172
174 result = 0; 173 result = 0;
175 for (c = 1; c <= size; c++) 174 for (c = 1; c <= size; c++)
176 result += buffer[start + c - 1] << (8 * (size - c)); 175 result += ((uint64_t)buffer[start + c - 1]) << (8 * (size - c));
177 return result; 176 return result;
178} 177}
179 178
180static float 179static float
181getFloat (const char *buffer, size_t start, size_t size) 180getFloat (const unsigned char *buffer, size_t start, size_t size)
182{ 181{
183 float result; 182 unsigned char tmp[4];
184 char tmp[4];
185 183
186 if (size != sizeof (float)) 184 if (size != sizeof (float))
187 return 0.0; 185 return 0.0;
@@ -193,7 +191,7 @@ getFloat (const char *buffer, size_t start, size_t size)
193 tmp[3] = buffer[start]; 191 tmp[3] = buffer[start];
194 return *((float *) (tmp)); 192 return *((float *) (tmp));
195 } 193 }
196 return result; 194 return 0.0;
197} 195}
198 196
199static const unsigned int MKV_Parse_list[] = { 197static const unsigned int MKV_Parse_list[] = {
@@ -216,27 +214,27 @@ EXTRACTOR_mkv_extract (const unsigned char *data, size_t size,
216 const char *options) 214 const char *options)
217{ 215{
218 int ret; 216 int ret;
219 char buffer[128]; 217 char buffer[256];
220 char temp[128]; 218 size_t p;
221 size_t p; /*pointer in buffer */ 219 int c;
222 int c, c2; /*counter in some loops */ 220 uint32_t eID;
223 unsigned int eID; /*element ID */ 221 int64_t eSize; /* signed? */
224 int64_t eSize; /*Size of element content */ 222 unsigned int offs;
225 int offs;
226 int64_t timescale = 1000000; 223 int64_t timescale = 1000000;
227 float duration = -1.0; 224 float duration = -1.0;
228 int64_t DefaultDuration = 0; 225 enum MKV_TrackType trackType;
229 int TrackType = 0; 226 int have_audio = 0;
230 int pvt_look_flag = 0; 227 int have_video = 0;
231 int curr_c = -1; 228 unsigned int value_width = 0;
232 int a_c = -1; 229 unsigned int value_height = 0;
233 int v_c = -1; 230 int64_t value;
234 int t_c = -1;
235 int value_width = 0;
236 int value_height = 0;
237 int value = 0;
238 size_t size1; 231 size_t size1;
239 const unsigned char *start; 232 const unsigned char *start;
233 int is_mkv = 0;
234 unsigned int fps = 0;
235 unsigned int bit_depth = 0;
236 const unsigned char *codec = NULL;
237 int codec_strlen = 0;
240 238
241 if (size > 32 * 1024) 239 if (size > 32 * 1024)
242 size1 = 32 * 1024; 240 size1 = 32 * 1024;
@@ -255,125 +253,65 @@ EXTRACTOR_mkv_extract (const unsigned char *data, size_t size,
255 p += offs; 253 p += offs;
256 if (!offs || p >= size) 254 if (!offs || p >= size)
257 break; 255 break;
256 if (MKVID_EBML == eID)
257 {
258 ADD ("video/mkv", EXTRACTOR_METATYPE_MIMETYPE);
259 is_mkv = 1;
260 continue;
261 }
262 if (! is_mkv)
263 return 0;
258 for (c = 0; c < sizeof (MKV_Parse_list) / sizeof (*MKV_Parse_list); c++) 264 for (c = 0; c < sizeof (MKV_Parse_list) / sizeof (*MKV_Parse_list); c++)
259 if (MKV_Parse_list[c] == eID) 265 if (MKV_Parse_list[c] == eID)
260 { 266 break;
261 break;
262 }
263 if (c < sizeof (MKV_Parse_list) / sizeof (*MKV_Parse_list)) 267 if (c < sizeof (MKV_Parse_list) / sizeof (*MKV_Parse_list))
264 continue; 268 continue;
269
265 if (p + eSize > size) 270 if (p + eSize > size)
266 break; /*TODO - add (if requied) suckup from file to data */ 271 break;
267 if (eSize == 4 || eSize == 8 || eSize == 1 || eSize == 2)
268 value = (int) getInt (data, p, eSize);
269 272
273 if ( (eSize == 4) || (eSize == 8) || (eSize == 1) || (eSize == 2))
274 value = getInt (data, p, eSize);
275
270 switch (eID) 276 switch (eID)
271 { 277 {
272 case MKVID_TrackType: /*detect a stream type (video/audio/text) */ 278 case MKVID_TrackType: /*detect a stream type (video/audio/text) */
273 TrackType = value; 279 trackType = (enum MKV_TrackType) value;
274 pvt_look_flag = 0; 280 switch (trackType)
275 switch (TrackType)
276 { 281 {
277 case MKV_Track_video: 282 case MKV_Track_video:
278 v_c++; 283 have_video = 1;
279 if (v_c > MAX_STREAMS)
280 v_c = MAX_STREAMS;
281 if (duration != -1.0)
282 {
283 /* FIXME: duration might still be -1 here, defer until
284 end of function & check if duration is != -1 */
285 snprintf (buffer,
286 sizeof(buffer),
287 "%u s (video)",
288 (int) (duration / 1e+9 * (float) timescale));
289 ADD (buffer, EXTRACTOR_METATYPE_DURATION);
290 }
291 curr_c = v_c;
292 break; 284 break;
293 case MKV_Track_audio: 285 case MKV_Track_audio:
294 a_c++; 286 have_audio = 1;
295 if (a_c > MAX_STREAMS)
296 a_c = MAX_STREAMS;
297 if (duration != -1.0)
298 {
299 /* FIXME: duration might still be -1 here, defer until
300 end of function & check if duration is != -1 */
301 snprintf (buffer,
302 sizeof (buffer),
303 "%u s (audio)",
304 (unsigned int) (duration / 1e+9 * (float) timescale));
305 ADD (buffer, EXTRACTOR_METATYPE_DURATION);
306 }
307 curr_c = a_c;
308 break; 287 break;
288 case MKV_Track_subtitle:
289 break;
309 case MKV_Track_subtitle_orig: 290 case MKV_Track_subtitle_orig:
310 t_c++; 291 break;
311 TrackType = MKV_Track_subtitle; /*for normal use in lang array */
312 if (t_c > MAX_STREAMS)
313 t_c = MAX_STREAMS;
314 curr_c = t_c;
315 break;
316 } 292 }
317 break; 293 break;
318 case MKVID_DefaultDuration: /*fps detection */ 294 case MKVID_DefaultDuration:
319 if (TrackType == MKV_Track_video && v_c >= 0) 295 fps = (unsigned int) (1000000000 / value);
320 {
321 DefaultDuration = value;
322 if (DefaultDuration > 100)
323 {
324 /* FIXME: integrate with codec name/id into 'METATYPE_FORMAT' */
325 snprintf (buffer,
326 sizeof (buffer),
327 "fps: %u", 1000000000 / DefaultDuration);
328 ADD (buffer, EXTRACTOR_METATYPE_UNKNOWN);
329 }
330 }
331 break; 296 break;
332 case MKVID_Language: /*stream language */ 297 case MKVID_Language:
333 if (curr_c >= 0 && TrackType < 4 && eSize < MAX_STRING_SIZE) 298 snprintf (buffer,
334 { 299 sizeof (buffer),
335 /* FIXME: why first temp, then buffer? */ 300 "%.*s",
336 snprintf (buffer, 301 (int) eSize,
337 sizeof (buffer), 302 data + p);
338 "%.*s", 303 ADD (buffer, EXTRACTOR_METATYPE_LANGUAGE);
339 (int) eSize,
340 data + p);
341 ADD (buffer, EXTRACTOR_METATYPE_LANGUAGE);
342 }
343 break; 304 break;
344 case MKVID_CodecName: /*passtrough */ 305 case MKVID_CodecName:
345 case MKVID_CodecID: /*codec detection (if V_MS/VFW/FOURCC - set a fourcc code, else fill a vcodecs value) */ 306 case MKVID_CodecID:
346 if (curr_c >= 0 && TrackType < 4 && eSize < MAX_STRING_SIZE) 307 codec = data + p;
347 { 308 codec_strlen = eSize;
348 if (!strncmp (data + p, "V_MS/VFW/FOURCC", eSize))
349 pvt_look_flag = 1;
350 snprintf (buffer,
351 sizeof (buffer),
352 "codec: %.*s",
353 (int) eSize,
354 data + p);
355 ADD (buffer,
356 EXTRACTOR_METATYPE_FORMAT);
357 }
358 break; 309 break;
359 case MKVID_CodecPrivate: 310 case MKVID_CodecPrivate:
360 if (pvt_look_flag && v_c >= 0 && eSize >= 24)
361 { /*CodecPrivate contains a BITMAPINFOHEADER structure due CodecID==V_MS/VFW/FOURCC */
362 pvt_look_flag = 0;
363 //TODO
364 /*
365 video[v_c][V_cc]=(buffer[p+16]<<24)+(buffer[p+17]<<16)+(buffer[p+18]<<8)+buffer[p+19];
366 if (codec[v_c][MKV_Track_video])
367 {
368 free (codec[v_c][MKV_Track_video]);
369 codec[v_c][MKV_Track_video] = NULL;
370 }
371 */
372 }
373 break; 311 break;
374 case MKVID_PixelWidth: /*pasthough *//*bug with aspect differ from 1:1 */ 312 case MKVID_PixelWidth: /*pasthough *//*bug with aspect differ from 1:1 */
375 case MKVID_DisplayWidth: 313 case MKVID_DisplayWidth:
376 value_width = value; 314 value_width = value;
377 break; 315 break;
378 case MKVID_PixelHeight: /*pasthough */ 316 case MKVID_PixelHeight: /*pasthough */
379 case MKVID_DisplayHeight: 317 case MKVID_DisplayHeight:
@@ -381,60 +319,88 @@ EXTRACTOR_mkv_extract (const unsigned char *data, size_t size,
381 break; 319 break;
382 case MKVID_TimeCodeScale: 320 case MKVID_TimeCodeScale:
383 timescale = getInt (data, p, eSize); 321 timescale = getInt (data, p, eSize);
384 snprintf (buffer,
385 sizeof (buffer),
386 "TimeScale: %u", timescale);
387 ADD (buffer, EXTRACTOR_METATYPE_UNKNOWN);
388 break; 322 break;
389 case MKVID_Duration: 323 case MKVID_Duration:
390 duration = getFloat (data, p, eSize); 324 duration = getFloat (data, p, eSize);
391 snprintf (buffer,
392 sizeof (buffer),
393 "%f ms", duration);
394 ADD (buffer, EXTRACTOR_METATYPE_DURATION);
395 break; 325 break;
396 case MKVID_Channels: 326 case MKVID_Channels:
397 snprintf (buffer, 327 /* num_channels = (unsigned int) value; */
398 sizeof (buffer),
399 "channels: %u", value);
400 ADD (buffer, EXTRACTOR_METATYPE_UNKNOWN);
401 break; 328 break;
402 case MKVID_BitDepth: 329 case MKVID_BitDepth:
403 snprintf (buffer, 330 bit_depth = (unsigned int) value;
404 sizeof (buffer),
405 "BitDepth: %u", value);
406 ADD (buffer, EXTRACTOR_METATYPE_UNKNOWN);
407 break; 331 break;
408 case MKVID_OutputSamplingFrequency: /*pasthough */ 332 case MKVID_OutputSamplingFrequency:
409 case MKVID_SamplingFrequency: 333 case MKVID_SamplingFrequency:
410 /* FIXME: the resulting value seems wrong... Unit? */ 334 /* FIXME: what unit has 'value'? */
411 snprintf (buffer,
412 sizeof (buffer),
413 "Sampling Frequency: %u", value);
414 ADD (buffer, EXTRACTOR_METATYPE_UNKNOWN);
415 break;
416 break; 335 break;
417 case MKVID_Title: 336 case MKVID_Title:
418 if (eSize > MAX_STRING_SIZE) 337 if (eSize > MAX_STRING_SIZE)
419 break; 338 break;
420 strncpy(temp,data+p,eSize); 339 snprintf (buffer,
421 temp[eSize] = '\0'; 340 sizeof (buffer),
422 ADD (temp, EXTRACTOR_METATYPE_TITLE); 341 "%.*s",
342 (int) eSize,
343 (const char*) data + p);
344 ADD (buffer, EXTRACTOR_METATYPE_TITLE);
345 break;
346 default:
423 break; 347 break;
424/*TODO case MKVID_Tags:*/
425 } 348 }
426 p += eSize; /*skip unknown or uninteresting */ 349 p += eSize; /*skip unknown or uninteresting */
427 } 350 }
428 while (1); 351 while (1);
352
353 snprintf (buffer,
354 sizeof (buffer),
355 "%u s (%s%s%s)",
356 (unsigned int) (duration / 1e+9 * (float) timescale),
357 (have_audio ? "audio" : ""),
358 ((have_audio && have_video) ? "/" : ""),
359 (have_video ? "video" : ""));
360 if ( (have_audio || have_video) && (duration >= 0.0) )
361 ADD (buffer, EXTRACTOR_METATYPE_DURATION);
429 if ( (value_width != 0) && (value_height != 0) ) 362 if ( (value_width != 0) && (value_height != 0) )
363 {
430 snprintf (buffer, 364 snprintf (buffer,
431 sizeof(buffer), 365 sizeof(buffer),
432 "%ux%u", 366 "%ux%u",
433 value_width, value_height); 367 value_width, value_height);
434 ADD (buffer, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS); 368 ADD (buffer, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS);
435 369 }
436EXIT:
437 370
371 if (NULL != codec)
372 {
373 if ( (fps != 0) && (bit_depth != 0) )
374 snprintf (buffer,
375 sizeof (buffer),
376 "%.*s (%u fps, %u bit)",
377 codec_strlen,
378 codec,
379 fps,
380 bit_depth);
381 else if (fps != 0)
382 snprintf (buffer,
383 sizeof (buffer),
384 "%.*s (%u fps)",
385 codec_strlen,
386 codec,
387 fps);
388 else if (bit_depth != 0)
389 snprintf (buffer,
390 sizeof (buffer),
391 "%.*s (%u bit)",
392 codec_strlen,
393 codec,
394 bit_depth);
395 else
396 snprintf (buffer,
397 sizeof (buffer),
398 "%.*s",
399 codec_strlen,
400 codec);
401 ADD (buffer,
402 EXTRACTOR_METATYPE_FORMAT);
403 }
404EXIT:
438 return ret; 405 return ret;
439
440} 406}