FFmpeg
Loading...
Searching...
No Matches
ccfifo.c
Go to the documentation of this file.
1/*
2 * CEA-708 Closed Captioning FIFO
3 * Copyright (c) 2023 LTN Global Communications
4 *
5 * Author: Devin Heitmueller <dheitmueller@ltnglobal.com>
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include "ccfifo.h"
25#include "libavutil/fifo.h"
26
27#define MAX_CC_ELEMENTS 128
28
29struct cc_lookup {
30 int num;
31 int den;
34};
35
36const static struct cc_lookup cc_lookup_vals[] = {
37 { 15, 1, 40, 4 },
38 { 24, 1, 25, 3 },
39 { 24000, 1001, 25, 3 },
40 { 30, 1, 20, 2 },
41 { 30000, 1001, 20, 2},
42 { 60, 1, 10, 1 },
43 { 60000, 1001, 10, 1},
44};
45
47{
50 memset(ccf, 0, sizeof(*ccf));
51}
52
53int ff_ccfifo_init(CCFifo *ccf, AVRational framerate, void *log_ctx)
54{
55 int i;
56
57 memset(ccf, 0, sizeof(*ccf));
58 ccf->log_ctx = log_ctx;
59 ccf->framerate = framerate;
60
62 goto error;
63
65 goto error;
66
67 /* Based on the target FPS, figure out the expected cc_count and number of
68 608 tuples per packet. See ANSI/CTA-708-E Sec 4.3.6.1. */
69 for (i = 0; i < FF_ARRAY_ELEMS(cc_lookup_vals); i++) {
70 if (framerate.num == cc_lookup_vals[i].num &&
71 framerate.den == cc_lookup_vals[i].den) {
72 ccf->expected_cc_count = cc_lookup_vals[i].cc_count;
73 ccf->expected_608 = cc_lookup_vals[i].num_608;
74 break;
75 }
76 }
77
78 if (ccf->expected_608 == 0) {
79 /* We didn't find an output frame we support. We'll let the call succeed
80 and the FIFO to be allocated, but the extract/inject functions will simply
81 leave everything the way it is */
82 ccf->passthrough = 1;
83 }
84
85 return 0;
86
87error:
89 return AVERROR(ENOMEM);
90}
91
92int ff_ccfifo_injectbytes(CCFifo *ccf, uint8_t *cc_data, size_t len)
93{
94 int cc_608_tuples = 0;
95 int cc_708_tuples = 0;
96 int cc_filled = 0;
97
98 if (ccf->passthrough) {
99 return 0;
100 }
101
102 if (len < ff_ccfifo_getoutputsize(ccf)) {
103 return AVERROR(EINVAL);
104 }
105
106 /* Insert any available data from the 608 FIFO */
107 if (ccf->expected_608 <= av_fifo_can_read(ccf->cc_608_fifo))
108 cc_608_tuples = ccf->expected_608;
109 else
110 cc_608_tuples = av_fifo_can_read(ccf->cc_608_fifo);
111 av_fifo_read(ccf->cc_608_fifo, cc_data, cc_608_tuples);
112 cc_filled += cc_608_tuples;
113
114 /* Insert any available data from the 708 FIFO */
115 if ((ccf->expected_cc_count - cc_filled) <= av_fifo_can_read(ccf->cc_708_fifo))
116 cc_708_tuples = ccf->expected_cc_count - cc_filled;
117 else
118 cc_708_tuples = av_fifo_can_read(ccf->cc_708_fifo);
119 av_fifo_read(ccf->cc_708_fifo, &cc_data[cc_filled * CC_BYTES_PER_ENTRY], cc_708_tuples);
120 cc_filled += cc_708_tuples;
121
122 /* Insert 708 padding into any remaining fields */
123 while (cc_filled < ccf->expected_cc_count) {
124 cc_data[cc_filled * CC_BYTES_PER_ENTRY] = 0xfa;
125 cc_data[cc_filled * CC_BYTES_PER_ENTRY + 1] = 0x00;
126 cc_data[cc_filled * CC_BYTES_PER_ENTRY + 2] = 0x00;
127 cc_filled++;
128 }
129
130 return 0;
131}
132
134{
135 AVFrameSideData *sd;
136 int ret;
137
138 if (ccf->passthrough == 1 || ccf->cc_detected == 0)
139 return 0;
140
143 if (sd) {
144 ret = ff_ccfifo_injectbytes(ccf, sd->data, sd->size);
145 if (ret < 0) {
147 return ret;
148 }
149 }
150
151 return 0;
152}
153
154int ff_ccfifo_extractbytes(CCFifo *ccf, uint8_t *cc_bytes, size_t len)
155{
157
158 if (ccf->passthrough == 1) {
160 "cc_fifo cannot transcode captions fps=%d/%d\n",
161 ccf->framerate.num, ccf->framerate.den);
162 return 0;
163 }
164
165 ccf->cc_detected = 1;
166
167 for (int i = 0; i < cc_count; i++) {
168 /* See ANSI/CTA-708-E Sec 4.3, Table 3 */
169 uint8_t cc_valid = (cc_bytes[CC_BYTES_PER_ENTRY*i] & 0x04) >> 2;
170 uint8_t cc_type = cc_bytes[CC_BYTES_PER_ENTRY*i] & 0x03;
171 if (cc_type == 0x00 || cc_type == 0x01) {
172 av_fifo_write(ccf->cc_608_fifo, &cc_bytes[CC_BYTES_PER_ENTRY*i], 1);
173 } else if (cc_valid && (cc_type == 0x02 || cc_type == 0x03)) {
174 av_fifo_write(ccf->cc_708_fifo, &cc_bytes[CC_BYTES_PER_ENTRY*i], 1);
175 }
176 }
177 return 0;
178}
179
180/* Read the A53 side data, discard padding, and put 608/708 into
181 queues so we can ensure they get into the output frames at
182 the correct rate... */
184{
186 if (side_data) {
187 ff_ccfifo_extractbytes(ccf, side_data->data, side_data->size);
188
189 /* Remove the side data, as we will re-create it on the
190 output as needed */
191 if (!ccf->passthrough)
193 }
194 return 0;
195}
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
CC FIFO Buffer.
static int ff_ccfifo_getoutputsize(const CCFifo *ccf)
Provide the size in bytes of an output buffer to allocate.
Definition ccfifo.h:95
#define CC_BYTES_PER_ENTRY
Definition ccfifo.h:38
static AVFrame * frame
A generic FIFO API.
#define AVERROR(e)
Definition error.h:45
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition fifo.c:47
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition fifo.c:286
size_t av_fifo_can_read(const AVFifo *f)
Definition fifo.c:87
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition fifo.c:188
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition fifo.c:240
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition frame.c:659
void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
Remove and free all side data instances of the given type.
Definition frame.c:725
AVFrameSideData * av_frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, size_t size)
Add a new side data to a frame.
Definition frame.c:647
@ AV_FRAME_DATA_A53_CC
ATSC A53 Part 4 Closed Captions.
Definition frame.h:59
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
int ff_ccfifo_inject(CCFifo *ccf, AVFrame *frame)
Insert CC data from the FIFO into an AVFrame (as side data)
Definition ccfifo.c:133
int ff_ccfifo_init(CCFifo *ccf, AVRational framerate, void *log_ctx)
Initialize a CCFifo.
Definition ccfifo.c:53
#define MAX_CC_ELEMENTS
Definition ccfifo.c:27
int ff_ccfifo_extractbytes(CCFifo *ccf, uint8_t *cc_bytes, size_t len)
Just like ff_ccfifo_extract(), but takes the raw bytes instead of an AVFrame.
Definition ccfifo.c:154
int ff_ccfifo_injectbytes(CCFifo *ccf, uint8_t *cc_data, size_t len)
Just like ff_ccfifo_inject(), but takes the raw bytes to insert the CC data int rather than an AVFram...
Definition ccfifo.c:92
void ff_ccfifo_uninit(CCFifo *ccf)
Free all memory allocated in a CCFifo and clear the context.
Definition ccfifo.c:46
int ff_ccfifo_extract(CCFifo *ccf, AVFrame *frame)
Extract CC data from an AVFrame.
Definition ccfifo.c:183
static const struct cc_lookup cc_lookup_vals[]
Definition ccfifo.c:36
void av_log_once(void *avcl, int initial_level, int subsequent_level, int *state, const char *fmt,...)
Definition log.c:450
#define FF_ARRAY_ELEMS(a)
Structure to hold side data for an AVFrame.
Definition frame.h:327
size_t size
Definition frame.h:330
uint8_t * data
Definition frame.h:329
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
int expected_cc_count
Definition ccfifo.h:44
int cc_detected
Definition ccfifo.h:46
struct AVFifo * cc_608_fifo
Definition ccfifo.h:41
int expected_608
Definition ccfifo.h:45
struct AVFifo * cc_708_fifo
Definition ccfifo.h:42
void * log_ctx
Definition ccfifo.h:49
int passthrough_warning
Definition ccfifo.h:48
AVRational framerate
Definition ccfifo.h:43
int passthrough
Definition ccfifo.h:47
int cc_count
Definition ccfifo.c:32
int den
Definition ccfifo.c:31
int num_608
Definition ccfifo.c:33
int num
Definition ccfifo.c:30
static void error(const char *err)
float framerate
Definition av1_levels.c:29
int len