Skip to content

Commit 490afff

Browse files
author
Philip de Nier
committed
raw2bmx: Add support for ANC/VBI frame wrapped in KLV
1 parent 9a79daf commit 490afff

File tree

7 files changed

+227
-23
lines changed

7 files changed

+227
-23
lines changed

apps/raw2bmx/raw2bmx.cpp

+40-11
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include <bmx/essence_parser/RawEssenceReader.h>
6565
#include <bmx/essence_parser/FileEssenceSource.h>
6666
#include <bmx/essence_parser/KLVEssenceSource.h>
67+
#include <bmx/essence_parser/KLVEssenceReader.h>
6768
#include <bmx/essence_parser/FilePatternEssenceSource.h>
6869
#include <bmx/essence_parser/D10RawEssenceReader.h>
6970
#include <bmx/essence_parser/MPEG2AspectRatioFilter.h>
@@ -153,6 +154,7 @@ struct RawInput
153154

154155
RawEssenceReader *raw_reader;
155156
WaveReader *wave_reader;
157+
KLVEssenceReader *klv_reader;
156158
uint32_t channel_count;
157159
TimedTextManifestParser *timed_text_manifest;
158160

@@ -256,14 +258,20 @@ static uint32_t read_samples(RawInput *input, uint32_t max_samples_per_read)
256258
uint32_t num_frame_samples = input->sample_sequence[input->sample_sequence_offset];
257259
input->sample_sequence_offset = (input->sample_sequence_offset + 1) % input->sample_sequence_size;
258260

259-
if (input->raw_reader)
261+
if (input->raw_reader) {
260262
return (input->raw_reader->ReadSamples(num_frame_samples) == num_frame_samples ? 1 : 0);
261-
else
263+
} else if (input->klv_reader) {
264+
BMX_ASSERT(num_frame_samples == 1);
265+
return (input->klv_reader->ReadValue() ? 1 : 0);
266+
} else {
262267
return (input->wave_reader->Read(num_frame_samples) == num_frame_samples ? 1 : 0);
268+
}
263269
} else {
264270
BMX_ASSERT(input->sample_sequence_size == 1 && input->sample_sequence[0] == 1);
265271
if (input->raw_reader)
266272
return input->raw_reader->ReadSamples(max_samples_per_read);
273+
else if (input->klv_reader)
274+
return (input->klv_reader->ReadValue() ? 1 : 0);
267275
else
268276
return input->wave_reader->Read(max_samples_per_read);
269277
}
@@ -327,6 +335,12 @@ static bool open_raw_reader(RawInput *input)
327335
{
328336
input->raw_reader = new D10RawEssenceReader(essence_source);
329337
}
338+
else if (input->parse_klv &&
339+
(input->essence_type == ANC_DATA ||
340+
input->essence_type == VBI_DATA))
341+
{
342+
input->klv_reader = new KLVEssenceReader(dynamic_cast<KLVEssenceSource*>(essence_source));
343+
}
330344
else
331345
{
332346
input->raw_reader = new RawEssenceReader(essence_source);
@@ -392,6 +406,7 @@ static void clear_input(RawInput *input)
392406
{
393407
delete input->raw_reader;
394408
delete input->wave_reader;
409+
delete input->klv_reader;
395410
delete input->filter;
396411
delete input->timed_text_manifest;
397412
delete input->wave_chunk_refs;
@@ -834,8 +849,8 @@ static void usage(const char *cmd)
834849
printf(" --vc3_1080i_1260 <name> Raw VC3/DNxHD 1920x1080i 85 Mbps input file\n");
835850
printf(" --pcm <name> Raw PCM audio input file\n");
836851
printf(" --wave <name> Wave PCM audio input file\n");
837-
printf(" --anc <name> Raw ST 436 Ancillary data. Currently requires the --anc-const option\n");
838-
printf(" --vbi <name> Raw ST 436 Vertical Blanking Interval data. Currently requires the --vbi-const option\n");
852+
printf(" --anc <name> Raw ST 436 Ancillary data. Requires the --anc-const option or frame wrapped in KLV and the --klv option\n");
853+
printf(" --vbi <name> Raw ST 436 Vertical Blanking Interval data. Requires the --vbi-const option or frame wrapped in KLV and the --klv option\n");
839854
printf(" --tt <manifest> Manifest file containing Timed Text metadata\n");
840855
printf("\n\n");
841856
printf("Notes:\n");
@@ -4045,10 +4060,10 @@ int main(int argc, const char** argv)
40454060
fprintf(stderr, "Multiple '%s' inputs are not permitted\n", argv[cmdln_index]);
40464061
return 1;
40474062
}
4048-
if (input.anc_const_size == 0)
4063+
if (input.anc_const_size == 0 && !input.parse_klv)
40494064
{
40504065
usage_ref(argv[0]);
4051-
fprintf(stderr, "Missing or zero '--anc-const' option for input '%s'\n", argv[cmdln_index]);
4066+
fprintf(stderr, "Missing or zero '--anc-const' or '--klv' options for input '%s'\n", argv[cmdln_index]);
40524067
return 1;
40534068
}
40544069
input.essence_type = ANC_DATA;
@@ -4071,7 +4086,7 @@ int main(int argc, const char** argv)
40714086
fprintf(stderr, "Multiple '%s' inputs are not permitted\n", argv[cmdln_index]);
40724087
return 1;
40734088
}
4074-
if (input.vbi_const_size == 0)
4089+
if (input.vbi_const_size == 0 && !input.parse_klv)
40754090
{
40764091
usage_ref(argv[0]);
40774092
fprintf(stderr, "Missing or zero '--vbi-const' option for input '%s'\n", argv[cmdln_index]);
@@ -5593,10 +5608,12 @@ int main(int argc, const char** argv)
55935608
clip_track->SetChannelAssignment(audio_layout_mode_label);
55945609
break;
55955610
case ANC_DATA:
5596-
clip_track->SetConstantDataSize(input->anc_const_size);
5611+
if (input->anc_const_size)
5612+
clip_track->SetConstantDataSize(input->anc_const_size);
55975613
break;
55985614
case VBI_DATA:
5599-
clip_track->SetConstantDataSize(input->vbi_const_size);
5615+
if (input->vbi_const_size)
5616+
clip_track->SetConstantDataSize(input->vbi_const_size);
56005617
break;
56015618
case TIMED_TEXT:
56025619
clip_track->SetTimedTextSource(input->timed_text_manifest);
@@ -5863,12 +5880,14 @@ int main(int argc, const char** argv)
58635880
case ANC_DATA:
58645881
input->sample_sequence[0] = 1;
58655882
input->sample_sequence_size = 1;
5866-
input->raw_reader->SetFixedSampleSize(input->anc_const_size);
5883+
if (input->raw_reader && input->anc_const_size)
5884+
input->raw_reader->SetFixedSampleSize(input->anc_const_size);
58675885
break;
58685886
case VBI_DATA:
58695887
input->sample_sequence[0] = 1;
58705888
input->sample_sequence_size = 1;
5871-
input->raw_reader->SetFixedSampleSize(input->vbi_const_size);
5889+
if (input->raw_reader && input->vbi_const_size)
5890+
input->raw_reader->SetFixedSampleSize(input->vbi_const_size);
58725891
break;
58735892
case TIMED_TEXT:
58745893
break;
@@ -6206,6 +6225,16 @@ int main(int argc, const char** argv)
62066225
input->raw_reader->GetSampleData(), input->raw_reader->GetSampleDataSize(),
62076226
num_samples);
62086227
}
6228+
} else if (input->klv_reader) {
6229+
num_samples = input->klv_reader->GetValueSize() ? 1 : 0;
6230+
if (num_samples) {
6231+
output_track->WriteSamples(
6232+
output_channel_index,
6233+
input->klv_reader->GetValue(),
6234+
input->klv_reader->GetValueSize(),
6235+
num_samples
6236+
);
6237+
}
62096238
} else {
62106239
Frame *frame = input->wave_reader->GetTrack(input_channel_index)->GetFrameBuffer()->GetLastFrame(false);
62116240
BMX_ASSERT(frame);

include/bmx/essence_parser/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ list(APPEND bmx_headers
99
bmx/essence_parser/FileEssenceSource.h
1010
bmx/essence_parser/FilePatternEssenceSource.h
1111
bmx/essence_parser/J2CEssenceParser.h
12+
bmx/essence_parser/KLVDataReader.h
1213
bmx/essence_parser/KLVEssenceSource.h
1314
bmx/essence_parser/MJPEGEssenceParser.h
1415
bmx/essence_parser/MPEG2AspectRatioFilter.h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (C) 2024, British Broadcasting Corporation
3+
* All Rights Reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* * Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in the
12+
* documentation and/or other materials provided with the distribution.
13+
* * Neither the name of the British Broadcasting Corporation nor the names
14+
* of its contributors may be used to endorse or promote products derived
15+
* from this software without specific prior written permission.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
*/
29+
30+
#ifndef BMX_KLV_ESSENCE_READER_H_
31+
#define BMX_KLV_ESSENCE_READER_H_
32+
33+
#include <bmx/essence_parser/KLVEssenceSource.h>
34+
#include <bmx/ByteArray.h>
35+
36+
37+
namespace bmx
38+
{
39+
40+
class KLVEssenceReader
41+
{
42+
public:
43+
KLVEssenceReader(KLVEssenceSource *essence_source);
44+
~KLVEssenceReader();
45+
46+
uint32_t ReadValue();
47+
48+
unsigned char* GetValue() const { return mValueBuffer.GetBytes(); }
49+
uint32_t GetValueSize() const { return mValueBuffer.GetSize(); }
50+
51+
private:
52+
KLVEssenceSource *mEssenceSource;
53+
ByteArray mValueBuffer;
54+
};
55+
56+
57+
};
58+
59+
60+
#endif

include/bmx/essence_parser/KLVEssenceSource.h

+6
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ class KLVEssenceSource : public EssenceSource
5959
virtual int GetErrno() const;
6060
virtual std::string GetStrError() const;
6161

62+
public:
63+
bool PositionInV(uint64_t *size);
64+
65+
uint64_t GetOffsetInV() const { return mValueLen - mRemValueLen; }
66+
6267
private:
6368
typedef enum
6469
{
@@ -73,6 +78,7 @@ class KLVEssenceSource : public EssenceSource
7378
uint32_t mTrackNum;
7479
KLVState mState;
7580
uint64_t mValueLen;
81+
uint64_t mRemValueLen;
7682
};
7783

7884

src/essence_parser/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ list(APPEND bmx_sources
88
essence_parser/FileEssenceSource.cpp
99
essence_parser/FilePatternEssenceSource.cpp
1010
essence_parser/J2CEssenceParser.cpp
11+
essence_parser/KLVEssenceReader.cpp
1112
essence_parser/KLVEssenceSource.cpp
1213
essence_parser/MJPEGEssenceParser.cpp
1314
essence_parser/MPEG2AspectRatioFilter.cpp
+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (C) 2024, British Broadcasting Corporation
3+
* All Rights Reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* * Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in the
12+
* documentation and/or other materials provided with the distribution.
13+
* * Neither the name of the British Broadcasting Corporation nor the names
14+
* of its contributors may be used to endorse or promote products derived
15+
* from this software without specific prior written permission.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
*/
29+
30+
#ifdef HAVE_CONFIG_H
31+
#include "config.h"
32+
#endif
33+
34+
#define __STDC_LIMIT_MACROS
35+
36+
#include <libMXF++/MXF.h>
37+
38+
#include <bmx/essence_parser/KLVEssenceReader.h>
39+
#include <bmx/BMXException.h>
40+
#include <bmx/Logging.h>
41+
42+
using namespace std;
43+
using namespace bmx;
44+
45+
46+
KLVEssenceReader::KLVEssenceReader(KLVEssenceSource *essence_source)
47+
{
48+
mEssenceSource = essence_source;
49+
}
50+
51+
KLVEssenceReader::~KLVEssenceReader()
52+
{
53+
}
54+
55+
uint32_t KLVEssenceReader::ReadValue()
56+
{
57+
// Position at the next non-zero Value
58+
uint64_t v_size = 0;
59+
while (v_size == 0) {
60+
if (!mEssenceSource->PositionInV(&v_size) || v_size > UINT32_MAX) {
61+
if (v_size > UINT32_MAX)
62+
log_warn("KLV value size %" PRIu64 " > max uint32 is not supported\n", v_size);
63+
mValueBuffer.SetSize(0);
64+
return 0;
65+
}
66+
}
67+
68+
// Expect to be at the start of the V because the read below reads the whole V
69+
BMX_CHECK(mEssenceSource->GetOffsetInV() == 0);
70+
71+
mValueBuffer.Allocate(v_size);
72+
73+
uint32_t read_size = mEssenceSource->Read(mValueBuffer.GetBytes(), v_size);
74+
if (read_size != v_size) {
75+
log_warn("Incomplete KLV; only read %u of %u\n", read_size, v_size);
76+
mValueBuffer.SetSize(0);
77+
return 0;
78+
}
79+
80+
mValueBuffer.SetSize(read_size);
81+
return read_size;
82+
}

0 commit comments

Comments
 (0)