diff mbox series

[FFmpeg-devel,1/2] avdevice/decklink_dec: mark the field flag if framerate > 30FPS

Message ID 1594992398-29104-1-git-send-email-lance.lmwang@gmail.com
State New
Headers show
Series [FFmpeg-devel,1/2] avdevice/decklink_dec: mark the field flag if framerate > 30FPS
Related show

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Limin Wang July 17, 2020, 1:26 p.m. UTC
From: Limin Wang <lance.lmwang@gmail.com>

In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag if the frame rate > 30FPS to
avoid interoperability issues. It will be used by the encoder to identify even or odd frames
and correctly calculate the frame number of the SEI TC.

---
 libavdevice/decklink_common.h |  1 +
 libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
 2 files changed, 15 insertions(+)

Comments

Marton Balint July 17, 2020, 5:13 p.m. UTC | #1
On Fri, 17 Jul 2020, lance.lmwang@gmail.com wrote:

> From: Limin Wang <lance.lmwang@gmail.com>
>
> In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag if the frame rate > 30FPS to
> avoid interoperability issues. It will be used by the encoder to identify even or odd frames
> and correctly calculate the frame number of the SEI TC.

This feature looks like it belongs to av_timecode_get_smpte_from_framenum 
and not into decklink. Also checking previous timecode and guessing 
something is a hack, especially since you have the exact source timecode.

Regards,
Marton

>
> ---
> libavdevice/decklink_common.h |  1 +
> libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
> 2 files changed, 15 insertions(+)
>
> diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
> index bd68c7b..8ddc411 100644
> --- a/libavdevice/decklink_common.h
> +++ b/libavdevice/decklink_common.h
> @@ -151,6 +151,7 @@ struct decklink_ctx {
>     int channels;
>     int audio_depth;
>     unsigned long tc_seen;    // used with option wait_for_tc
> +    uint32_t last_tc;
> };
> 
> typedef enum { DIRECTION_IN, DIRECTION_OUT} decklink_direction_t;
> diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
> index dde68ff..a60c01b 100644
> --- a/libavdevice/decklink_dec.cpp
> +++ b/libavdevice/decklink_dec.cpp
> @@ -884,12 +884,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
>                         int metadata_len;
>                         uint8_t* packed_metadata;
>                         AVTimecode tcr;
> +                        AVRational rate = ctx->video_st->r_frame_rate;
>
>                         if (av_timecode_init_from_string(&tcr, ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
>                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
>                             int size = sizeof(uint32_t) * 4;
>                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
> 
> +                            /* set the field flag if frame rate > 30FPS */
> +                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
> +                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
> +                                /* Odd frame */
> +                                if (ctx->last_tc == tc_data) {
> +                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
> +                                        tc_data |= (1 << 7);
> +                                    else
> +                                        tc_data |= (1 << 23);
> +                                }
> +                            }
> +                            ctx->last_tc = tc_data;
> +
>                             if (sd) {
>                                 *sd       = 1;       // one TC
>                                 *(sd + 1) = tc_data; // TC
> -- 
> 2.9.4
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Limin Wang July 17, 2020, 10:42 p.m. UTC | #2
On Fri, Jul 17, 2020 at 07:13:28PM +0200, Marton Balint wrote:
> 
> 
> On Fri, 17 Jul 2020, lance.lmwang@gmail.com wrote:
> 
> > From: Limin Wang <lance.lmwang@gmail.com>
> > 
> > In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag if the frame rate > 30FPS to
> > avoid interoperability issues. It will be used by the encoder to identify even or odd frames
> > and correctly calculate the frame number of the SEI TC.
> 
> This feature looks like it belongs to av_timecode_get_smpte_from_framenum
> and not into decklink. Also checking previous timecode and guessing
> something is a hack, especially since you have the exact source timecode.
If I understand correctly, it's not hacky, for the framerate > 30, the source timecode will be
frame pair(it's limited by 2bits limit of frame number ten digital. Below is one exmaple for 50fps
if you tested with SDI with TC.
00:00:00:24
00:00:00:24
00:00:00:25
00:00:00:25
00:00:00:00
00:00:00:00

That's why I check the last TC to get the frame is even or odd.

Why not use av_timecode_get_smpte_from_framenum(), for it's calculated by the string TC by one time,
so it lacks the information whether it's odd or even frame. 

> 
> Regards,
> Marton
> 
> > 
> > ---
> > libavdevice/decklink_common.h |  1 +
> > libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
> > 2 files changed, 15 insertions(+)
> > 
> > diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
> > index bd68c7b..8ddc411 100644
> > --- a/libavdevice/decklink_common.h
> > +++ b/libavdevice/decklink_common.h
> > @@ -151,6 +151,7 @@ struct decklink_ctx {
> >     int channels;
> >     int audio_depth;
> >     unsigned long tc_seen;    // used with option wait_for_tc
> > +    uint32_t last_tc;
> > };
> > 
> > typedef enum { DIRECTION_IN, DIRECTION_OUT} decklink_direction_t;
> > diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
> > index dde68ff..a60c01b 100644
> > --- a/libavdevice/decklink_dec.cpp
> > +++ b/libavdevice/decklink_dec.cpp
> > @@ -884,12 +884,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
> >                         int metadata_len;
> >                         uint8_t* packed_metadata;
> >                         AVTimecode tcr;
> > +                        AVRational rate = ctx->video_st->r_frame_rate;
> > 
> >                         if (av_timecode_init_from_string(&tcr, ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
> >                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
> >                             int size = sizeof(uint32_t) * 4;
> >                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
> > 
> > +                            /* set the field flag if frame rate > 30FPS */
> > +                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
> > +                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
> > +                                /* Odd frame */
> > +                                if (ctx->last_tc == tc_data) {
> > +                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
> > +                                        tc_data |= (1 << 7);
> > +                                    else
> > +                                        tc_data |= (1 << 23);
> > +                                }
> > +                            }
> > +                            ctx->last_tc = tc_data;
> > +
> >                             if (sd) {
> >                                 *sd       = 1;       // one TC
> >                                 *(sd + 1) = tc_data; // TC
> > -- 
> > 2.9.4
> > 
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > 
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Marton Balint July 18, 2020, 7:44 a.m. UTC | #3
On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:

> On Fri, Jul 17, 2020 at 07:13:28PM +0200, Marton Balint wrote:
>> 
>> 
>> On Fri, 17 Jul 2020, lance.lmwang@gmail.com wrote:
>> 
>> > From: Limin Wang <lance.lmwang@gmail.com>
>> > 
>> > In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag if the frame rate > 30FPS to
>> > avoid interoperability issues. It will be used by the encoder to identify even or odd frames
>> > and correctly calculate the frame number of the SEI TC.
>> 
>> This feature looks like it belongs to av_timecode_get_smpte_from_framenum
>> and not into decklink. Also checking previous timecode and guessing
>> something is a hack, especially since you have the exact source timecode.
> If I understand correctly, it's not hacky, for the framerate > 30, the source timecode will be
> frame pair(it's limited by 2bits limit of frame number ten digital. Below is one exmaple for 50fps
> if you tested with SDI with TC.
> 00:00:00:24
> 00:00:00:24
> 00:00:00:25
> 00:00:00:25
> 00:00:00:00
> 00:00:00:00

Have you actually tested this with a real SDI signal containing timecode?

Thanks,
Marton

>
> That's why I check the last TC to get the frame is even or odd.
>
> Why not use av_timecode_get_smpte_from_framenum(), for it's calculated by the string TC by one time,
> so it lacks the information whether it's odd or even frame.
>
>> 
>> Regards,
>> Marton
>> 
>> > 
>> > ---
>> > libavdevice/decklink_common.h |  1 +
>> > libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
>> > 2 files changed, 15 insertions(+)
>> > 
>> > diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
>> > index bd68c7b..8ddc411 100644
>> > --- a/libavdevice/decklink_common.h
>> > +++ b/libavdevice/decklink_common.h
>> > @@ -151,6 +151,7 @@ struct decklink_ctx {
>> >     int channels;
>> >     int audio_depth;
>> >     unsigned long tc_seen;    // used with option wait_for_tc
>> > +    uint32_t last_tc;
>> > };
>> > 
>> > typedef enum { DIRECTION_IN, DIRECTION_OUT} decklink_direction_t;
>> > diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
>> > index dde68ff..a60c01b 100644
>> > --- a/libavdevice/decklink_dec.cpp
>> > +++ b/libavdevice/decklink_dec.cpp
>> > @@ -884,12 +884,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
>> >                         int metadata_len;
>> >                         uint8_t* packed_metadata;
>> >                         AVTimecode tcr;
>> > +                        AVRational rate = ctx->video_st->r_frame_rate;
>> > 
>> >                         if (av_timecode_init_from_string(&tcr, ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
>> >                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
>> >                             int size = sizeof(uint32_t) * 4;
>> >                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
>> > 
>> > +                            /* set the field flag if frame rate > 30FPS */
>> > +                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
>> > +                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
>> > +                                /* Odd frame */
>> > +                                if (ctx->last_tc == tc_data) {
>> > +                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
>> > +                                        tc_data |= (1 << 7);
>> > +                                    else
>> > +                                        tc_data |= (1 << 23);
>> > +                                }
>> > +                            }
>> > +                            ctx->last_tc = tc_data;
>> > +
>> >                             if (sd) {
>> >                                 *sd       = 1;       // one TC
>> >                                 *(sd + 1) = tc_data; // TC
>> > -- 
>> > 2.9.4
>> > 
>> > _______________________________________________
>> > ffmpeg-devel mailing list
>> > ffmpeg-devel@ffmpeg.org
>> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > 
>> > To unsubscribe, visit link above, or email
>> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> 
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
> -- 
> Thanks,
> Limin Wang
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Limin Wang July 18, 2020, 2:38 p.m. UTC | #4
On Sat, Jul 18, 2020 at 09:44:03AM +0200, Marton Balint wrote:
> 
> 
> On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
> 
> > On Fri, Jul 17, 2020 at 07:13:28PM +0200, Marton Balint wrote:
> > > 
> > > 
> > > On Fri, 17 Jul 2020, lance.lmwang@gmail.com wrote:
> > > 
> > > > From: Limin Wang <lance.lmwang@gmail.com>
> > > > > In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag
> > > if the frame rate > 30FPS to
> > > > avoid interoperability issues. It will be used by the encoder to identify even or odd frames
> > > > and correctly calculate the frame number of the SEI TC.
> > > 
> > > This feature looks like it belongs to av_timecode_get_smpte_from_framenum
> > > and not into decklink. Also checking previous timecode and guessing
> > > something is a hack, especially since you have the exact source timecode.
> > If I understand correctly, it's not hacky, for the framerate > 30, the source timecode will be
> > frame pair(it's limited by 2bits limit of frame number ten digital. Below is one exmaple for 50fps
> > if you tested with SDI with TC.
> > 00:00:00:24
> > 00:00:00:24
> > 00:00:00:25
> > 00:00:00:25
> > 00:00:00:00
> > 00:00:00:00
> 
> Have you actually tested this with a real SDI signal containing timecode?

Yes, have tested with SDI playback by decklink UltraStudio 4K mini with TC enabled.

> 
> Thanks,
> Marton
> 
> > 
> > That's why I check the last TC to get the frame is even or odd.
> > 
> > Why not use av_timecode_get_smpte_from_framenum(), for it's calculated by the string TC by one time,
> > so it lacks the information whether it's odd or even frame.
> > 
> > > 
> > > Regards,
> > > Marton
> > > 
> > > > > ---
> > > > libavdevice/decklink_common.h |  1 +
> > > > libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
> > > > 2 files changed, 15 insertions(+)
> > > > > diff --git a/libavdevice/decklink_common.h
> > > b/libavdevice/decklink_common.h
> > > > index bd68c7b..8ddc411 100644
> > > > --- a/libavdevice/decklink_common.h
> > > > +++ b/libavdevice/decklink_common.h
> > > > @@ -151,6 +151,7 @@ struct decklink_ctx {
> > > >     int channels;
> > > >     int audio_depth;
> > > >     unsigned long tc_seen;    // used with option wait_for_tc
> > > > +    uint32_t last_tc;
> > > > };
> > > > > typedef enum { DIRECTION_IN, DIRECTION_OUT}
> > > decklink_direction_t;
> > > > diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
> > > > index dde68ff..a60c01b 100644
> > > > --- a/libavdevice/decklink_dec.cpp
> > > > +++ b/libavdevice/decklink_dec.cpp
> > > > @@ -884,12 +884,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
> > > >                         int metadata_len;
> > > >                         uint8_t* packed_metadata;
> > > >                         AVTimecode tcr;
> > > > +                        AVRational rate = ctx->video_st->r_frame_rate;
> > > > >                         if (av_timecode_init_from_string(&tcr,
> > > ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
> > > >                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
> > > >                             int size = sizeof(uint32_t) * 4;
> > > >                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
> > > > > +                            /* set the field flag if frame rate
> > > > 30FPS */
> > > > +                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
> > > > +                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
> > > > +                                /* Odd frame */
> > > > +                                if (ctx->last_tc == tc_data) {
> > > > +                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
> > > > +                                        tc_data |= (1 << 7);
> > > > +                                    else
> > > > +                                        tc_data |= (1 << 23);
> > > > +                                }
> > > > +                            }
> > > > +                            ctx->last_tc = tc_data;
> > > > +
> > > >                             if (sd) {
> > > >                                 *sd       = 1;       // one TC
> > > >                                 *(sd + 1) = tc_data; // TC
> > > > -- > 2.9.4
> > > > > _______________________________________________
> > > > ffmpeg-devel mailing list
> > > > ffmpeg-devel@ffmpeg.org
> > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > > > To unsubscribe, visit link above, or email
> > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > > _______________________________________________
> > > ffmpeg-devel mailing list
> > > ffmpeg-devel@ffmpeg.org
> > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > 
> > > To unsubscribe, visit link above, or email
> > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > 
> > -- 
> > Thanks,
> > Limin Wang
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > 
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Marton Balint July 18, 2020, 6:38 p.m. UTC | #5
On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:

> On Sat, Jul 18, 2020 at 09:44:03AM +0200, Marton Balint wrote:
>> 
>> 
>> On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
>> 
>> > On Fri, Jul 17, 2020 at 07:13:28PM +0200, Marton Balint wrote:
>> > > 
>> > > 
>> > > On Fri, 17 Jul 2020, lance.lmwang@gmail.com wrote:
>> > > 
>> > > > From: Limin Wang <lance.lmwang@gmail.com>
>> > > > > In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag
>> > > if the frame rate > 30FPS to
>> > > > avoid interoperability issues. It will be used by the encoder to identify even or odd frames
>> > > > and correctly calculate the frame number of the SEI TC.
>> > > 
>> > > This feature looks like it belongs to av_timecode_get_smpte_from_framenum
>> > > and not into decklink. Also checking previous timecode and guessing
>> > > something is a hack, especially since you have the exact source timecode.
>> > If I understand correctly, it's not hacky, for the framerate > 30, the source timecode will be
>> > frame pair(it's limited by 2bits limit of frame number ten digital. Below is one exmaple for 50fps
>> > if you tested with SDI with TC.
>> > 00:00:00:24
>> > 00:00:00:24
>> > 00:00:00:25
>> > 00:00:00:25
>> > 00:00:00:00
>> > 00:00:00:00
>> 
>> Have you actually tested this with a real SDI signal containing timecode?
>
> Yes, have tested with SDI playback by decklink UltraStudio 4K mini with TC enabled.

I still don't understand how this works. Isn't timecode in the SDI signal 
also contain the so called "field bit" flag to support 50fps timecode? And 
if it does, then why can't you query it from decklink? Timecode in SDI 
signal is also supposed to be an SMPTE 12M timecode, so all the bits you 
need should be in it, you should not need to guess anything. Therefore it 
makes little sense to me that the DeckLink API does not provide a proper 
timecode as string, unless the original capture you made with your 
UltraStudio and which you played back also has a faulty timecode.
What generated the signal which you captured with UltraStudio? Not ffmpeg 
I hope...

Regards,
Marton


>
>> 
>> Thanks,
>> Marton
>> 
>> > 
>> > That's why I check the last TC to get the frame is even or odd.
>> > 
>> > Why not use av_timecode_get_smpte_from_framenum(), for it's calculated by the string TC by one time,
>> > so it lacks the information whether it's odd or even frame.
>> > 
>> > > 
>> > > Regards,
>> > > Marton
>> > > 
>> > > > > ---
>> > > > libavdevice/decklink_common.h |  1 +
>> > > > libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
>> > > > 2 files changed, 15 insertions(+)
>> > > > > diff --git a/libavdevice/decklink_common.h
>> > > b/libavdevice/decklink_common.h
>> > > > index bd68c7b..8ddc411 100644
>> > > > --- a/libavdevice/decklink_common.h
>> > > > +++ b/libavdevice/decklink_common.h
>> > > > @@ -151,6 +151,7 @@ struct decklink_ctx {
>> > > >     int channels;
>> > > >     int audio_depth;
>> > > >     unsigned long tc_seen;    // used with option wait_for_tc
>> > > > +    uint32_t last_tc;
>> > > > };
>> > > > > typedef enum { DIRECTION_IN, DIRECTION_OUT}
>> > > decklink_direction_t;
>> > > > diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
>> > > > index dde68ff..a60c01b 100644
>> > > > --- a/libavdevice/decklink_dec.cpp
>> > > > +++ b/libavdevice/decklink_dec.cpp
>> > > > @@ -884,12 +884,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
>> > > >                         int metadata_len;
>> > > >                         uint8_t* packed_metadata;
>> > > >                         AVTimecode tcr;
>> > > > +                        AVRational rate = ctx->video_st->r_frame_rate;
>> > > > >                         if (av_timecode_init_from_string(&tcr,
>> > > ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
>> > > >                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
>> > > >                             int size = sizeof(uint32_t) * 4;
>> > > >                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
>> > > > > +                            /* set the field flag if frame rate
>> > > > 30FPS */
>> > > > +                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
>> > > > +                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
>> > > > +                                /* Odd frame */
>> > > > +                                if (ctx->last_tc == tc_data) {
>> > > > +                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
>> > > > +                                        tc_data |= (1 << 7);
>> > > > +                                    else
>> > > > +                                        tc_data |= (1 << 23);
>> > > > +                                }
>> > > > +                            }
>> > > > +                            ctx->last_tc = tc_data;
>> > > > +
>> > > >                             if (sd) {
>> > > >                                 *sd       = 1;       // one TC
>> > > >                                 *(sd + 1) = tc_data; // TC
>> > > > -- > 2.9.4
>> > > > > _______________________________________________
>> > > > ffmpeg-devel mailing list
>> > > > ffmpeg-devel@ffmpeg.org
>> > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > > > To unsubscribe, visit link above, or email
>> > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > > _______________________________________________
>> > > ffmpeg-devel mailing list
>> > > ffmpeg-devel@ffmpeg.org
>> > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > 
>> > > To unsubscribe, visit link above, or email
>> > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > 
>> > -- 
>> > Thanks,
>> > Limin Wang
>> > _______________________________________________
>> > ffmpeg-devel mailing list
>> > ffmpeg-devel@ffmpeg.org
>> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > 
>> > To unsubscribe, visit link above, or email
>> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> 
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
> -- 
> Thanks,
> Limin Wang
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Limin Wang July 19, 2020, 2:44 a.m. UTC | #6
On Sat, Jul 18, 2020 at 08:38:16PM +0200, Marton Balint wrote:
> 
> 
> On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
> 
> > On Sat, Jul 18, 2020 at 09:44:03AM +0200, Marton Balint wrote:
> > > 
> > > 
> > > On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
> > > 
> > > > On Fri, Jul 17, 2020 at 07:13:28PM +0200, Marton Balint wrote:
> > > > > > > > > On Fri, 17 Jul 2020, lance.lmwang@gmail.com wrote:
> > > > > > > > From: Limin Wang <lance.lmwang@gmail.com>
> > > > > > > In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag
> > > > > if the frame rate > 30FPS to
> > > > > > avoid interoperability issues. It will be used by the encoder to identify even or odd frames
> > > > > > and correctly calculate the frame number of the SEI TC.
> > > > > > > This feature looks like it belongs to
> > > av_timecode_get_smpte_from_framenum
> > > > > and not into decklink. Also checking previous timecode and guessing
> > > > > something is a hack, especially since you have the exact source timecode.
> > > > If I understand correctly, it's not hacky, for the framerate > 30, the source timecode will be
> > > > frame pair(it's limited by 2bits limit of frame number ten digital. Below is one exmaple for 50fps
> > > > if you tested with SDI with TC.
> > > > 00:00:00:24
> > > > 00:00:00:24
> > > > 00:00:00:25
> > > > 00:00:00:25
> > > > 00:00:00:00
> > > > 00:00:00:00
> > > 
> > > Have you actually tested this with a real SDI signal containing timecode?
> > 
> > Yes, have tested with SDI playback by decklink UltraStudio 4K mini with TC enabled.
> 
> I still don't understand how this works. Isn't timecode in the SDI signal
> also contain the so called "field bit" flag to support 50fps timecode? And
> if it does, then why can't you query it from decklink? Timecode in SDI
> signal is also supposed to be an SMPTE 12M timecode, so all the bits you
> need should be in it, you should not need to guess anything. Therefore it
> makes little sense to me that the DeckLink API does not provide a proper
> timecode as string, unless the original capture you made with your
> UltraStudio and which you played back also has a faulty timecode.
> What generated the signal which you captured with UltraStudio? Not ffmpeg I
> hope...

It's auto-generated by configure of UltraStudio. I have tested with bmdTimecodeFieldMark
flag, it's not set as expected for testing. I have no clue how to get the flag as the API 
provide the TC string is same for the frame pair. Maybe I miss something.

> 
> Regards,
> Marton
> 
> 
> > 
> > > 
> > > Thanks,
> > > Marton
> > > 
> > > > > That's why I check the last TC to get the frame is even or odd.
> > > > > Why not use av_timecode_get_smpte_from_framenum(), for it's
> > > calculated by the string TC by one time,
> > > > so it lacks the information whether it's odd or even frame.
> > > > > > > > Regards,
> > > > > Marton
> > > > > > > > > ---
> > > > > > libavdevice/decklink_common.h |  1 +
> > > > > > libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
> > > > > > 2 files changed, 15 insertions(+)
> > > > > > > diff --git a/libavdevice/decklink_common.h
> > > > > b/libavdevice/decklink_common.h
> > > > > > index bd68c7b..8ddc411 100644
> > > > > > --- a/libavdevice/decklink_common.h
> > > > > > +++ b/libavdevice/decklink_common.h
> > > > > > @@ -151,6 +151,7 @@ struct decklink_ctx {
> > > > > >     int channels;
> > > > > >     int audio_depth;
> > > > > >     unsigned long tc_seen;    // used with option wait_for_tc
> > > > > > +    uint32_t last_tc;
> > > > > > };
> > > > > > > typedef enum { DIRECTION_IN, DIRECTION_OUT}
> > > > > decklink_direction_t;
> > > > > > diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
> > > > > > index dde68ff..a60c01b 100644
> > > > > > --- a/libavdevice/decklink_dec.cpp
> > > > > > +++ b/libavdevice/decklink_dec.cpp
> > > > > > @@ -884,12 +884,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
> > > > > >                         int metadata_len;
> > > > > >                         uint8_t* packed_metadata;
> > > > > >                         AVTimecode tcr;
> > > > > > +                        AVRational rate = ctx->video_st->r_frame_rate;
> > > > > > >                         if (av_timecode_init_from_string(&tcr,
> > > > > ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
> > > > > >                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
> > > > > >                             int size = sizeof(uint32_t) * 4;
> > > > > >                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
> > > > > > > +                            /* set the field flag if frame rate
> > > > > > 30FPS */
> > > > > > +                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
> > > > > > +                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
> > > > > > +                                /* Odd frame */
> > > > > > +                                if (ctx->last_tc == tc_data) {
> > > > > > +                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
> > > > > > +                                        tc_data |= (1 << 7);
> > > > > > +                                    else
> > > > > > +                                        tc_data |= (1 << 23);
> > > > > > +                                }
> > > > > > +                            }
> > > > > > +                            ctx->last_tc = tc_data;
> > > > > > +
> > > > > >                             if (sd) {
> > > > > >                                 *sd       = 1;       // one TC
> > > > > >                                 *(sd + 1) = tc_data; // TC
> > > > > > -- > 2.9.4
> > > > > > > _______________________________________________
> > > > > > ffmpeg-devel mailing list
> > > > > > ffmpeg-devel@ffmpeg.org
> > > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > > > > > To unsubscribe, visit link above, or email
> > > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > > > > _______________________________________________
> > > > > ffmpeg-devel mailing list
> > > > > ffmpeg-devel@ffmpeg.org
> > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > > > > > To unsubscribe, visit link above, or email
> > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > > > > -- > Thanks,
> > > > Limin Wang
> > > > _______________________________________________
> > > > ffmpeg-devel mailing list
> > > > ffmpeg-devel@ffmpeg.org
> > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > > > To unsubscribe, visit link above, or email
> > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > > _______________________________________________
> > > ffmpeg-devel mailing list
> > > ffmpeg-devel@ffmpeg.org
> > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > 
> > > To unsubscribe, visit link above, or email
> > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > 
> > -- 
> > Thanks,
> > Limin Wang
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > 
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Marton Balint July 19, 2020, 7:05 a.m. UTC | #7
On Sun, 19 Jul 2020, lance.lmwang@gmail.com wrote:

> On Sat, Jul 18, 2020 at 08:38:16PM +0200, Marton Balint wrote:
>> 
>> 
>> On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
>> 
>> > On Sat, Jul 18, 2020 at 09:44:03AM +0200, Marton Balint wrote:
>> > > 
>> > > 
>> > > On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
>> > > 
>> > > > On Fri, Jul 17, 2020 at 07:13:28PM +0200, Marton Balint wrote:
>> > > > > > > > > On Fri, 17 Jul 2020, lance.lmwang@gmail.com wrote:
>> > > > > > > > From: Limin Wang <lance.lmwang@gmail.com>
>> > > > > > > In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag
>> > > > > if the frame rate > 30FPS to
>> > > > > > avoid interoperability issues. It will be used by the encoder to identify even or odd frames
>> > > > > > and correctly calculate the frame number of the SEI TC.
>> > > > > > > This feature looks like it belongs to
>> > > av_timecode_get_smpte_from_framenum
>> > > > > and not into decklink. Also checking previous timecode and guessing
>> > > > > something is a hack, especially since you have the exact source timecode.
>> > > > If I understand correctly, it's not hacky, for the framerate > 30, the source timecode will be
>> > > > frame pair(it's limited by 2bits limit of frame number ten digital. Below is one exmaple for 50fps
>> > > > if you tested with SDI with TC.
>> > > > 00:00:00:24
>> > > > 00:00:00:24
>> > > > 00:00:00:25
>> > > > 00:00:00:25
>> > > > 00:00:00:00
>> > > > 00:00:00:00
>> > > 
>> > > Have you actually tested this with a real SDI signal containing timecode?
>> > 
>> > Yes, have tested with SDI playback by decklink UltraStudio 4K mini with TC enabled.
>> 
>> I still don't understand how this works. Isn't timecode in the SDI signal
>> also contain the so called "field bit" flag to support 50fps timecode? And
>> if it does, then why can't you query it from decklink? Timecode in SDI
>> signal is also supposed to be an SMPTE 12M timecode, so all the bits you
>> need should be in it, you should not need to guess anything. Therefore it
>> makes little sense to me that the DeckLink API does not provide a proper
>> timecode as string, unless the original capture you made with your
>> UltraStudio and which you played back also has a faulty timecode.
>> What generated the signal which you captured with UltraStudio? Not ffmpeg I
>> hope...
>
> It's auto-generated by configure of UltraStudio.

You mean using XLR timecode input selection? I would not trust that with 
50fps...

> I have tested with bmdTimecodeFieldMark
> flag, it's not set as expected for testing. I have no clue how to get the flag as the API 
> provide the TC string is same for the frame pair. Maybe I miss something.

I'd try to generate SDI video with timecode by some other means. E.g. 
using MediaExpress / DaVinci Resolve and a native 1080p50 file.

Regards,
Marton


>
>> 
>> Regards,
>> Marton
>> 
>> 
>> > 
>> > > 
>> > > Thanks,
>> > > Marton
>> > > 
>> > > > > That's why I check the last TC to get the frame is even or odd.
>> > > > > Why not use av_timecode_get_smpte_from_framenum(), for it's
>> > > calculated by the string TC by one time,
>> > > > so it lacks the information whether it's odd or even frame.
>> > > > > > > > Regards,
>> > > > > Marton
>> > > > > > > > > ---
>> > > > > > libavdevice/decklink_common.h |  1 +
>> > > > > > libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
>> > > > > > 2 files changed, 15 insertions(+)
>> > > > > > > diff --git a/libavdevice/decklink_common.h
>> > > > > b/libavdevice/decklink_common.h
>> > > > > > index bd68c7b..8ddc411 100644
>> > > > > > --- a/libavdevice/decklink_common.h
>> > > > > > +++ b/libavdevice/decklink_common.h
>> > > > > > @@ -151,6 +151,7 @@ struct decklink_ctx {
>> > > > > >     int channels;
>> > > > > >     int audio_depth;
>> > > > > >     unsigned long tc_seen;    // used with option wait_for_tc
>> > > > > > +    uint32_t last_tc;
>> > > > > > };
>> > > > > > > typedef enum { DIRECTION_IN, DIRECTION_OUT}
>> > > > > decklink_direction_t;
>> > > > > > diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
>> > > > > > index dde68ff..a60c01b 100644
>> > > > > > --- a/libavdevice/decklink_dec.cpp
>> > > > > > +++ b/libavdevice/decklink_dec.cpp
>> > > > > > @@ -884,12 +884,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
>> > > > > >                         int metadata_len;
>> > > > > >                         uint8_t* packed_metadata;
>> > > > > >                         AVTimecode tcr;
>> > > > > > +                        AVRational rate = ctx->video_st->r_frame_rate;
>> > > > > > >                         if (av_timecode_init_from_string(&tcr,
>> > > > > ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
>> > > > > >                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
>> > > > > >                             int size = sizeof(uint32_t) * 4;
>> > > > > >                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
>> > > > > > > +                            /* set the field flag if frame rate
>> > > > > > 30FPS */
>> > > > > > +                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
>> > > > > > +                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
>> > > > > > +                                /* Odd frame */
>> > > > > > +                                if (ctx->last_tc == tc_data) {
>> > > > > > +                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
>> > > > > > +                                        tc_data |= (1 << 7);
>> > > > > > +                                    else
>> > > > > > +                                        tc_data |= (1 << 23);
>> > > > > > +                                }
>> > > > > > +                            }
>> > > > > > +                            ctx->last_tc = tc_data;
>> > > > > > +
>> > > > > >                             if (sd) {
>> > > > > >                                 *sd       = 1;       // one TC
>> > > > > >                                 *(sd + 1) = tc_data; // TC
>> > > > > > -- > 2.9.4
>> > > > > > > _______________________________________________
>> > > > > > ffmpeg-devel mailing list
>> > > > > > ffmpeg-devel@ffmpeg.org
>> > > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > > > > > To unsubscribe, visit link above, or email
>> > > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > > > > _______________________________________________
>> > > > > ffmpeg-devel mailing list
>> > > > > ffmpeg-devel@ffmpeg.org
>> > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > > > > > To unsubscribe, visit link above, or email
>> > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > > > > -- > Thanks,
>> > > > Limin Wang
>> > > > _______________________________________________
>> > > > ffmpeg-devel mailing list
>> > > > ffmpeg-devel@ffmpeg.org
>> > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > > > To unsubscribe, visit link above, or email
>> > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > > _______________________________________________
>> > > ffmpeg-devel mailing list
>> > > ffmpeg-devel@ffmpeg.org
>> > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > 
>> > > To unsubscribe, visit link above, or email
>> > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > 
>> > -- 
>> > Thanks,
>> > Limin Wang
>> > _______________________________________________
>> > ffmpeg-devel mailing list
>> > ffmpeg-devel@ffmpeg.org
>> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > 
>> > To unsubscribe, visit link above, or email
>> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> 
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
> -- 
> Thanks,
> Limin Wang
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Limin Wang July 20, 2020, 1:05 p.m. UTC | #8
On Sun, Jul 19, 2020 at 09:05:33AM +0200, Marton Balint wrote:
> 
> 
> On Sun, 19 Jul 2020, lance.lmwang@gmail.com wrote:
> 
> > On Sat, Jul 18, 2020 at 08:38:16PM +0200, Marton Balint wrote:
> > > 
> > > 
> > > On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
> > > 
> > > > On Sat, Jul 18, 2020 at 09:44:03AM +0200, Marton Balint wrote:
> > > > > > > > > On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
> > > > > > > > On Fri, Jul 17, 2020 at 07:13:28PM +0200, Marton Balint
> > > wrote:
> > > > > > > > > > > On Fri, 17 Jul 2020, lance.lmwang@gmail.com wrote:
> > > > > > > > > > From: Limin Wang <lance.lmwang@gmail.com>
> > > > > > > > > In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag
> > > > > > > if the frame rate > 30FPS to
> > > > > > > > avoid interoperability issues. It will be used by the encoder to identify even or odd frames
> > > > > > > > and correctly calculate the frame number of the SEI TC.
> > > > > > > > > This feature looks like it belongs to
> > > > > av_timecode_get_smpte_from_framenum
> > > > > > > and not into decklink. Also checking previous timecode and guessing
> > > > > > > something is a hack, especially since you have the exact source timecode.
> > > > > > If I understand correctly, it's not hacky, for the framerate > 30, the source timecode will be
> > > > > > frame pair(it's limited by 2bits limit of frame number ten digital. Below is one exmaple for 50fps
> > > > > > if you tested with SDI with TC.
> > > > > > 00:00:00:24
> > > > > > 00:00:00:24
> > > > > > 00:00:00:25
> > > > > > 00:00:00:25
> > > > > > 00:00:00:00
> > > > > > 00:00:00:00
> > > > > > > Have you actually tested this with a real SDI signal
> > > containing timecode?
> > > > > Yes, have tested with SDI playback by decklink UltraStudio 4K
> > > mini with TC enabled.
> > > 
> > > I still don't understand how this works. Isn't timecode in the SDI signal
> > > also contain the so called "field bit" flag to support 50fps timecode? And
> > > if it does, then why can't you query it from decklink? Timecode in SDI
> > > signal is also supposed to be an SMPTE 12M timecode, so all the bits you
> > > need should be in it, you should not need to guess anything. Therefore it
> > > makes little sense to me that the DeckLink API does not provide a proper
> > > timecode as string, unless the original capture you made with your
> > > UltraStudio and which you played back also has a faulty timecode.
> > > What generated the signal which you captured with UltraStudio? Not ffmpeg I
> > > hope...
> > 
> > It's auto-generated by configure of UltraStudio.
> 
> You mean using XLR timecode input selection? I would not trust that with
> 50fps...

I'm not sure it's XLR or not, it's configured by the menu.

> 
> > I have tested with bmdTimecodeFieldMark
> > flag, it's not set as expected for testing. I have no clue how to get
> > the flag as the API provide the TC string is same for the frame pair.
> > Maybe I miss something.
> 
> I'd try to generate SDI video with timecode by some other means. E.g. using
> MediaExpress / DaVinci Resolve and a native 1080p50 file.

What's your tested result for the 1080p50 file?  I haven't MediaExpress / DaVinci Resolve
to generate the native 1080p50 file to try.


> 
> Regards,
> Marton
> 
> 
> > 
> > > 
> > > Regards,
> > > Marton
> > > 
> > > 
> > > > > > > > Thanks,
> > > > > Marton
> > > > > > > > > That's why I check the last TC to get the frame is even
> > > or odd.
> > > > > > > Why not use av_timecode_get_smpte_from_framenum(), for it's
> > > > > calculated by the string TC by one time,
> > > > > > so it lacks the information whether it's odd or even frame.
> > > > > > > > > > Regards,
> > > > > > > Marton
> > > > > > > > > > > ---
> > > > > > > > libavdevice/decklink_common.h |  1 +
> > > > > > > > libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
> > > > > > > > 2 files changed, 15 insertions(+)
> > > > > > > > > diff --git a/libavdevice/decklink_common.h
> > > > > > > b/libavdevice/decklink_common.h
> > > > > > > > index bd68c7b..8ddc411 100644
> > > > > > > > --- a/libavdevice/decklink_common.h
> > > > > > > > +++ b/libavdevice/decklink_common.h
> > > > > > > > @@ -151,6 +151,7 @@ struct decklink_ctx {
> > > > > > > >     int channels;
> > > > > > > >     int audio_depth;
> > > > > > > >     unsigned long tc_seen;    // used with option wait_for_tc
> > > > > > > > +    uint32_t last_tc;
> > > > > > > > };
> > > > > > > > > typedef enum { DIRECTION_IN, DIRECTION_OUT}
> > > > > > > decklink_direction_t;
> > > > > > > > diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
> > > > > > > > index dde68ff..a60c01b 100644
> > > > > > > > --- a/libavdevice/decklink_dec.cpp
> > > > > > > > +++ b/libavdevice/decklink_dec.cpp
> > > > > > > > @@ -884,12 +884,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
> > > > > > > >                         int metadata_len;
> > > > > > > >                         uint8_t* packed_metadata;
> > > > > > > >                         AVTimecode tcr;
> > > > > > > > +                        AVRational rate = ctx->video_st->r_frame_rate;
> > > > > > > > >                         if (av_timecode_init_from_string(&tcr,
> > > > > > > ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
> > > > > > > >                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
> > > > > > > >                             int size = sizeof(uint32_t) * 4;
> > > > > > > >                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
> > > > > > > > > +                            /* set the field flag if frame rate
> > > > > > > > 30FPS */
> > > > > > > > +                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
> > > > > > > > +                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
> > > > > > > > +                                /* Odd frame */
> > > > > > > > +                                if (ctx->last_tc == tc_data) {
> > > > > > > > +                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
> > > > > > > > +                                        tc_data |= (1 << 7);
> > > > > > > > +                                    else
> > > > > > > > +                                        tc_data |= (1 << 23);
> > > > > > > > +                                }
> > > > > > > > +                            }
> > > > > > > > +                            ctx->last_tc = tc_data;
> > > > > > > > +
> > > > > > > >                             if (sd) {
> > > > > > > >                                 *sd       = 1;       // one TC
> > > > > > > >                                 *(sd + 1) = tc_data; // TC
> > > > > > > > -- > 2.9.4
> > > > > > > > > _______________________________________________
> > > > > > > > ffmpeg-devel mailing list
> > > > > > > > ffmpeg-devel@ffmpeg.org
> > > > > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > > > > > > > To unsubscribe, visit link above, or email
> > > > > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > > > > > > _______________________________________________
> > > > > > > ffmpeg-devel mailing list
> > > > > > > ffmpeg-devel@ffmpeg.org
> > > > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > > > > > > > To unsubscribe, visit link above, or email
> > > > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > > > > > > -- > Thanks,
> > > > > > Limin Wang
> > > > > > _______________________________________________
> > > > > > ffmpeg-devel mailing list
> > > > > > ffmpeg-devel@ffmpeg.org
> > > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > > > > > To unsubscribe, visit link above, or email
> > > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > > > > _______________________________________________
> > > > > ffmpeg-devel mailing list
> > > > > ffmpeg-devel@ffmpeg.org
> > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > > > > > To unsubscribe, visit link above, or email
> > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > > > > -- > Thanks,
> > > > Limin Wang
> > > > _______________________________________________
> > > > ffmpeg-devel mailing list
> > > > ffmpeg-devel@ffmpeg.org
> > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > > > To unsubscribe, visit link above, or email
> > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > > _______________________________________________
> > > ffmpeg-devel mailing list
> > > ffmpeg-devel@ffmpeg.org
> > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > > 
> > > To unsubscribe, visit link above, or email
> > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> > 
> > -- 
> > Thanks,
> > Limin Wang
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> > 
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Marton Balint July 20, 2020, 3:21 p.m. UTC | #9
On Mon, 20 Jul 2020, lance.lmwang@gmail.com wrote:

> On Sun, Jul 19, 2020 at 09:05:33AM +0200, Marton Balint wrote:
>> 
>> 
>> On Sun, 19 Jul 2020, lance.lmwang@gmail.com wrote:
>> 
>> > On Sat, Jul 18, 2020 at 08:38:16PM +0200, Marton Balint wrote:
>> > > 
>> > > 
>> > > On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
>> > > 
>> > > > On Sat, Jul 18, 2020 at 09:44:03AM +0200, Marton Balint wrote:
>> > > > > > > > > On Sat, 18 Jul 2020, lance.lmwang@gmail.com wrote:
>> > > > > > > > On Fri, Jul 17, 2020 at 07:13:28PM +0200, Marton Balint
>> > > wrote:
>> > > > > > > > > > > On Fri, 17 Jul 2020, lance.lmwang@gmail.com wrote:
>> > > > > > > > > > From: Limin Wang <lance.lmwang@gmail.com>
>> > > > > > > > > In SMPTE ST 12-1: 2014 Sec 12.2, we need to mark the frame flag
>> > > > > > > if the frame rate > 30FPS to
>> > > > > > > > avoid interoperability issues. It will be used by the encoder to identify even or odd frames
>> > > > > > > > and correctly calculate the frame number of the SEI TC.
>> > > > > > > > > This feature looks like it belongs to
>> > > > > av_timecode_get_smpte_from_framenum
>> > > > > > > and not into decklink. Also checking previous timecode and guessing
>> > > > > > > something is a hack, especially since you have the exact source timecode.
>> > > > > > If I understand correctly, it's not hacky, for the framerate > 30, the source timecode will be
>> > > > > > frame pair(it's limited by 2bits limit of frame number ten digital. Below is one exmaple for 50fps
>> > > > > > if you tested with SDI with TC.
>> > > > > > 00:00:00:24
>> > > > > > 00:00:00:24
>> > > > > > 00:00:00:25
>> > > > > > 00:00:00:25
>> > > > > > 00:00:00:00
>> > > > > > 00:00:00:00
>> > > > > > > Have you actually tested this with a real SDI signal
>> > > containing timecode?
>> > > > > Yes, have tested with SDI playback by decklink UltraStudio 4K
>> > > mini with TC enabled.
>> > > 
>> > > I still don't understand how this works. Isn't timecode in the SDI signal
>> > > also contain the so called "field bit" flag to support 50fps timecode? And
>> > > if it does, then why can't you query it from decklink? Timecode in SDI
>> > > signal is also supposed to be an SMPTE 12M timecode, so all the bits you
>> > > need should be in it, you should not need to guess anything. Therefore it
>> > > makes little sense to me that the DeckLink API does not provide a proper
>> > > timecode as string, unless the original capture you made with your
>> > > UltraStudio and which you played back also has a faulty timecode.
>> > > What generated the signal which you captured with UltraStudio? Not ffmpeg I
>> > > hope...
>> > 
>> > It's auto-generated by configure of UltraStudio.
>> 
>> You mean using XLR timecode input selection? I would not trust that with
>> 50fps...
>
> I'm not sure it's XLR or not, it's configured by the menu.
>
>> 
>> > I have tested with bmdTimecodeFieldMark
>> > flag, it's not set as expected for testing. I have no clue how to get
>> > the flag as the API provide the TC string is same for the frame pair.
>> > Maybe I miss something.
>> 
>> I'd try to generate SDI video with timecode by some other means. E.g. using
>> MediaExpress / DaVinci Resolve and a native 1080p50 file.
>
> What's your tested result for the 1080p50 file?  I haven't MediaExpress / DaVinci Resolve
> to generate the native 1080p50 file to try.

I have not tested anything, all I am saying is that I find that highly 
unlikely that decklink API cannot detect a 50fps timecode properly in the 
SDI signal, so I suspect that your tests are somehow flawed, and you 
should try testing by some other means.

I can do tests next week if you don't figure it out until then.

Regards,
Marton

>
>
>> 
>> Regards,
>> Marton
>> 
>> 
>> > 
>> > > 
>> > > Regards,
>> > > Marton
>> > > 
>> > > 
>> > > > > > > > Thanks,
>> > > > > Marton
>> > > > > > > > > That's why I check the last TC to get the frame is even
>> > > or odd.
>> > > > > > > Why not use av_timecode_get_smpte_from_framenum(), for it's
>> > > > > calculated by the string TC by one time,
>> > > > > > so it lacks the information whether it's odd or even frame.
>> > > > > > > > > > Regards,
>> > > > > > > Marton
>> > > > > > > > > > > ---
>> > > > > > > > libavdevice/decklink_common.h |  1 +
>> > > > > > > > libavdevice/decklink_dec.cpp  | 14 ++++++++++++++
>> > > > > > > > 2 files changed, 15 insertions(+)
>> > > > > > > > > diff --git a/libavdevice/decklink_common.h
>> > > > > > > b/libavdevice/decklink_common.h
>> > > > > > > > index bd68c7b..8ddc411 100644
>> > > > > > > > --- a/libavdevice/decklink_common.h
>> > > > > > > > +++ b/libavdevice/decklink_common.h
>> > > > > > > > @@ -151,6 +151,7 @@ struct decklink_ctx {
>> > > > > > > >     int channels;
>> > > > > > > >     int audio_depth;
>> > > > > > > >     unsigned long tc_seen;    // used with option wait_for_tc
>> > > > > > > > +    uint32_t last_tc;
>> > > > > > > > };
>> > > > > > > > > typedef enum { DIRECTION_IN, DIRECTION_OUT}
>> > > > > > > decklink_direction_t;
>> > > > > > > > diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
>> > > > > > > > index dde68ff..a60c01b 100644
>> > > > > > > > --- a/libavdevice/decklink_dec.cpp
>> > > > > > > > +++ b/libavdevice/decklink_dec.cpp
>> > > > > > > > @@ -884,12 +884,26 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
>> > > > > > > >                         int metadata_len;
>> > > > > > > >                         uint8_t* packed_metadata;
>> > > > > > > >                         AVTimecode tcr;
>> > > > > > > > +                        AVRational rate = ctx->video_st->r_frame_rate;
>> > > > > > > > >                         if (av_timecode_init_from_string(&tcr,
>> > > > > > > ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
>> > > > > > > >                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
>> > > > > > > >                             int size = sizeof(uint32_t) * 4;
>> > > > > > > >                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
>> > > > > > > > > +                            /* set the field flag if frame rate
>> > > > > > > > 30FPS */
>> > > > > > > > +                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
>> > > > > > > > +                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
>> > > > > > > > +                                /* Odd frame */
>> > > > > > > > +                                if (ctx->last_tc == tc_data) {
>> > > > > > > > +                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
>> > > > > > > > +                                        tc_data |= (1 << 7);
>> > > > > > > > +                                    else
>> > > > > > > > +                                        tc_data |= (1 << 23);
>> > > > > > > > +                                }
>> > > > > > > > +                            }
>> > > > > > > > +                            ctx->last_tc = tc_data;
>> > > > > > > > +
>> > > > > > > >                             if (sd) {
>> > > > > > > >                                 *sd       = 1;       // one TC
>> > > > > > > >                                 *(sd + 1) = tc_data; // TC
>> > > > > > > > -- > 2.9.4
>> > > > > > > > > _______________________________________________
>> > > > > > > > ffmpeg-devel mailing list
>> > > > > > > > ffmpeg-devel@ffmpeg.org
>> > > > > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > > > > > > > To unsubscribe, visit link above, or email
>> > > > > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > > > > > > _______________________________________________
>> > > > > > > ffmpeg-devel mailing list
>> > > > > > > ffmpeg-devel@ffmpeg.org
>> > > > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > > > > > > > To unsubscribe, visit link above, or email
>> > > > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > > > > > > -- > Thanks,
>> > > > > > Limin Wang
>> > > > > > _______________________________________________
>> > > > > > ffmpeg-devel mailing list
>> > > > > > ffmpeg-devel@ffmpeg.org
>> > > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > > > > > To unsubscribe, visit link above, or email
>> > > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > > > > _______________________________________________
>> > > > > ffmpeg-devel mailing list
>> > > > > ffmpeg-devel@ffmpeg.org
>> > > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > > > > > To unsubscribe, visit link above, or email
>> > > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > > > > -- > Thanks,
>> > > > Limin Wang
>> > > > _______________________________________________
>> > > > ffmpeg-devel mailing list
>> > > > ffmpeg-devel@ffmpeg.org
>> > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > > > To unsubscribe, visit link above, or email
>> > > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > > _______________________________________________
>> > > ffmpeg-devel mailing list
>> > > ffmpeg-devel@ffmpeg.org
>> > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > > 
>> > > To unsubscribe, visit link above, or email
>> > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> > 
>> > -- 
>> > Thanks,
>> > Limin Wang
>> > _______________________________________________
>> > ffmpeg-devel mailing list
>> > ffmpeg-devel@ffmpeg.org
>> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > 
>> > To unsubscribe, visit link above, or email
>> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> 
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
> -- 
> Thanks,
> Limin Wang
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Marton Balint July 20, 2020, 9:12 p.m. UTC | #10
On Mon, 20 Jul 2020, Marton Balint wrote:

>
> This feature looks like it belongs to 
> av_timecode_get_smpte_from_framenum and not into decklink.

I just sent a patch which implements this, because I confirmed that other 
code using av_timecode_get_smpte_from_framenum also seem to require the 
special handling for 50/60fps which you already implemented in 
av_timecode_get_smpte.

Regards,
Marton
Marton Balint July 29, 2020, 8:16 p.m. UTC | #11
>>> > > > > > if you tested with SDI with TC.
>>> > > > > > 00:00:00:24
>>> > > > > > 00:00:00:24
>>> > > > > > 00:00:00:00
>>> > > > > > 00:00:00:00

I did tests, and depending on which timecode you select, and the timecode 
formats which are available in the SDI signal, this really can be the 
case, so you were right that the decklink API usually does not provide the 
proper timecode as string, only the value of "raw" timecodes in the 
signal, regardless of used frame rate.

I could not test, but assume that if a high frame rate timecode is 
detected then valid string timecode is returned. Otherwise max 30fps 
timecode.

>>> > I have tested with bmdTimecodeFieldMark
>>> > flag, it's not set as expected for testing. I have no clue how to get
>>> > the flag as the API provide the TC string is same for the frame pair.
>>> > Maybe I miss something.

SMPTE ST 12-2 has a good overview of the used signalling in section 7. 
Basically for 50/60 fps different timecode types (VITC1, VITC2) are used 
for different parity frames.

We have to be smart here to generate proper timecode, because the decklink 
API does not tell you which timecode it had found for an rp188any query... 
I suggest the following:

- If the user selects high frame rate timecode (not available as an
   option at the moment, but can be added), then use that directly.
- If the user selects rp188any then
   - Query high frame rate timecode, if exists use that directly.
   - Otherwise
     - for <= 30fps query rp188any and use that directly
     - for > 30fps
       - query VITC1, if exists use that with frame doubling and field flag
         checking
       - otherwise query VITC2, if exists use that with frame doubling
         and field flag checking
       - otherwise query LTC, if exists use that with frame doubling and
         field flag checking
       - note that this special ordering of querying the timecode types
         is slightly different from what the decklink API does and it
         should be mentioned in the docs.
- Otherwise
   - for <= 30fps query the selected timecode and use that directly
   - for > 30fps query the selected timecode and use that with frame
     doubling and field flag checking

Also probably it is better to use IDeckLinkTimecode->GetComponents() and 
use av_timecode_get_smpte() instead of using the string value.

Regards,
Marton
Limin Wang July 30, 2020, 1:39 a.m. UTC | #12
On Wed, Jul 29, 2020 at 10:16:33PM +0200, Marton Balint wrote:
> 
> 
> > > > > > > > > if you tested with SDI with TC.
> > > > > > > > > 00:00:00:24
> > > > > > > > > 00:00:00:24
> > > > > > > > > 00:00:00:00
> > > > > > > > > 00:00:00:00
> 
> I did tests, and depending on which timecode you select, and the timecode
> formats which are available in the SDI signal, this really can be the case,
> so you were right that the decklink API usually does not provide the proper
> timecode as string, only the value of "raw" timecodes in the signal,
> regardless of used frame rate.
> 
> I could not test, but assume that if a high frame rate timecode is detected
> then valid string timecode is returned. Otherwise max 30fps timecode.
> 
> > > > > I have tested with bmdTimecodeFieldMark
> > > > > flag, it's not set as expected for testing. I have no clue how to get
> > > > > the flag as the API provide the TC string is same for the frame pair.
> > > > > Maybe I miss something.
> 
> SMPTE ST 12-2 has a good overview of the used signalling in section 7.
> Basically for 50/60 fps different timecode types (VITC1, VITC2) are used for
> different parity frames.
> 
> We have to be smart here to generate proper timecode, because the decklink
> API does not tell you which timecode it had found for an rp188any query... I
> suggest the following:
> 
> - If the user selects high frame rate timecode (not available as an
>   option at the moment, but can be added), then use that directly.
> - If the user selects rp188any then
>   - Query high frame rate timecode, if exists use that directly.
>   - Otherwise
>     - for <= 30fps query rp188any and use that directly
>     - for > 30fps
>       - query VITC1, if exists use that with frame doubling and field flag
>         checking
>       - otherwise query VITC2, if exists use that with frame doubling
>         and field flag checking
>       - otherwise query LTC, if exists use that with frame doubling and
>         field flag checking
>       - note that this special ordering of querying the timecode types
>         is slightly different from what the decklink API does and it
>         should be mentioned in the docs.
> - Otherwise
>   - for <= 30fps query the selected timecode and use that directly
>   - for > 30fps query the selected timecode and use that with frame
>     doubling and field flag checking
The suggestion is very clear, I lacks the different TC test signal so I can't
try to implement and test it yet.

> 
> Also probably it is better to use IDeckLinkTimecode->GetComponents() and use
> av_timecode_get_smpte() instead of using the string value.

Yes, the TC format is rp188any when I test, I recall I have try to get by GetComponents, 
the result is consistent with string() before, I'll try to retest again if I 
test signal is avaiable.


> 
> Regards,
> Marton
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
diff mbox series

Patch

diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
index bd68c7b..8ddc411 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -151,6 +151,7 @@  struct decklink_ctx {
     int channels;
     int audio_depth;
     unsigned long tc_seen;    // used with option wait_for_tc
+    uint32_t last_tc;
 };
 
 typedef enum { DIRECTION_IN, DIRECTION_OUT} decklink_direction_t;
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index dde68ff..a60c01b 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -884,12 +884,26 @@  HRESULT decklink_input_callback::VideoInputFrameArrived(
                         int metadata_len;
                         uint8_t* packed_metadata;
                         AVTimecode tcr;
+                        AVRational rate = ctx->video_st->r_frame_rate;
 
                         if (av_timecode_init_from_string(&tcr, ctx->video_st->r_frame_rate, tc, ctx) >= 0) {
                             uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0);
                             int size = sizeof(uint32_t) * 4;
                             uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size);
 
+                            /* set the field flag if frame rate > 30FPS */
+                            /* Refer to SMPTE ST 12-1:2014 Sec 12.2 */
+                            if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) {
+                                /* Odd frame */
+                                if (ctx->last_tc == tc_data) {
+                                    if (av_cmp_q(rate, (AVRational) {50, 1}) == 0)
+                                        tc_data |= (1 << 7);
+                                    else
+                                        tc_data |= (1 << 23);
+                                }
+                            }
+                            ctx->last_tc = tc_data;
+
                             if (sd) {
                                 *sd       = 1;       // one TC
                                 *(sd + 1) = tc_data; // TC