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

Marton Balint cus at passwd.hu
Mon Jul 3 20:52:13 EEST 2017



On Mon, 3 Jul 2017, Aaron Levinson wrote:

>> +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;
>> +    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;
>> +    }
>
> It would seem that the purpose of this code is to convert between the 
> Blackmagic 10-bit format (v210, according to the Blackmagic 
> documentation) and YUV420 (which is presumably easier than converting to 
> UYVY).  Why not use a color converter for this?

Because I only need the luma component and only in 8 bit, so getting 
anything else would be a waste of resources. Also the code is short enough 
and more readable than factorizing something from v210dec.

> Looking through the 
> ffmpeg code base, I see that v210 is handled using a decoder/encoder and 
> not as a pixel format, which seems odd, but maybe there is some way to 
> take advantage of that support instead of doing it yourself.  At the 
> very least, it seems reasonable to add a comment explaining what this 
> code is doing.

ok for the comment.

>
> Also, I understand that this is being done because libzvbi doesn't 
> support the v210 pixel format (which would be useful to explain in a 
> comment), but I have to wonder if the conversion between the 10-bit v210 
> pixel format and the 8-bit YUV420 pixel format will result in a loss of 
> data that is relevant for teletext.  If you've accommodated that 
> possibility, it would be good to describe in a comment.

I understand your concern, but for teletext you decode roughly 0.5 bit of 
information from a 8 bit value. So even using 8bit is a lot more than what 
you need. I will add a comment about this.

>>   #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 +387,21 @@ 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 (videoFrame->GetWidth() == 720 && (vanc_format == 
> bmdFormat8BitYUV || vanc_format == bmdFormat10BitYUV)) {
>
> According to the documentation in indevs.texi, the teletext support only 
> works for SD PAL.  Yet, this check doesn't isolate things just to SD 
> PAL.  I know that this issue was preexisting (although you have moved 
> the check to a different place in the code), but if you want to restrict 
> this code to SD PAL, then the best way is to check if the BMDDisplayMode 
> is bmdModePAL.  If you want to base things on the width/height, you 
> could check for a width of 720 and a height of 576, although this could 
> indicate either bmdModePAL or bmdModePALp (although there may be no 
> Blackmagic devices that support bmdModePALp on input).  Just checking 
> for a width of 720 includes NTSC, NTSCp, PAL, and PALp.

Ok.

>
>> +                    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);
>
> Since you already know if the format is 10-bit or 8-bit prior to 
> entering the for loop, putting the check here may result in an 
> unnecessary branch every loop iteration, depending on how the compiler 
> optimizes the code.  So, for efficiency, it would make more sense to 
> move the if check to earlier, prior to executing the for loop, but this 
> will end up causing you to effectively duplicate the for loop code the 
> way it is currently written.
>

The overhead is negligable (35 if-s per frame) and I find this more 
readable than duplicating the whole loop.

>> +                        }
>> +                        if (i == 22)
>> +                            i = 317;
>>                       }
>> -                    if (i == 22)
>> -                        i = 317;
>>                   }
>>                   vanc->Release();
>>                   if (txt_buf - txt_buf0 > 1) {
>> 
>
> Overall, looks good.  I'll review the second patch in a bit.

Thanks, I will send a v2.

Regards,
Marton


More information about the ffmpeg-devel mailing list