Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
55702dbd
Commit
55702dbd
authored
Mar 07, 2014
by
Rafaël Carré
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Decklink input: factor out some SDI code
parent
9df9c4cf
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
262 additions
and
157 deletions
+262
-157
modules/access/Makefile.am
modules/access/Makefile.am
+1
-1
modules/access/decklink.cpp
modules/access/decklink.cpp
+22
-156
modules/access/sdi.c
modules/access/sdi.c
+202
-0
modules/access/sdi.h
modules/access/sdi.h
+37
-0
No files found.
modules/access/Makefile.am
View file @
55702dbd
...
...
@@ -132,7 +132,7 @@ liblinsys_sdi_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(accessdir)'
access_LTLIBRARIES
+=
$(LTLIBlinsys_hdsdi)
$(LTLIBlinsys_sdi)
EXTRA_LTLIBRARIES
+=
liblinsys_hdsdi_plugin.la liblinsys_sdi_plugin.la
libdecklink_plugin_la_SOURCES
=
access/decklink.cpp
libdecklink_plugin_la_SOURCES
=
access/decklink.cpp
access/sdi.c access/sdi.h
libdecklink_plugin_la_CXXFLAGS
=
$(AM_CFLAGS)
$(CPPFLAGS_decklink)
libdecklink_plugin_la_LIBADD
=
$(LIBS_decklink)
-ldl
if
HAVE_DECKLINK
...
...
modules/access/decklink.cpp
View file @
55702dbd
...
...
@@ -2,10 +2,10 @@
* decklink.cpp: BlackMagic DeckLink SDI input module
*****************************************************************************
* Copyright (C) 2010 Steinar H. Gunderson
* Copyright (C) 2009 Michael Niedermayer <michaelni@gmx.at>
* Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
* Copyright (C) 2012-2014 Rafaël Carré
*
* Authors: Steinar H. Gunderson <steinar+vlc@gunderson.no>
Rafaël Carré <funman@videolanorg>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
...
...
@@ -38,6 +38,8 @@
#include <DeckLinkAPI.h>
#include <DeckLinkAPIDispatch.cpp>
#include "sdi.h"
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
...
...
@@ -268,60 +270,6 @@ private:
demux_t
*
demux_
;
};
static
inline
uint32_t
av_le2ne32
(
uint32_t
val
)
{
union
{
uint32_t
v
;
uint8_t
b
[
4
];
}
u
;
u
.
v
=
val
;
return
(
u
.
b
[
0
]
<<
0
)
|
(
u
.
b
[
1
]
<<
8
)
|
(
u
.
b
[
2
]
<<
16
)
|
(
u
.
b
[
3
]
<<
24
);
}
static
void
v210_convert
(
uint16_t
*
dst
,
const
uint32_t
*
bytes
,
const
int
width
,
const
int
height
)
{
const
int
stride
=
((
width
+
47
)
/
48
)
*
48
*
8
/
3
/
4
;
uint16_t
*
y
=
&
dst
[
0
];
uint16_t
*
u
=
&
dst
[
width
*
height
*
2
/
2
];
uint16_t
*
v
=
&
dst
[
width
*
height
*
3
/
2
];
#define READ_PIXELS(a, b, c) \
do { \
val = av_le2ne32(*src++); \
*a++ = val & 0x3FF; \
*b++ = (val >> 10) & 0x3FF; \
*c++ = (val >> 20) & 0x3FF; \
} while (0)
for
(
int
h
=
0
;
h
<
height
;
h
++
)
{
const
uint32_t
*
src
=
bytes
;
uint32_t
val
=
0
;
int
w
;
for
(
w
=
0
;
w
<
width
-
5
;
w
+=
6
)
{
READ_PIXELS
(
u
,
y
,
v
);
READ_PIXELS
(
y
,
u
,
y
);
READ_PIXELS
(
v
,
y
,
u
);
READ_PIXELS
(
y
,
v
,
y
);
}
if
(
w
<
width
-
1
)
{
READ_PIXELS
(
u
,
y
,
v
);
val
=
av_le2ne32
(
*
src
++
);
*
y
++
=
val
&
0x3FF
;
}
if
(
w
<
width
-
3
)
{
*
u
++
=
(
val
>>
10
)
&
0x3FF
;
*
y
++
=
(
val
>>
20
)
&
0x3FF
;
val
=
av_le2ne32
(
*
src
++
);
*
v
++
=
val
&
0x3FF
;
*
y
++
=
(
val
>>
10
)
&
0x3FF
;
}
bytes
+=
stride
;
}
}
HRESULT
DeckLinkCaptureDelegate
::
VideoInputFrameArrived
(
IDeckLinkVideoInputFrame
*
videoFrame
,
IDeckLinkAudioInputPacket
*
audioFrame
)
{
demux_sys_t
*
sys
=
demux_
->
p_sys
;
...
...
@@ -359,97 +307,16 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame
break
;
uint16_t
dec
[
width
*
2
];
v210_convert
(
&
dec
[
0
],
buf
,
width
,
1
);
static
const
uint16_t
vanc_header
[
3
]
=
{
0
,
0x3ff
,
0x3ff
};
if
(
!
memcmp
(
vanc_header
,
dec
,
sizeof
(
vanc_header
)))
{
int
len
=
(
dec
[
5
]
&
0xff
)
+
6
+
1
;
uint16_t
vanc_sum
=
0
;
bool
parity_ok
=
true
;
for
(
int
i
=
3
;
i
<
len
-
1
;
i
++
)
{
uint16_t
v
=
dec
[
i
];
int
np
=
v
>>
8
;
int
p
=
parity
(
v
&
0xff
);
if
((
!!
p
^
!!
(
v
&
0x100
))
||
(
np
!=
1
&&
np
!=
2
))
{
parity_ok
=
false
;
break
;
}
vanc_sum
+=
v
;
vanc_sum
&=
0x1ff
;
dec
[
i
]
&=
0xff
;
}
if
(
!
parity_ok
)
continue
;
vanc_sum
|=
((
~
vanc_sum
&
0x100
)
<<
1
);
if
(
dec
[
len
-
1
]
!=
vanc_sum
)
continue
;
if
(
dec
[
3
]
!=
0x61
/* DID */
||
dec
[
4
]
!=
0x01
/* SDID = CEA-708 */
)
continue
;
/* CDP follows */
uint16_t
*
cdp
=
&
dec
[
6
];
if
(
cdp
[
0
]
!=
0x96
||
cdp
[
1
]
!=
0x69
)
continue
;
len
-=
7
;
// remove VANC header and checksum
if
(
cdp
[
2
]
!=
len
)
block_t
*
cc
=
vanc_to_cc
(
demux_
,
dec
,
width
*
2
);
if
(
!
cc
)
continue
;
uint8_t
cdp_sum
=
0
;
for
(
int
i
=
0
;
i
<
len
-
1
;
i
++
)
cdp_sum
+=
cdp
[
i
];
cdp_sum
=
cdp_sum
?
256
-
cdp_sum
:
0
;
if
(
cdp
[
len
-
1
]
!=
cdp_sum
)
continue
;
uint8_t
rate
=
cdp
[
3
];
if
(
!
(
rate
&
0x0f
))
continue
;
rate
>>=
4
;
if
(
rate
>
8
)
continue
;
if
(
!
(
cdp
[
4
]
&
0x43
))
/* ccdata_present | caption_service_active | reserved */
continue
;
uint16_t
hdr
=
(
cdp
[
5
]
<<
8
)
|
cdp
[
6
];
if
(
cdp
[
7
]
!=
0x72
)
/* ccdata_id */
continue
;
int
cc_count
=
cdp
[
8
];
if
(
!
(
cc_count
&
0xe0
))
continue
;
cc_count
&=
0x1f
;
/* FIXME: parse additional data (CC language?) */
if
((
len
-
13
)
<
cc_count
*
3
)
continue
;
if
(
cdp
[
len
-
4
]
!=
0x74
)
/* footer id */
continue
;
uint16_t
ftr
=
(
cdp
[
len
-
3
]
<<
8
)
|
cdp
[
len
-
2
];
if
(
ftr
!=
hdr
)
continue
;
block_t
*
cc
=
block_Alloc
(
cc_count
*
3
);
for
(
int
i
=
0
;
i
<
cc_count
;
i
++
)
{
cc
->
p_buffer
[
3
*
i
+
0
]
=
cdp
[
9
+
3
*
i
+
0
]
&
3
;
cc
->
p_buffer
[
3
*
i
+
1
]
=
cdp
[
9
+
3
*
i
+
1
];
cc
->
p_buffer
[
3
*
i
+
2
]
=
cdp
[
9
+
3
*
i
+
2
];
}
cc
->
i_pts
=
cc
->
i_dts
=
VLC_TS_0
+
stream_time
;
if
(
!
sys
->
cc_es
)
{
es_format_t
fmt
;
es_format_Init
(
&
fmt
,
SPU_ES
,
VLC_FOURCC
(
'c'
,
'c'
,
'1'
,
' '
)
);
fmt
.
psz_description
=
strdup
(
"Closed captions 1"
);
fmt
.
psz_description
=
strdup
(
N_
(
"Closed captions 1"
)
);
if
(
fmt
.
psz_description
)
{
sys
->
cc_es
=
es_out_Add
(
demux_
->
out
,
&
fmt
);
msg_Dbg
(
demux_
,
"Adding Closed captions stream"
);
...
...
@@ -461,7 +328,6 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame
block_Release
(
cc
);
break
;
// we found the line with Closed Caption data
}
}
vanc
->
Release
();
}
}
else
{
...
...
modules/access/sdi.c
0 → 100644
View file @
55702dbd
/*****************************************************************************
* sdi.c: SDI helpers
*****************************************************************************
* Copyright (C) 2014 Rafaël Carré
* Copyright (C) 2009 Michael Niedermayer <michaelni@gmx.at>
* Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "sdi.h"
static
inline
uint32_t
av_le2ne32
(
uint32_t
val
)
{
union
{
uint32_t
v
;
uint8_t
b
[
4
];
}
u
;
u
.
v
=
val
;
return
(
u
.
b
[
0
]
<<
0
)
|
(
u
.
b
[
1
]
<<
8
)
|
(
u
.
b
[
2
]
<<
16
)
|
(
u
.
b
[
3
]
<<
24
);
}
void
v210_convert
(
uint16_t
*
dst
,
const
uint32_t
*
bytes
,
const
int
width
,
const
int
height
)
{
const
int
stride
=
((
width
+
47
)
/
48
)
*
48
*
8
/
3
/
4
;
uint16_t
*
y
=
&
dst
[
0
];
uint16_t
*
u
=
&
dst
[
width
*
height
*
2
/
2
];
uint16_t
*
v
=
&
dst
[
width
*
height
*
3
/
2
];
#define READ_PIXELS(a, b, c) \
do { \
val = av_le2ne32(*src++); \
*a++ = val & 0x3FF; \
*b++ = (val >> 10) & 0x3FF; \
*c++ = (val >> 20) & 0x3FF; \
} while (0)
for
(
int
h
=
0
;
h
<
height
;
h
++
)
{
const
uint32_t
*
src
=
bytes
;
uint32_t
val
=
0
;
int
w
;
for
(
w
=
0
;
w
<
width
-
5
;
w
+=
6
)
{
READ_PIXELS
(
u
,
y
,
v
);
READ_PIXELS
(
y
,
u
,
y
);
READ_PIXELS
(
v
,
y
,
u
);
READ_PIXELS
(
y
,
v
,
y
);
}
if
(
w
<
width
-
1
)
{
READ_PIXELS
(
u
,
y
,
v
);
val
=
av_le2ne32
(
*
src
++
);
*
y
++
=
val
&
0x3FF
;
}
if
(
w
<
width
-
3
)
{
*
u
++
=
(
val
>>
10
)
&
0x3FF
;
*
y
++
=
(
val
>>
20
)
&
0x3FF
;
val
=
av_le2ne32
(
*
src
++
);
*
v
++
=
val
&
0x3FF
;
*
y
++
=
(
val
>>
10
)
&
0x3FF
;
}
bytes
+=
stride
;
}
}
#undef vanc_to_cc
block_t
*
vanc_to_cc
(
vlc_object_t
*
obj
,
uint16_t
*
buf
,
size_t
words
)
{
if
(
words
<
3
)
{
msg_Err
(
obj
,
"VANC line too small (%zu words)"
,
words
);
return
NULL
;
}
static
const
uint8_t
vanc_header
[
6
]
=
{
0x00
,
0x00
,
0xff
,
0x03
,
0xff
,
0x03
};
if
(
memcmp
(
vanc_header
,
buf
,
3
*
2
))
{
/* Does not start with the VANC header */
return
NULL
;
}
size_t
len
=
(
buf
[
5
]
&
0xff
)
+
6
+
1
;
if
(
len
>
words
)
{
msg_Err
(
obj
,
"Data Count (%zu) > line length (%zu)"
,
len
,
words
);
return
NULL
;
}
uint16_t
vanc_sum
=
0
;
for
(
size_t
i
=
3
;
i
<
len
-
1
;
i
++
)
{
uint16_t
v
=
buf
[
i
];
int
np
=
v
>>
8
;
int
p
=
parity
(
v
&
0xff
);
if
((
!!
p
^
!!
(
v
&
0x100
))
||
(
np
!=
1
&&
np
!=
2
))
{
msg_Err
(
obj
,
"Parity incorrect for word %zu"
,
i
);
return
NULL
;
}
vanc_sum
+=
v
;
vanc_sum
&=
0x1ff
;
buf
[
i
]
&=
0xff
;
}
vanc_sum
|=
((
~
vanc_sum
&
0x100
)
<<
1
);
if
(
buf
[
len
-
1
]
!=
vanc_sum
)
{
msg_Err
(
obj
,
"VANC checksum incorrect: 0x%.4x != 0x%.4x"
,
vanc_sum
,
buf
[
len
-
1
]);
return
NULL
;
}
if
(
buf
[
3
]
!=
0x61
/* DID */
||
buf
[
4
]
!=
0x01
/* SDID = CEA-708 */
)
{
//msg_Err(obj, "Not a CEA-708 packet: DID = 0x%.2x SDID = 0x%.2x", buf[3], buf[4]);
// XXX : what is Not a CEA-708 packet: DID = 0x61 SDID = 0x02 ?
return
NULL
;
}
/* CDP follows */
uint16_t
*
cdp
=
&
buf
[
6
];
if
(
cdp
[
0
]
!=
0x96
||
cdp
[
1
]
!=
0x69
)
{
msg_Err
(
obj
,
"Invalid CDP header 0x%.2x 0x%.2x"
,
cdp
[
0
],
cdp
[
1
]);
return
NULL
;
}
len
-=
7
;
// remove VANC header and checksum
if
(
cdp
[
2
]
!=
len
)
{
msg_Err
(
obj
,
"CDP len %d != %zu"
,
cdp
[
2
],
len
);
return
NULL
;
}
uint8_t
cdp_sum
=
0
;
for
(
size_t
i
=
0
;
i
<
len
-
1
;
i
++
)
cdp_sum
+=
cdp
[
i
];
cdp_sum
=
cdp_sum
?
256
-
cdp_sum
:
0
;
if
(
cdp
[
len
-
1
]
!=
cdp_sum
)
{
msg_Err
(
obj
,
"CDP checksum invalid 0x%.4x != 0x%.4x"
,
cdp_sum
,
cdp
[
len
-
1
]);
return
NULL
;
}
uint8_t
rate
=
cdp
[
3
];
if
(
!
(
rate
&
0x0f
))
{
msg_Err
(
obj
,
"CDP frame rate invalid (0x%.2x)"
,
rate
);
return
NULL
;
}
rate
>>=
4
;
if
(
rate
>
8
)
{
msg_Err
(
obj
,
"CDP frame rate invalid (0x%.2x)"
,
rate
);
return
NULL
;
}
if
(
!
(
cdp
[
4
]
&
0x43
))
/* ccdata_present | caption_service_active | reserved */
{
msg_Err
(
obj
,
"CDP flags invalid (0x%.2x)"
,
cdp
[
4
]);
return
NULL
;
}
uint16_t
hdr
=
(
cdp
[
5
]
<<
8
)
|
cdp
[
6
];
if
(
cdp
[
7
]
!=
0x72
)
/* ccdata_id */
{
msg_Err
(
obj
,
"Invalid ccdata_id 0x%.2x"
,
cdp
[
7
]);
return
NULL
;
}
unsigned
cc_count
=
cdp
[
8
];
if
(
!
(
cc_count
&
0xe0
))
{
msg_Err
(
obj
,
"Invalid cc_count 0x%.2x"
,
cc_count
);
return
NULL
;
}
cc_count
&=
0x1f
;
if
((
len
-
13
)
<
cc_count
*
3
)
{
msg_Err
(
obj
,
"Invalid cc_count %d (> %zu)"
,
cc_count
*
3
,
len
-
13
);
return
NULL
;
}
if
(
cdp
[
len
-
4
]
!=
0x74
)
/* footer id */
{
msg_Err
(
obj
,
"Invalid footer id 0x%.2x"
,
cdp
[
len
-
4
]);
return
NULL
;
}
uint16_t
ftr
=
(
cdp
[
len
-
3
]
<<
8
)
|
cdp
[
len
-
2
];
if
(
ftr
!=
hdr
)
{
msg_Err
(
obj
,
"Header 0x%.4x != Footer 0x%.4x"
,
hdr
,
ftr
);
return
NULL
;
}
block_t
*
cc
=
block_Alloc
(
cc_count
*
3
);
for
(
size_t
i
=
0
;
i
<
cc_count
;
i
++
)
{
cc
->
p_buffer
[
3
*
i
+
0
]
=
cdp
[
9
+
3
*
i
+
0
]
/* & 3 */
;
cc
->
p_buffer
[
3
*
i
+
1
]
=
cdp
[
9
+
3
*
i
+
1
];
cc
->
p_buffer
[
3
*
i
+
2
]
=
cdp
[
9
+
3
*
i
+
2
];
}
return
cc
;
}
modules/access/sdi.h
0 → 100644
View file @
55702dbd
/*****************************************************************************
* sdi.c: SDI helpers
*****************************************************************************
* Copyright (C) 2014 Rafaël Carré
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef __cplusplus
extern
"C"
{
#endif
#include <vlc_common.h>
#include <vlc_block.h>
#include <inttypes.h>
void
v210_convert
(
uint16_t
*
dst
,
const
uint32_t
*
bytes
,
const
int
width
,
const
int
height
);
block_t
*
vanc_to_cc
(
vlc_object_t
*
,
uint16_t
*
,
size_t
);
#define vanc_to_cc(obj, buf, words) vanc_to_cc(VLC_OBJECT(obj), buf, words)
#ifdef __cplusplus
}
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment