2
* Copyright (C) 2007 Haakon Sporsheim <hakon.sporsheim@tandberg.com>
3
* 2008 Ole Andr� Vadla Ravn�s <ole.andre.ravnas@tandberg.com>
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Library General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Library General Public License for more details.
15
* You should have received a copy of the GNU Library General Public
16
* License along with this library; if not, write to the
17
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
* Boston, MA 02111-1307, USA.
21
#include "ksvideohelpers.h"
24
#include "kshelpers.h"
26
GST_DEBUG_CATEGORY_EXTERN (gst_ks_debug);
27
#define GST_CAT_DEFAULT gst_ks_debug
29
static const GUID MEDIASUBTYPE_FOURCC =
30
{ 0x0 /* FourCC here */ , 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00,
34
extern const GUID MEDIASUBTYPE_I420 =
35
{ 0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
40
ks_video_format_to_structure (GUID subtype_guid, GUID format_guid)
42
GstStructure *structure = NULL;
44
if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_MJPG) || IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_TVMJ) || /* FIXME: NOT tested */
45
IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_WAKE) || /* FIXME: NOT tested */
46
IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_CFCC) || /* FIXME: NOT tested */
47
IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_IJPG)) { /* FIXME: NOT tested */
48
structure = gst_structure_new ("image/jpeg", NULL);
49
} else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB555) || /* FIXME: NOT tested */
50
IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB565) || /* FIXME: NOT tested */
51
IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB24) || IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB32) || /* FIXME: NOT tested */
52
IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_ARGB1555) || /* FIXME: NOT tested */
53
IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_ARGB32) || /* FIXME: NOT tested */
54
IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_ARGB4444)) { /* FIXME: NOT tested */
55
guint depth = 0, bpp = 0;
57
guint32 r_mask = 0, b_mask = 0, g_mask = 0;
59
if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB555)) {
62
endianness = G_BIG_ENDIAN;
66
} else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB565)) {
68
endianness = G_BIG_ENDIAN;
72
} else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB24)) {
74
endianness = G_BIG_ENDIAN;
78
} else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB32)) {
81
endianness = G_BIG_ENDIAN;
90
} else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_ARGB1555)) {
93
endianness = G_BIG_ENDIAN;
97
} else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_ARGB32)) {
99
endianness = G_BIG_ENDIAN;
104
*r_mask = 0xff000000;
105
*g_mask = 0x00ff0000;
106
*b_mask = 0x0000ff00;
108
} else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_ARGB4444)) {
111
endianness = G_BIG_ENDIAN;
119
g_assert_not_reached ();
122
structure = gst_structure_new ("video/x-raw-rgb",
123
"bpp", G_TYPE_INT, bpp,
124
"depth", G_TYPE_INT, depth,
125
"red_mask", G_TYPE_INT, r_mask,
126
"green_mask", G_TYPE_INT, g_mask,
127
"blue_mask", G_TYPE_INT, b_mask,
128
"endianness", G_TYPE_INT, endianness, NULL);
129
} else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_dvsd)) {
130
if (IsEqualGUID (&format_guid, &FORMAT_DvInfo)) {
131
structure = gst_structure_new ("video/x-dv",
132
"systemstream", G_TYPE_BOOLEAN, TRUE, NULL);
133
} else if (IsEqualGUID (&format_guid, &FORMAT_VideoInfo)) {
134
structure = gst_structure_new ("video/x-dv",
135
"systemstream", G_TYPE_BOOLEAN, FALSE,
136
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('d', 'v', 's', 'd'),
139
} else if (memcmp (&subtype_guid.Data2, &MEDIASUBTYPE_FOURCC.Data2,
140
sizeof (subtype_guid) - sizeof (subtype_guid.Data1)) == 0) {
141
guint8 *p = (guint8 *) & subtype_guid.Data1;
143
structure = gst_structure_new ("video/x-raw-yuv",
144
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC (p[0], p[1], p[2], p[3]),
149
GST_DEBUG ("Unknown DirectShow Video GUID %08x-%04x-%04x-%04x-%08x%04x",
150
subtype_guid.Data1, subtype_guid.Data2, subtype_guid.Data3,
151
*(WORD *) subtype_guid.Data4, *(DWORD *) & subtype_guid.Data4[2],
152
*(WORD *) & subtype_guid.Data4[6]);
159
ks_video_append_video_stream_cfg_fields (GstStructure * structure,
160
const KS_VIDEO_STREAM_CONFIG_CAPS * vscc)
162
g_return_val_if_fail (structure, FALSE);
163
g_return_val_if_fail (vscc, FALSE);
166
if (vscc->MinOutputSize.cx == vscc->MaxOutputSize.cx) {
167
gst_structure_set (structure,
168
"width", G_TYPE_INT, vscc->MaxOutputSize.cx, NULL);
170
gst_structure_set (structure,
171
"width", GST_TYPE_INT_RANGE,
172
vscc->MinOutputSize.cx, vscc->MaxOutputSize.cx, NULL);
176
if (vscc->MinOutputSize.cy == vscc->MaxOutputSize.cy) {
177
gst_structure_set (structure,
178
"height", G_TYPE_INT, vscc->MaxOutputSize.cy, NULL);
180
gst_structure_set (structure,
181
"height", GST_TYPE_INT_RANGE,
182
vscc->MinOutputSize.cy, vscc->MaxOutputSize.cy, NULL);
186
if (vscc->MinFrameInterval == vscc->MaxFrameInterval) {
187
gst_structure_set (structure,
188
"framerate", GST_TYPE_FRACTION,
189
(gint) (10000000 / vscc->MaxFrameInterval), 1, NULL);
191
gst_structure_set (structure,
192
"framerate", GST_TYPE_FRACTION_RANGE,
193
(gint) (10000000 / vscc->MaxFrameInterval), 1,
194
(gint) (10000000 / vscc->MinFrameInterval), 1, NULL);
201
ks_video_media_type_dup (KsVideoMediaType * media_type)
203
KsVideoMediaType *result = g_new (KsVideoMediaType, 1);
205
memcpy (result, media_type, sizeof (KsVideoMediaType));
207
result->range = g_malloc (media_type->range->FormatSize);
208
memcpy ((gpointer) result->range, media_type->range,
209
media_type->range->FormatSize);
211
result->format = g_malloc (media_type->format_size);
212
memcpy (result->format, media_type->format, media_type->format_size);
214
result->translated_caps = gst_caps_ref (media_type->translated_caps);
220
ks_video_media_type_free (KsVideoMediaType * media_type)
222
if (media_type == NULL)
225
g_free ((gpointer) media_type->range);
227
g_free (media_type->format);
229
if (media_type->translated_caps != NULL)
230
gst_caps_unref (media_type->translated_caps);
236
ks_video_media_type_list_remove_duplicates (GList * media_types)
238
GList *master, *duplicates;
243
master = duplicates = NULL;
245
/* Find the first set of duplicates and their master */
246
for (entry = media_types; entry != NULL && duplicates == NULL;
247
entry = entry->next) {
248
KsVideoMediaType *mt = entry->data;
251
for (other_entry = media_types; other_entry != NULL;
252
other_entry = other_entry->next) {
253
KsVideoMediaType *other_mt = other_entry->data;
258
if (gst_caps_is_equal (mt->translated_caps, other_mt->translated_caps))
259
duplicates = g_list_prepend (duplicates, other_mt);
262
if (duplicates != NULL)
266
if (duplicates != NULL) {
267
KsVideoMediaType *selected_mt = master->data;
270
* Pick a FORMAT_VideoInfo2 if present, if not we just stay with the
273
for (entry = duplicates; entry != NULL; entry = entry->next) {
274
KsVideoMediaType *mt = entry->data;
276
if (IsEqualGUID (&mt->range->Specifier, &FORMAT_VideoInfo2)) {
277
ks_video_media_type_free (selected_mt);
280
ks_video_media_type_free (mt);
283
/* Remove the dupe from the main list */
284
media_types = g_list_remove (media_types, mt);
287
/* Update master node with the selected MediaType */
288
master->data = selected_mt;
290
g_list_free (duplicates);
293
while (master != NULL);
299
ks_video_probe_filter_for_caps (HANDLE filter_handle)
305
if (!ks_filter_get_pin_property (filter_handle, 0, KSPROPSETID_Pin,
306
KSPROPERTY_PIN_CTYPES, &pin_count, sizeof (pin_count)))
309
GST_DEBUG ("pin_count = %d", pin_count);
311
for (pin_id = 0; pin_id < pin_count; pin_id++) {
312
KSPIN_COMMUNICATION pin_comm;
313
KSPIN_DATAFLOW pin_flow;
316
if (!ks_filter_get_pin_property (filter_handle, pin_id, KSPROPSETID_Pin,
317
KSPROPERTY_PIN_COMMUNICATION, &pin_comm, sizeof (pin_comm)))
320
if (!ks_filter_get_pin_property (filter_handle, pin_id, KSPROPSETID_Pin,
321
KSPROPERTY_PIN_DATAFLOW, &pin_flow, sizeof (pin_flow)))
324
if (!ks_filter_get_pin_property (filter_handle, pin_id, KSPROPSETID_Pin,
325
KSPROPERTY_PIN_CATEGORY, &pin_cat, sizeof (pin_cat)))
328
GST_DEBUG ("pin[%d]: pin_comm=%d, pin_flow=%d", pin_id, pin_comm, pin_flow);
330
if (pin_flow == KSPIN_DATAFLOW_OUT &&
331
memcmp (&pin_cat, &PINNAME_CAPTURE, sizeof (GUID)) == 0) {
332
KSMULTIPLE_ITEM *items;
334
if (ks_filter_get_pin_property_multi (filter_handle, pin_id,
335
KSPROPSETID_Pin, KSPROPERTY_PIN_DATARANGES, &items)) {
336
KSDATARANGE *range = (KSDATARANGE *) (items + 1);
339
for (i = 0; i < items->Count; i++) {
340
if (IsEqualGUID (&range->MajorFormat, &KSDATAFORMAT_TYPE_VIDEO)) {
341
KsVideoMediaType *entry;
342
gpointer src_vscc, src_format;
343
GstStructure *media_structure;
345
entry = g_new0 (KsVideoMediaType, 1);
346
entry->pin_id = pin_id;
348
entry->range = g_malloc (range->FormatSize);
349
memcpy ((gpointer) entry->range, range, range->FormatSize);
351
if (IsEqualGUID (&range->Specifier, &FORMAT_VideoInfo)) {
352
KS_DATARANGE_VIDEO *vr = (KS_DATARANGE_VIDEO *) entry->range;
354
src_vscc = &vr->ConfigCaps;
355
src_format = &vr->VideoInfoHeader;
357
entry->format_size = sizeof (vr->VideoInfoHeader);
358
entry->sample_size = vr->VideoInfoHeader.bmiHeader.biSizeImage;
359
} else if (IsEqualGUID (&range->Specifier, &FORMAT_VideoInfo2)) {
360
KS_DATARANGE_VIDEO2 *vr = (KS_DATARANGE_VIDEO2 *) entry->range;
362
src_vscc = &vr->ConfigCaps;
363
src_format = &vr->VideoInfoHeader;
365
entry->format_size = sizeof (vr->VideoInfoHeader);
366
entry->sample_size = vr->VideoInfoHeader.bmiHeader.biSizeImage;
367
} else if (IsEqualGUID (&range->Specifier, &FORMAT_MPEGVideo)) {
368
/* Untested and probably wrong... */
369
KS_DATARANGE_MPEG1_VIDEO *vr =
370
(KS_DATARANGE_MPEG1_VIDEO *) entry->range;
372
src_vscc = &vr->ConfigCaps;
373
src_format = &vr->VideoInfoHeader;
375
entry->format_size = sizeof (vr->VideoInfoHeader);
377
vr->VideoInfoHeader.hdr.bmiHeader.biSizeImage;
378
} else if (IsEqualGUID (&range->Specifier, &FORMAT_MPEG2Video)) {
379
/* Untested and probably wrong... */
380
KS_DATARANGE_MPEG2_VIDEO *vr =
381
(KS_DATARANGE_MPEG2_VIDEO *) entry->range;
383
src_vscc = &vr->ConfigCaps;
384
src_format = &vr->VideoInfoHeader;
386
entry->format_size = sizeof (vr->VideoInfoHeader);
388
vr->VideoInfoHeader.hdr.bmiHeader.biSizeImage;
390
g_assert_not_reached ();
392
g_assert (entry->sample_size != 0);
394
memcpy ((gpointer) & entry->vscc, src_vscc, sizeof (entry->vscc));
396
entry->format = g_malloc (entry->format_size);
397
memcpy (entry->format, src_format, entry->format_size);
400
ks_video_format_to_structure (range->SubFormat,
403
if (media_structure == NULL) {
404
g_warning ("ks_video_format_to_structure returned NULL");
405
ks_video_media_type_free (entry);
407
} else if (ks_video_append_video_stream_cfg_fields (media_structure,
409
entry->translated_caps = gst_caps_new_empty ();
410
gst_caps_append_structure (entry->translated_caps,
413
gst_structure_free (media_structure);
414
ks_video_media_type_free (entry);
419
ret = g_list_prepend (ret, entry);
422
/* REVISIT: Each KSDATARANGE should start on a 64-bit boundary */
423
range = (KSDATARANGE *) (((guchar *) range) + range->FormatSize);
432
ret = g_list_reverse (ret);
433
ret = ks_video_media_type_list_remove_duplicates (ret);
441
ks_video_create_pin_conn_from_media_type (KsVideoMediaType * media_type)
443
KSPIN_CONNECT *conn = NULL;
444
KSDATAFORMAT *format = NULL;
447
conn = g_malloc0 (sizeof (KSPIN_CONNECT) + sizeof (KSDATAFORMAT) +
448
media_type->format_size);
450
conn->Interface.Set = KSINTERFACESETID_Standard;
451
conn->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
452
conn->Interface.Flags = 0;
454
conn->Medium.Set = KSMEDIUMSETID_Standard;
455
conn->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
456
conn->Medium.Flags = 0;
458
conn->PinId = media_type->pin_id;
459
conn->PinToHandle = NULL;
460
conn->Priority.PriorityClass = KSPRIORITY_NORMAL;
461
conn->Priority.PrioritySubClass = 1;
463
format = (KSDATAFORMAT *) (conn + 1);
464
memcpy (format, media_type->range, sizeof (KSDATAFORMAT));
465
format->FormatSize = sizeof (KSDATAFORMAT) + media_type->format_size;
467
vih = (guint8 *) (format + 1);
468
memcpy (vih, media_type->format, media_type->format_size);
474
ks_video_fixate_media_type (const KSDATARANGE * range,
475
guint8 * format, gint width, gint height, gint fps_n, gint fps_d)
477
DWORD dwRate = (width * height * fps_n) / fps_d;
479
g_return_val_if_fail (format != NULL, FALSE);
481
if (IsEqualGUID (&range->Specifier, &FORMAT_VideoInfo)) {
482
KS_VIDEOINFOHEADER *vih = (KS_VIDEOINFOHEADER *) format;
484
vih->AvgTimePerFrame = gst_util_uint64_scale_int (10000000, fps_d, fps_n);
485
vih->dwBitRate = dwRate * vih->bmiHeader.biBitCount;
487
g_assert (vih->bmiHeader.biWidth == width);
488
g_assert (vih->bmiHeader.biHeight == height);
489
} else if (IsEqualGUID (&range->Specifier, &FORMAT_VideoInfo2)) {
490
KS_VIDEOINFOHEADER2 *vih = (KS_VIDEOINFOHEADER2 *) format;
492
vih->AvgTimePerFrame = gst_util_uint64_scale_int (10000000, fps_d, fps_n);
493
vih->dwBitRate = dwRate * vih->bmiHeader.biBitCount;
495
g_assert (vih->bmiHeader.biWidth == width);
496
g_assert (vih->bmiHeader.biHeight == height);
497
} else if (IsEqualGUID (&range->Specifier, &FORMAT_MPEGVideo)) {
498
KS_MPEG1VIDEOINFO *vih = (KS_MPEG1VIDEOINFO *) format;
500
vih->hdr.AvgTimePerFrame =
501
gst_util_uint64_scale_int (10000000, fps_d, fps_n);
502
vih->hdr.dwBitRate = dwRate * vih->hdr.bmiHeader.biBitCount;
504
/* FIXME: set height and width? */
505
g_assert (vih->hdr.bmiHeader.biWidth == width);
506
g_assert (vih->hdr.bmiHeader.biHeight == height);
507
} else if (IsEqualGUID (&range->Specifier, &FORMAT_MPEG2Video)) {
508
KS_MPEGVIDEOINFO2 *vih = (KS_MPEGVIDEOINFO2 *) format;
510
vih->hdr.AvgTimePerFrame =
511
gst_util_uint64_scale_int (10000000, fps_d, fps_n);
512
vih->hdr.dwBitRate = dwRate * vih->hdr.bmiHeader.biBitCount;
514
/* FIXME: set height and width? */
515
g_assert (vih->hdr.bmiHeader.biWidth == width);
516
g_assert (vih->hdr.bmiHeader.biHeight == height);
524
static GstStructure *
525
ks_video_append_var_video_fields (GstStructure * structure)
528
gst_structure_set (structure,
529
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
530
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
531
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
538
ks_video_get_all_caps (void)
540
static GstCaps *caps = NULL;
543
GstStructure *structure;
544
caps = gst_caps_new_empty ();
546
/* from Windows SDK 6.0 uuids.h */
549
ks_video_append_var_video_fields (ks_video_format_to_structure
550
(MEDIASUBTYPE_RGB555, FORMAT_VideoInfo));
551
gst_caps_append_structure (caps, structure);
554
ks_video_append_var_video_fields (ks_video_format_to_structure
555
(MEDIASUBTYPE_RGB565, FORMAT_VideoInfo));
556
gst_caps_append_structure (caps, structure);
559
ks_video_append_var_video_fields (ks_video_format_to_structure
560
(MEDIASUBTYPE_RGB24, FORMAT_VideoInfo));
561
gst_caps_append_structure (caps, structure);
564
ks_video_append_var_video_fields (ks_video_format_to_structure
565
(MEDIASUBTYPE_RGB32, FORMAT_VideoInfo));
566
gst_caps_append_structure (caps, structure);
570
ks_video_append_var_video_fields (gst_structure_new ("video/x-raw-yuv",
572
gst_caps_append_structure (caps, structure);
576
ks_video_append_var_video_fields (ks_video_format_to_structure
577
(MEDIASUBTYPE_MJPG, FORMAT_VideoInfo));
578
gst_caps_append_structure (caps, structure);
581
ks_video_append_var_video_fields (ks_video_format_to_structure
582
(MEDIASUBTYPE_dvsd, FORMAT_VideoInfo));
583
gst_caps_append_structure (caps, structure);
585
structure = /* no variable video fields (width, height, framerate) */
586
ks_video_format_to_structure (MEDIASUBTYPE_dvsd, FORMAT_DvInfo);
587
gst_caps_append_structure (caps, structure);