-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path0010-32-bit-timecode-to-64-bit-RFC-5484-timecode-function.patch
More file actions
156 lines (151 loc) · 6.03 KB
/
0010-32-bit-timecode-to-64-bit-RFC-5484-timecode-function.patch
File metadata and controls
156 lines (151 loc) · 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
From 483a4d96fb7f0663331d0c6750880974f2a287e7 Mon Sep 17 00:00:00 2001
From: Dave Rice <dave at dericed.com>
Date: Mon, 30 Jun 2025 00:00:00 +0200
Subject: [PATCH 10/19] 32-bit timecode to 64-bit RFC 5484 timecode functions
---
libavutil/timecode.c | 104 +++++++++++++++++++++++++++++++++++++++++++
libavutil/timecode.h | 22 +++++++++
2 files changed, 126 insertions(+)
diff --git a/libavutil/timecode.c b/libavutil/timecode.c
index b5352a3961..341a4fef98 100644
--- a/libavutil/timecode.c
+++ b/libavutil/timecode.c
@@ -243,3 +243,107 @@ int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *st
return av_timecode_init_from_components(tc, rate, flags, hh, mm, ss, ff, log_ctx);
}
+
+static int bcd_to_int(int bcd) {
+ return ((bcd >> 4) & 0xF) * 10 + (bcd & 0xF);
+}
+
+uint64_t av_timecode_expand_to_64bit(uint32_t tc32)
+{
+ uint64_t tc64 = 0;
+
+ int hours_bcd = tc32 & 0x3F; // bits 0-5
+ int bgf1 = (tc32 >> 6) & 0x1; // bit 6
+ int bgf2 = (tc32 >> 7) & 0x1; // bit 7
+ int minutes_bcd = (tc32 >> 8) & 0x7F; // bits 8-14
+ int bgf0 = (tc32 >> 15) & 0x1; // bit 15
+ int seconds_bcd = (tc32 >> 16) & 0x7F; // bits 16-22
+ int frames_bcd = (tc32 >> 24) & 0x3F; // bits 24-29
+ int drop = (tc32 >> 30) & 0x1; // bit 30
+ int color = (tc32 >> 31) & 0x1; // bit 31
+
+ int hours = bcd_to_int(hours_bcd);
+ int minutes = bcd_to_int(minutes_bcd);
+ int seconds = bcd_to_int(seconds_bcd);
+ int frames = bcd_to_int(frames_bcd);
+
+ // Units and tens
+ int uh = hours % 10, th = hours / 10;
+ int um = minutes % 10, tm = minutes / 10;
+ int us = seconds % 10, ts = seconds / 10;
+ int uf = frames % 10, tf = frames / 10;
+
+ // Assign bits as per RFC 5484 layout
+ tc64 |= (uint64_t)(uf & 0xF) << 0; // Units of frames
+ tc64 |= 0 << 4; // First binary group
+ tc64 |= (uint64_t)(tf & 0x3) << 8; // Tens of frames (2 bits)
+ tc64 |= (uint64_t)drop << 10; // Drop frame flag
+ tc64 |= (uint64_t)color << 11; // Color frame flag
+ tc64 |= 0 << 12; // Second binary group
+
+ tc64 |= (uint64_t)(us & 0xF) << 16; // Units of seconds
+ tc64 |= 0 << 20; // Third binary group
+ tc64 |= (uint64_t)(ts & 0x7) << 24; // Tens of seconds
+ tc64 |= 0 << 27; // Polarity correction
+ tc64 |= 0 << 28; // Fourth binary group
+
+ tc64 |= (uint64_t)(um & 0xF) << 32; // Units of minutes
+ tc64 |= (uint64_t)0 << 36; // Fifth binary group
+ tc64 |= (uint64_t)(tm & 0x7) << 40; // Tens of minutes
+ tc64 |= (uint64_t)bgf0 << 43; // BGF0
+ tc64 |= (uint64_t)0 << 44; // Sixth binary group
+
+ tc64 |= (uint64_t)(uh & 0xF) << 48; // Units of hours
+ tc64 |= (uint64_t)0 << 52; // Seventh binary group
+ tc64 |= (uint64_t)(th & 0x3) << 56; // Tens of hours
+ tc64 |= (uint64_t)bgf1 << 58; // BGF1
+ tc64 |= (uint64_t)bgf2 << 59; // BGF2
+ tc64 |= (uint64_t)0 << 60; // Eighth binary group
+
+ return tc64;
+}
+
+static int int_to_bcd(int val) {
+ return ((val / 10) << 4) | (val % 10);
+}
+
+uint32_t av_timecode_parse_from_64bit(uint64_t tc64)
+{
+ uint32_t tc32 = 0;
+
+ int uf = (tc64 >> 0) & 0xF; // Ones of frames
+ int tf = (tc64 >> 8) & 0x3; // Tens of frames
+ int drop = (tc64 >> 10) & 0x1;
+ int color= (tc64 >> 11) & 0x1;
+
+ int us = (tc64 >> 16) & 0xF; // Ones of seconds
+ int ts = (tc64 >> 24) & 0x7; // Tens of seconds
+
+ int um = (tc64 >> 32) & 0xF; // Ones of minutes
+ int tm = (tc64 >> 40) & 0x7; // Tens of minutes
+ int bgf0 = (tc64 >> 43) & 0x1;
+
+ int uh = (tc64 >> 48) & 0xF; // Ones of hours
+ int th = (tc64 >> 56) & 0x3; // Tens of hours
+ int bgf1 = (tc64 >> 58) & 0x1;
+ int bgf2 = (tc64 >> 59) & 0x1;
+
+ int hours = int_to_bcd(th * 10 + uh);
+ int minutes = int_to_bcd(tm * 10 + um);
+ int seconds = int_to_bcd(ts * 10 + us);
+ int frames = int_to_bcd(tf * 10 + uf);
+
+ // Assemble tc32 using the FFmpeg SMPTE 32-bit format
+ tc32 |= (hours & 0x3F) << 0; // bits 0-5: hours (BCD)
+ tc32 |= (bgf1 & 0x1) << 6; // bit 6: BGF1
+ tc32 |= (bgf2 & 0x1) << 7; // bit 7: BGF2 (or FIELD)
+ tc32 |= (minutes & 0x7F) << 8; // bits 8-14: minutes (BCD)
+ tc32 |= (bgf0 & 0x1) << 15; // bit 15: BGF0
+ tc32 |= (seconds & 0x7F) << 16; // bits 16-22: seconds (BCD)
+ tc32 |= 0 << 23; // bit 23: FIELD (set to 0)
+ tc32 |= (frames & 0x3F) << 24; // bits 24-29: frames (BCD)
+ tc32 |= (drop & 0x1) << 30; // bit 30: drop frame flag
+ tc32 |= (color & 0x1) << 31; // bit 31: color frame flag
+
+ return tc32;
+}
diff --git a/libavutil/timecode.h b/libavutil/timecode.h
index fe0fc83576..81713a9adf 100644
--- a/libavutil/timecode.h
+++ b/libavutil/timecode.h
@@ -196,4 +196,26 @@ int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *st
*/
int av_timecode_check_frame_rate(AVRational rate);
+/**
+ * Convert a 32-bit SMPTE 12M timecode to 64-bit SMPTE 12M/RFC 5484 format.
+ *
+ * This maps the timecode as described in RFC 5484 Section 6.2,
+ * expanding BCD-encoded time values into bit fields without the sync word.
+ *
+ * @param tc32 The 32-bit SMPTE timecode (from DeckLink or av_timecode_get_smpte)
+ * @return The 64-bit SMPTE 12M timecode format (without sync word)
+ */
+uint64_t av_timecode_expand_to_64bit(uint32_t tc32);
+
+/**
+ * Convert a 64-bit SMPTE 12M/RFC 5484 timecode to 32-bit SMPTE format.
+ *
+ * This reconstructs the packed 32-bit SMPTE timecode (DeckLink-style or FFmpeg output)
+ * from a full 64-bit representation.
+ *
+ * @param tc64 The 64-bit timecode value in RFC 5484 / SMPTE 12M format (without sync word)
+ * @return A 32-bit SMPTE timecode
+ */
+uint32_t av_timecode_parse_from_64bit(uint64_t tc64);
+
#endif /* AVUTIL_TIMECODE_H */
--
2.52.0