[FFmpeg-devel] avdevice/decklink_dec: Extract NTSC VANC

Submitted by Ray Tiley on Feb. 6, 2018, 1:35 a.m.

Details

Message ID 1517880918-31224-1-git-send-email-raytiley@gmail.com
State New
Headers show

Commit Message

Ray Tiley Feb. 6, 2018, 1:35 a.m.
This changes how NTSC VANC is extracted from the buffer. In NTSC the vanc
data interleved between the uyvy and not just the luma as in
high definition resolutions.

In my testing this allows a decklink card encoding valid NTSC closed
captions to pass the caption data to the x264 encoder.

Updated with rewviews from Devon Heitmueller and Marton Balint.

Signed-off-by: Ray Tiley <raytiley@gmail.com>
---
 libavdevice/decklink_dec.cpp | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

Comments

Marton Balint Feb. 11, 2018, 8:41 p.m.
On Mon, 5 Feb 2018, Ray Tiley wrote:

> This changes how NTSC VANC is extracted from the buffer. In NTSC the vanc
> data interleved between the uyvy and not just the luma as in
> high definition resolutions.
>
> In my testing this allows a decklink card encoding valid NTSC closed
> captions to pass the caption data to the x264 encoder.
>
> Updated with rewviews from Devon Heitmueller and Marton Balint.
>
> Signed-off-by: Ray Tiley <raytiley@gmail.com>
> ---
> libavdevice/decklink_dec.cpp | 37 ++++++++++++++++++++++++++++++++++---
> 1 file changed, 34 insertions(+), 3 deletions(-)
>
> diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
> index 94dae26..c3683bb 100644
> --- a/libavdevice/decklink_dec.cpp
> +++ b/libavdevice/decklink_dec.cpp
> @@ -149,6 +149,30 @@ static void extract_luma_from_v210(uint16_t *dst, const uint8_t *src, int width)
>     }
> }
> 
> +static void unpack_v210(uint16_t *dst, const uint8_t *src, int width)
> +{
> +    int i;
> +    for (i = 0; i < width / 6; i++) {
> +        *dst++ =  src[0]       + ((src[1] & 3)  << 8);
> +        *dst++ = (src[1] >> 2) + ((src[2] & 15) << 6);
> +        *dst++ = (src[2] >> 4) + ((src[3] & 63) << 4);
> +
> +        *dst++ =  src[4]       + ((src[5] & 3)  << 8);
> +        *dst++ = (src[5] >> 2) + ((src[6] & 15) << 6);
> +        *dst++ = (src[6] >> 4) + ((src[7] & 63) << 4);
> +
> +        *dst++ =  src[8]       + ((src[9] & 3)  << 8);
> +        *dst++ = (src[9] >> 2) + ((src[10] & 15) << 6);
> +        *dst++ = (src[10] >> 4) + ((src[11] & 63) << 4);
> +
> +        *dst++ =  src[12]       + ((src[13] & 3)  << 8);
> +        *dst++ = (src[13] >> 2) + ((src[14] & 15) << 6);
> +        *dst++ = (src[14] >> 4) + ((src[15] & 63) << 4);
> +
> +        src += 16;
> +    }
> +}

Sorry for the delay, and for not spotting this earlier, but I think you 
can simply write this:

     int i;
     for (i = 0; i < width * 2 / 3; i++) {
         *dst++ =  src[0]       + ((src[1] & 3)  << 8);
         *dst++ = (src[1] >> 2) + ((src[2] & 15) << 6);
         *dst++ = (src[2] >> 4) + ((src[3] & 63) << 4);
         src += 4;
     }

> +
> static uint8_t calc_parity_and_line_offset(int line)
> {
>     uint8_t ret = (line < 313) << 5;
> @@ -740,9 +764,16 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
>                     for (i = vanc_line_numbers[idx].vanc_start; i <= vanc_line_numbers[idx].vanc_end; i++) {
>                         uint8_t *buf;
>                         if (vanc->GetBufferForVerticalBlankingLine(i, (void**)&buf) == S_OK) {
> -                            uint16_t luma_vanc[MAX_WIDTH_VANC];
> -                            extract_luma_from_v210(luma_vanc, buf, videoFrame->GetWidth());
> -                            txt_buf = get_metadata(avctx, luma_vanc, videoFrame->GetWidth(),
> +                            uint16_t vanc[MAX_WIDTH_VANC];
> +                            size_t vanc_size = videoFrame->GetWidth();
> +                            if (ctx->bmd_mode == bmdModeNTSC &&
> +                                videoFrame->GetWidth() * 2 <= MAX_WIDTH_VANC) {
> +                              vanc_size = vanc_size * 2;
> +                              unpack_v210(vanc, buf, videoFrame->GetWidth());

Please use 4 space indent.

> +                            } else {
> +                              extract_luma_from_v210(vanc, buf, videoFrame->GetWidth());
> +                            }
> +                            txt_buf = get_metadata(avctx, vanc, vanc_size,
>                                                    txt_buf, sizeof(txt_buf0) - (txt_buf - txt_buf0), &pkt);
>                         }
>                         if (i == vanc_line_numbers[idx].field0_vanc_end)

Thanks,
Marton

Patch hide | download patch | download mbox

diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 94dae26..c3683bb 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -149,6 +149,30 @@  static void extract_luma_from_v210(uint16_t *dst, const uint8_t *src, int width)
     }
 }
 
+static void unpack_v210(uint16_t *dst, const uint8_t *src, int width)
+{
+    int i;
+    for (i = 0; i < width / 6; i++) {
+        *dst++ =  src[0]       + ((src[1] & 3)  << 8);
+        *dst++ = (src[1] >> 2) + ((src[2] & 15) << 6);
+        *dst++ = (src[2] >> 4) + ((src[3] & 63) << 4);
+
+        *dst++ =  src[4]       + ((src[5] & 3)  << 8);
+        *dst++ = (src[5] >> 2) + ((src[6] & 15) << 6);
+        *dst++ = (src[6] >> 4) + ((src[7] & 63) << 4);
+
+        *dst++ =  src[8]       + ((src[9] & 3)  << 8);
+        *dst++ = (src[9] >> 2) + ((src[10] & 15) << 6);
+        *dst++ = (src[10] >> 4) + ((src[11] & 63) << 4);
+
+        *dst++ =  src[12]       + ((src[13] & 3)  << 8);
+        *dst++ = (src[13] >> 2) + ((src[14] & 15) << 6);
+        *dst++ = (src[14] >> 4) + ((src[15] & 63) << 4);
+
+        src += 16;
+    }
+}
+
 static uint8_t calc_parity_and_line_offset(int line)
 {
     uint8_t ret = (line < 313) << 5;
@@ -740,9 +764,16 @@  HRESULT decklink_input_callback::VideoInputFrameArrived(
                     for (i = vanc_line_numbers[idx].vanc_start; i <= vanc_line_numbers[idx].vanc_end; i++) {
                         uint8_t *buf;
                         if (vanc->GetBufferForVerticalBlankingLine(i, (void**)&buf) == S_OK) {
-                            uint16_t luma_vanc[MAX_WIDTH_VANC];
-                            extract_luma_from_v210(luma_vanc, buf, videoFrame->GetWidth());
-                            txt_buf = get_metadata(avctx, luma_vanc, videoFrame->GetWidth(),
+                            uint16_t vanc[MAX_WIDTH_VANC];
+                            size_t vanc_size = videoFrame->GetWidth();
+                            if (ctx->bmd_mode == bmdModeNTSC &&
+                                videoFrame->GetWidth() * 2 <= MAX_WIDTH_VANC) {
+                              vanc_size = vanc_size * 2;
+                              unpack_v210(vanc, buf, videoFrame->GetWidth());
+                            } else {
+                              extract_luma_from_v210(vanc, buf, videoFrame->GetWidth());
+                            }
+                            txt_buf = get_metadata(avctx, vanc, vanc_size,
                                                    txt_buf, sizeof(txt_buf0) - (txt_buf - txt_buf0), &pkt);
                         }
                         if (i == vanc_line_numbers[idx].field0_vanc_end)