diff mbox

[FFmpeg-devel,PATCHv2,1/2] avdevice/decklink_dec: add support for decoding teletext from 10bit ancillary data

Message ID 20170707232313.5371-1-cus@passwd.hu
State Accepted
Commit cc0916bfc27e2baba7747a7503bfd183d2e8bba0
Headers show

Commit Message

Marton Balint July 7, 2017, 11:23 p.m. UTC
This also add supports for 4K DeckLink cards because they always output the
ancillary data in 10-bit.

v2:
- only try teletext decoding for 576i PAL mode
- some comments as requested by Aaron Levinson

Signed-off-by: Marton Balint <cus@passwd.hu>
---
 doc/indevs.texi              |  4 +--
 libavdevice/decklink_dec.cpp | 61 ++++++++++++++++++++++++++++++++------------
 2 files changed, 47 insertions(+), 18 deletions(-)

Comments

Marton Balint July 18, 2017, 5:10 p.m. UTC | #1
On Sat, 8 Jul 2017, Marton Balint wrote:

> This also add supports for 4K DeckLink cards because they always output the
> ancillary data in 10-bit.
>
> v2:
> - only try teletext decoding for 576i PAL mode
> - some comments as requested by Aaron Levinson
>
> Signed-off-by: Marton Balint <cus@passwd.hu>

Applied the series, thanks for all the comments.

Regards,
Marton
John Warburton July 19, 2017, 8:54 a.m. UTC | #2
On Tue, Jul 18, 2017 at 6:10 PM, Marton Balint <cus@passwd.hu> wrote:
> On Sat, 8 Jul 2017, Marton Balint wrote:
>
>> This also add supports for 4K DeckLink cards because they always output the
>> ancillary data in 10-bit.
>>
>> v2:
>> - only try teletext decoding for 576i PAL mode
>> - some comments as requested by Aaron Levinson
>>
>> Signed-off-by: Marton Balint <cus@passwd.hu>
>
> Applied the series, thanks for all the comments.

Since this patch was applied, the mingw-w64 compiler, gcc version
6.4.1, fails to link shared library avdevice-57.dll, giving the
following error. It is as if the const uint8_t ff_reverse[256] that is
found in libavutil/reverse.c somehow isn't being discovered by the
linker. I'm afraid my knowledge beyond this point is zero.

libavdevice/decklink_dec.o:decklink_dec.cpp:(.rdata$.refptr.ff_reverse[.refptr.ff_reverse]+0x0):
undefined reference to `ff_reverse'
collect2: error: ld returned 1 exit status
ffbuild/library.mak:101: recipe for target 'libavdevice/avdevice-57.dll' failed
make: *** [libavdevice/avdevice-57.dll] Error 1
Build failure. Please see error messages above.

Kind regards,
John Warburton
Marton Balint July 19, 2017, 4:48 p.m. UTC | #3
On Wed, 19 Jul 2017, John Warburton wrote:

> On Tue, Jul 18, 2017 at 6:10 PM, Marton Balint <cus@passwd.hu> wrote:
>> On Sat, 8 Jul 2017, Marton Balint wrote:
>>
>>> This also add supports for 4K DeckLink cards because they always output the
>>> ancillary data in 10-bit.
>>>
>>> v2:
>>> - only try teletext decoding for 576i PAL mode
>>> - some comments as requested by Aaron Levinson
>>>
>>> Signed-off-by: Marton Balint <cus@passwd.hu>
>>
>> Applied the series, thanks for all the comments.
>
> Since this patch was applied, the mingw-w64 compiler, gcc version
> 6.4.1, fails to link shared library avdevice-57.dll, giving the
> following error. It is as if the const uint8_t ff_reverse[256] that is
> found in libavutil/reverse.c somehow isn't being discovered by the
> linker. I'm afraid my knowledge beyond this point is zero.
>
> libavdevice/decklink_dec.o:decklink_dec.cpp:(.rdata$.refptr.ff_reverse[.refptr.ff_reverse]+0x0):
> undefined reference to `ff_reverse'
> collect2: error: ld returned 1 exit status
> ffbuild/library.mak:101: recipe for target 'libavdevice/avdevice-57.dll' failed
> make: *** [libavdevice/avdevice-57.dll] Error 1
> Build failure. Please see error messages above.

Hmmm. Does adding ff_reverse to the exported symbols in 
libavutil/libavutil.v fix the problem? Or maybe simply renaming 
every instance of ff_reverse in the codebase to avpriv_reverse?

Thanks,
Marton
Reimar Döffinger July 19, 2017, 9:55 p.m. UTC | #4
On 19.07.2017, at 18:48, Marton Balint <cus@passwd.hu> wrote:

> 
> On Wed, 19 Jul 2017, John Warburton wrote:
> 
>> On Tue, Jul 18, 2017 at 6:10 PM, Marton Balint <cus@passwd.hu> wrote:
>>> On Sat, 8 Jul 2017, Marton Balint wrote:
>>> 
>>>> This also add supports for 4K DeckLink cards because they always output the
>>>> ancillary data in 10-bit.
>>>> 
>>>> v2:
>>>> - only try teletext decoding for 576i PAL mode
>>>> - some comments as requested by Aaron Levinson
>>>> 
>>>> Signed-off-by: Marton Balint <cus@passwd.hu>
>>> 
>>> Applied the series, thanks for all the comments.
>> 
>> Since this patch was applied, the mingw-w64 compiler, gcc version
>> 6.4.1, fails to link shared library avdevice-57.dll, giving the
>> following error. It is as if the const uint8_t ff_reverse[256] that is
>> found in libavutil/reverse.c somehow isn't being discovered by the
>> linker. I'm afraid my knowledge beyond this point is zero.
>> 
>> libavdevice/decklink_dec.o:decklink_dec.cpp:(.rdata$.refptr.ff_reverse[.refptr.ff_reverse]+0x0):
>> undefined reference to `ff_reverse'
>> collect2: error: ld returned 1 exit status
>> ffbuild/library.mak:101: recipe for target 'libavdevice/avdevice-57.dll' failed
>> make: *** [libavdevice/avdevice-57.dll] Error 1
>> Build failure. Please see error messages above.
> 
> Hmmm. Does adding ff_reverse to the exported symbols in libavutil/libavutil.v fix the problem? Or maybe simply renaming every instance of ff_reverse in the codebase to avpriv_reverse?

Variables/arrays cannot be reliably exported from dynamic libraries and doing so should be avoided.
Even on Linux that leads to "fun" things like copy relocations you really don't want.
diff mbox

Patch

diff --git a/doc/indevs.texi b/doc/indevs.texi
index 51c304f3ec..330617a7c9 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -250,8 +250,8 @@  specifically lines 6 to 22, and lines 318 to 335. Line 6 is the LSB in the mask.
 Selected lines which do not contain teletext information will be ignored. You
 can use the special @option{all} constant to select all possible lines, or
 @option{standard} to skip lines 6, 318 and 319, which are not compatible with all
-receivers. Capturing teletext only works for SD PAL sources in 8 bit mode.
-To use this option, ffmpeg needs to be compiled with @code{--enable-libzvbi}.
+receivers. Capturing teletext only works for SD PAL sources. To use this
+option, ffmpeg needs to be compiled with @code{--enable-libzvbi}.
 
 @item channels
 Defines number of audio channels to capture. Must be @samp{2}, @samp{8} or @samp{16}.
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 39974e3ff4..6783a0ce77 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -30,6 +30,7 @@  extern "C" {
 extern "C" {
 #include "config.h"
 #include "libavformat/avformat.h"
+#include "libavutil/avassert.h"
 #include "libavutil/avutil.h"
 #include "libavutil/common.h"
 #include "libavutil/imgutils.h"
@@ -54,21 +55,43 @@  static uint8_t calc_parity_and_line_offset(int line)
     return ret;
 }
 
-int teletext_data_unit_from_vbi_data(int line, uint8_t *src, uint8_t *tgt)
+static void fill_data_unit_head(int line, uint8_t *tgt)
+{
+    tgt[0] = 0x02; // data_unit_id
+    tgt[1] = 0x2c; // data_unit_length
+    tgt[2] = calc_parity_and_line_offset(line); // field_parity, line_offset
+    tgt[3] = 0xe4; // framing code
+}
+
+static uint8_t* teletext_data_unit_from_vbi_data(int line, uint8_t *src, uint8_t *tgt, vbi_pixfmt fmt)
 {
     vbi_bit_slicer slicer;
 
-    vbi_bit_slicer_init(&slicer, 720, 13500000, 6937500, 6937500, 0x00aaaae4, 0xffff, 18, 6, 42 * 8, VBI_MODULATION_NRZ_MSB, VBI_PIXFMT_UYVY);
+    vbi_bit_slicer_init(&slicer, 720, 13500000, 6937500, 6937500, 0x00aaaae4, 0xffff, 18, 6, 42 * 8, VBI_MODULATION_NRZ_MSB, fmt);
 
     if (vbi_bit_slice(&slicer, src, tgt + 4) == FALSE)
-        return -1;
+        return tgt;
 
-    tgt[0] = 0x02; // data_unit_id
-    tgt[1] = 0x2c; // data_unit_length
-    tgt[2] = calc_parity_and_line_offset(line); // field_parity, line_offset
-    tgt[3] = 0xe4; // framing code
+    fill_data_unit_head(line, tgt);
 
-    return 0;
+    return tgt + 46;
+}
+
+static uint8_t* teletext_data_unit_from_vbi_data_10bit(int line, uint8_t *src, uint8_t *tgt)
+{
+    uint8_t y[720];
+    uint8_t *py = y;
+    uint8_t *pend = y + 720;
+    /* The 10-bit VBI data is packed in V210, but libzvbi only supports 8-bit,
+     * so we extract the 8 MSBs of the luma component, that is enough for
+     * teletext bit slicing. */
+    while (py < pend) {
+        *py++ = (src[1] >> 4) + ((src[2] & 15) << 4);
+        *py++ = (src[4] >> 2) + ((src[5] & 3 ) << 6);
+        *py++ = (src[6] >> 6) + ((src[7] & 63) << 2);
+        src += 8;
+    }
+    return teletext_data_unit_from_vbi_data(line, y, tgt, VBI_PIXFMT_YUV420);
 }
 #endif
 
@@ -359,7 +382,7 @@  HRESULT decklink_input_callback::VideoInputFrameArrived(
         //fprintf(stderr,"Video Frame size %d ts %d\n", pkt.size, pkt.pts);
 
 #if CONFIG_LIBZVBI
-        if (!no_video && ctx->teletext_lines && videoFrame->GetPixelFormat() == bmdFormat8BitYUV && videoFrame->GetWidth() == 720) {
+        if (!no_video && ctx->teletext_lines) {
             IDeckLinkVideoFrameAncillary *vanc;
             AVPacket txt_pkt;
             uint8_t txt_buf0[1611]; // max 35 * 46 bytes decoded teletext lines + 1 byte data_identifier
@@ -368,16 +391,22 @@  HRESULT decklink_input_callback::VideoInputFrameArrived(
             if (videoFrame->GetAncillaryData(&vanc) == S_OK) {
                 int i;
                 int64_t line_mask = 1;
+                BMDPixelFormat vanc_format = vanc->GetPixelFormat();
                 txt_buf[0] = 0x10;    // data_identifier - EBU_data
                 txt_buf++;
-                for (i = 6; i < 336; i++, line_mask <<= 1) {
-                    uint8_t *buf;
-                    if ((ctx->teletext_lines & line_mask) && vanc->GetBufferForVerticalBlankingLine(i, (void**)&buf) == S_OK) {
-                        if (teletext_data_unit_from_vbi_data(i, buf, txt_buf) >= 0)
-                            txt_buf += 46;
+                if (ctx->bmd_mode == bmdModePAL && (vanc_format == bmdFormat8BitYUV || vanc_format == bmdFormat10BitYUV)) {
+                    av_assert0(videoFrame->GetWidth() == 720);
+                    for (i = 6; i < 336; i++, line_mask <<= 1) {
+                        uint8_t *buf;
+                        if ((ctx->teletext_lines & line_mask) && vanc->GetBufferForVerticalBlankingLine(i, (void**)&buf) == S_OK) {
+                            if (vanc_format == bmdFormat8BitYUV)
+                                txt_buf = teletext_data_unit_from_vbi_data(i, buf, txt_buf, VBI_PIXFMT_UYVY);
+                            else
+                                txt_buf = teletext_data_unit_from_vbi_data_10bit(i, buf, txt_buf);
+                        }
+                        if (i == 22)
+                            i = 317;
                     }
-                    if (i == 22)
-                        i = 317;
                 }
                 vanc->Release();
                 if (txt_buf - txt_buf0 > 1) {