[FFmpeg-devel,2/4] avdevice/decklink_dec: Extraction of luma from V210 VANC modularized

Submitted by kjeyapal@akamai.com on Aug. 31, 2017, 8:36 a.m.

Details

Message ID 1504168610-2427-2-git-send-email-kjeyapal@akamai.com
State New
Headers show

Commit Message

kjeyapal@akamai.com Aug. 31, 2017, 8:36 a.m.
From: Karthick J <kjeyapal@akamai.com>

In preparation to support multiple VANC data decode

Signed-off-by: Karthick J <kjeyapal@akamai.com>
---
 libavdevice/decklink_dec.cpp | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

Comments

Marton Balint Sept. 3, 2017, 11:48 a.m.
On Thu, 31 Aug 2017, kjeyapal@akamai.com wrote:

> From: Karthick J <kjeyapal@akamai.com>
>
> In preparation to support multiple VANC data decode
>
> Signed-off-by: Karthick J <kjeyapal@akamai.com>
> ---
> libavdevice/decklink_dec.cpp | 31 ++++++++++++++++++-------------
> 1 file changed, 18 insertions(+), 13 deletions(-)
>
> diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
> index 40ef655..0b88fc8 100644
> --- a/libavdevice/decklink_dec.cpp
> +++ b/libavdevice/decklink_dec.cpp
> @@ -106,6 +106,18 @@ static void get_vanc_lines(int bmd_field_dominance, int height, int *field0_vanc
>     }
> }
> 
> +/* The 10-bit VANC data is packed in V210, we only need the luma component. */
> +static void extract_luma_from_v210(uint16_t *dst, const uint8_t *src, int width)
> +{
> +    int i;
> +    for (i = 0; i < width / 3; i += 3) {
> +        *dst++ = (src[1] >> 2) + ((src[2] & 15) << 6);
> +        *dst++ =  src[4]       + ((src[5] &  3) << 8);
> +        *dst++ = (src[6] >> 4) + ((src[7] & 63) << 4);
> +        src += 8;
> +    }
> +}
> +
> static uint8_t calc_parity_and_line_offset(int line)
> {
>     uint8_t ret = (line < 313) << 5;
> @@ -221,19 +233,10 @@ static uint8_t* teletext_data_unit_from_ancillary_packet(uint16_t *py, uint16_t
>     return tgt;
> }
> 
> -static uint8_t* teletext_data_unit_from_vanc_data(uint8_t *src, uint8_t *tgt, int64_t wanted_lines)
> +static uint8_t* teletext_data_unit_from_vanc_data(uint16_t *py, uint8_t *tgt, int64_t wanted_lines)
> {
> -    uint16_t y[1920];
> -    uint16_t *py = y;
> -    uint16_t *pend = y + 1920;
> -    /* The 10-bit VANC data is packed in V210, we only need the luma component. */
> -    while (py < pend) {
> -        *py++ = (src[1] >> 2) + ((src[2] & 15) << 6);
> -        *py++ =  src[4]       + ((src[5] &  3) << 8);
> -        *py++ = (src[6] >> 4) + ((src[7] & 63) << 4);
> -        src += 8;
> -    }
> -    py = y;
> +    uint16_t *pend = py + 1920;
> +
>     while (py < pend - 6) {
>         if (py[0] == 0 && py[1] == 0x3ff && py[2] == 0x3ff) {           // ancillary data flag
>             py += 3;
> @@ -570,8 +573,10 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
>                     for (i = 0; i <= vanc_end; i++) {
>                         uint8_t *buf;
>                         if (vanc->GetBufferForVerticalBlankingLine(i, (void**)&buf) == S_OK) {
> +                            uint16_t luma_vanc[4096]; // Allocated for highest width (4K)

I think we only have vanc numbers until resolution of 1920 width, so that 
should be enough. Probably better to add an av_assert which checks if 
frame width is less or equal to FF_ARRAY_ELEMS(luma_vanc).

> +                            extract_luma_from_v210(luma_vanc, buf, videoFrame->GetWidth());
>                             if (videoFrame->GetWidth() == 1920) {
> -                                txt_buf = teletext_data_unit_from_vanc_data(buf, txt_buf, ctx->teletext_lines);
> +                                txt_buf = teletext_data_unit_from_vanc_data(luma_vanc, txt_buf, ctx->teletext_lines);
>                                 if (txt_buf - txt_buf0 > 1611) {   // ensure we still have at least 1920 bytes free in the buffer
>                                     av_log(avctx, AV_LOG_ERROR, "Too many OP47 teletext packets.\n");
>                                     break;

Regards,
Marton
kjeyapal@akamai.com Sept. 5, 2017, 10:35 a.m.
>On 9/3/17, 5:18 PM, "Marton Balint" <cus@passwd.hu<mailto:cus@passwd.hu>> wrote:

>

>I think we only have vanc numbers until resolution of 1920 width, so that

>should be enough. Probably better to add an av_assert which checks if

>frame width is less or equal to FF_ARRAY_ELEMS(luma_vanc).

Done. Please find the patch attached. Have handled that 1920 limit, little different from your suggested method. Hope it is fine.

Regards,
Karthick

Patch hide | download patch | download mbox

diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 40ef655..0b88fc8 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -106,6 +106,18 @@  static void get_vanc_lines(int bmd_field_dominance, int height, int *field0_vanc
     }
 }
 
+/* The 10-bit VANC data is packed in V210, we only need the luma component. */
+static void extract_luma_from_v210(uint16_t *dst, const uint8_t *src, int width)
+{
+    int i;
+    for (i = 0; i < width / 3; i += 3) {
+        *dst++ = (src[1] >> 2) + ((src[2] & 15) << 6);
+        *dst++ =  src[4]       + ((src[5] &  3) << 8);
+        *dst++ = (src[6] >> 4) + ((src[7] & 63) << 4);
+        src += 8;
+    }
+}
+
 static uint8_t calc_parity_and_line_offset(int line)
 {
     uint8_t ret = (line < 313) << 5;
@@ -221,19 +233,10 @@  static uint8_t* teletext_data_unit_from_ancillary_packet(uint16_t *py, uint16_t
     return tgt;
 }
 
-static uint8_t* teletext_data_unit_from_vanc_data(uint8_t *src, uint8_t *tgt, int64_t wanted_lines)
+static uint8_t* teletext_data_unit_from_vanc_data(uint16_t *py, uint8_t *tgt, int64_t wanted_lines)
 {
-    uint16_t y[1920];
-    uint16_t *py = y;
-    uint16_t *pend = y + 1920;
-    /* The 10-bit VANC data is packed in V210, we only need the luma component. */
-    while (py < pend) {
-        *py++ = (src[1] >> 2) + ((src[2] & 15) << 6);
-        *py++ =  src[4]       + ((src[5] &  3) << 8);
-        *py++ = (src[6] >> 4) + ((src[7] & 63) << 4);
-        src += 8;
-    }
-    py = y;
+    uint16_t *pend = py + 1920;
+
     while (py < pend - 6) {
         if (py[0] == 0 && py[1] == 0x3ff && py[2] == 0x3ff) {           // ancillary data flag
             py += 3;
@@ -570,8 +573,10 @@  HRESULT decklink_input_callback::VideoInputFrameArrived(
                     for (i = 0; i <= vanc_end; i++) {
                         uint8_t *buf;
                         if (vanc->GetBufferForVerticalBlankingLine(i, (void**)&buf) == S_OK) {
+                            uint16_t luma_vanc[4096]; // Allocated for highest width (4K)
+                            extract_luma_from_v210(luma_vanc, buf, videoFrame->GetWidth());
                             if (videoFrame->GetWidth() == 1920) {
-                                txt_buf = teletext_data_unit_from_vanc_data(buf, txt_buf, ctx->teletext_lines);
+                                txt_buf = teletext_data_unit_from_vanc_data(luma_vanc, txt_buf, ctx->teletext_lines);
                                 if (txt_buf - txt_buf0 > 1611) {   // ensure we still have at least 1920 bytes free in the buffer
                                     av_log(avctx, AV_LOG_ERROR, "Too many OP47 teletext packets.\n");
                                     break;