3932 lines
85 KiB
C++
3932 lines
85 KiB
C++
/*
|
|
* libzvbi - vbi_dvb_mux unit test
|
|
*
|
|
* Copyright (C) 2007 Michael H. Schimek
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*/
|
|
|
|
/* $Id: test-dvb_mux.cc,v 1.6 2008/03/01 07:36:04 mschimek Exp $ */
|
|
|
|
#undef NDEBUG
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
#include <errno.h> /* XXX -> dvb_mux.h */
|
|
|
|
#include "src/misc.h"
|
|
#include "src/dvb.h"
|
|
#include "src/dvb_mux.h"
|
|
#include "src/dvb_demux.h"
|
|
#include "src/version.h"
|
|
|
|
#include "test-common.h"
|
|
|
|
#if 3 == VBI_VERSION_MINOR
|
|
# define sp_sample_format sample_format
|
|
# define sp_samples_per_line samples_per_line
|
|
#else
|
|
# define sp_sample_format sampling_format
|
|
/* Has no samples_per_line field yet. */
|
|
# define sp_samples_per_line bytes_per_line
|
|
#endif
|
|
|
|
// XXX Later.
|
|
enum {
|
|
VBI_ERR_BUFFER_OVERFLOW = 0,
|
|
VBI_ERR_AMBIGUOUS_VIDEOSTD = 0,
|
|
VBI_ERR_LINE_NUMBER = 0,
|
|
VBI_ERR_LINE_ORDER = 0,
|
|
VBI_ERR_INVALID_SERVICE = 0,
|
|
VBI_ERR_SAMPLE_NUMBER = 0,
|
|
VBI_ERR_NO_RAW_DATA = 0,
|
|
VBI_ERR_SAMPLING_PAR = 0,
|
|
};
|
|
|
|
enum {
|
|
EXPECT_FAILURE = FALSE,
|
|
EXPECT_SUCCESS = TRUE
|
|
};
|
|
|
|
// Data unit size.
|
|
enum {
|
|
VARIABLE = FALSE,
|
|
FIXED = TRUE
|
|
};
|
|
|
|
// Add stuffing data units.
|
|
enum {
|
|
NO_STUFFING = FALSE,
|
|
STUFFING = TRUE,
|
|
ANY_STUFFING = 0x12345,
|
|
};
|
|
|
|
static const unsigned int ANY_DATA_IDENTIFIER = 0x12345;
|
|
static const vbi_videostd_set ANY_VIDEOSTD = 0x12345;
|
|
|
|
static const vbi_service_set ALL_SERVICES = -1;
|
|
|
|
// EN 301 775 table 2.
|
|
static const unsigned int
|
|
data_identifiers[] = {
|
|
0, // "reserved for future use"
|
|
0x0F,
|
|
0x10, /* "EBU Teletext only or EBU Teletext combined with
|
|
VPS and/or WSS and/or Closed Captioning and/or
|
|
VBI sample data" */
|
|
0x1F,
|
|
0x20, // "reserved for future use"
|
|
0x7F,
|
|
0x80, // "user defined"
|
|
0x98,
|
|
0x99, /* "EBU Teletext and/or VPS and/or WSS and/or Closed
|
|
Captioning and/or VBI sample data" */
|
|
0x9B,
|
|
0x9C, // "user defined"
|
|
0xFF,
|
|
UINT_MAX
|
|
};
|
|
|
|
// EN 301 775 table 3.
|
|
static const vbi_service_set
|
|
good_services [] = {
|
|
0,
|
|
VBI_SLICED_CAPTION_625,
|
|
// EN 301 775 section 4.8.2: Only first field.
|
|
VBI_SLICED_CAPTION_625_F1,
|
|
VBI_SLICED_TELETEXT_B_625,
|
|
VBI_SLICED_TELETEXT_B_L10_625,
|
|
VBI_SLICED_TELETEXT_B_L25_625,
|
|
// EN 301 775 section 4.6.2: Only first field.
|
|
VBI_SLICED_VPS,
|
|
VBI_SLICED_WSS_625,
|
|
};
|
|
|
|
static vbi_bool
|
|
is_good_service (vbi_service_set service)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < N_ELEMENTS (good_services); ++i) {
|
|
if (service == good_services[i])
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static const vbi_service_set
|
|
all_services [] = {
|
|
0,
|
|
-1,
|
|
VBI_SLICED_2xCAPTION_525,
|
|
VBI_SLICED_CAPTION_525,
|
|
VBI_SLICED_CAPTION_525_F1,
|
|
VBI_SLICED_CAPTION_525_F2,
|
|
// Just a little challenge.
|
|
VBI_SLICED_CAPTION_625 | VBI_SLICED_WSS_625,
|
|
VBI_SLICED_CAPTION_625,
|
|
VBI_SLICED_CAPTION_625_F1,
|
|
VBI_SLICED_CAPTION_625_F2,
|
|
VBI_SLICED_TELETEXT_A,
|
|
VBI_SLICED_TELETEXT_BD_525,
|
|
VBI_SLICED_TELETEXT_B_525,
|
|
VBI_SLICED_TELETEXT_B_625 | VBI_SLICED_VPS,
|
|
VBI_SLICED_TELETEXT_B_625,
|
|
VBI_SLICED_TELETEXT_B_L10_625,
|
|
VBI_SLICED_TELETEXT_B_L25_625,
|
|
VBI_SLICED_TELETEXT_C_525,
|
|
VBI_SLICED_TELETEXT_D_525,
|
|
VBI_SLICED_VBI_525,
|
|
VBI_SLICED_VBI_625,
|
|
VBI_SLICED_VPS | VBI_SLICED_CAPTION_625,
|
|
VBI_SLICED_VPS | VBI_SLICED_VPS_F2,
|
|
VBI_SLICED_VPS,
|
|
VBI_SLICED_VPS_F2,
|
|
VBI_SLICED_WSS_625,
|
|
VBI_SLICED_WSS_CPR1204,
|
|
};
|
|
|
|
/* These line numbers are bad because they cannot be encoded in a
|
|
ETS 300 472 / EN 301 775 compliant stream. */
|
|
static const unsigned int
|
|
bad_line_numbers [] = {
|
|
32,
|
|
262,
|
|
263 + 32,
|
|
312,
|
|
313 + 32,
|
|
524,
|
|
525,
|
|
526,
|
|
624,
|
|
625,
|
|
626,
|
|
INT_MAX,
|
|
((unsigned int) INT_MAX) + 1,
|
|
UINT_MAX
|
|
};
|
|
|
|
static const unsigned int
|
|
raw_offsets [] = {
|
|
0,
|
|
1,
|
|
39,
|
|
40,
|
|
41,
|
|
250,
|
|
251,
|
|
252,
|
|
719,
|
|
720,
|
|
721,
|
|
INT_MAX,
|
|
((unsigned int) INT_MAX) + 1,
|
|
UINT_MAX
|
|
};
|
|
|
|
static const unsigned int
|
|
border_uints [] = {
|
|
INT_MAX,
|
|
((unsigned int) INT_MAX) + 1,
|
|
UINT_MAX
|
|
};
|
|
|
|
static vbi_sliced *
|
|
alloc_sliced (unsigned int n_lines)
|
|
{
|
|
vbi_sliced *sliced;
|
|
|
|
sliced = (vbi_sliced *) xmalloc (n_lines * sizeof (vbi_sliced));
|
|
|
|
/* Must initialize the .data[] arrays for valgrind. We fill
|
|
with 0xFF because zeros have special meaning. */
|
|
memset (sliced, -1, n_lines * sizeof (vbi_sliced));
|
|
|
|
return sliced;
|
|
}
|
|
|
|
static uint8_t *
|
|
alloc_raw_frame (const vbi_sampling_par *sp)
|
|
{
|
|
unsigned int n_lines;
|
|
unsigned int size;
|
|
|
|
n_lines = sp->count[0] + sp->count[1];
|
|
assert (n_lines > 0);
|
|
|
|
size = (n_lines - 1) * sp->bytes_per_line;
|
|
size += sp->sp_samples_per_line;
|
|
|
|
assert (size < (10 << 20));
|
|
|
|
return (uint8_t *) xralloc (size);
|
|
}
|
|
|
|
static void
|
|
assert_stuffing_ok (unsigned int * n_sliced_dus,
|
|
unsigned int * n_raw_dus,
|
|
unsigned int * n_stuffing_dus,
|
|
const uint8_t * p,
|
|
unsigned int n_bytes,
|
|
vbi_bool fixed_length)
|
|
{
|
|
/* Verify the value of reserved bits and stuffing bytes
|
|
which are ignored by the vbi_dvb_demux. */
|
|
|
|
*n_sliced_dus = 0;
|
|
*n_raw_dus = 0;
|
|
*n_stuffing_dus = 0;
|
|
|
|
while (n_bytes >= 2) {
|
|
unsigned int data_unit_id;
|
|
unsigned int data_unit_length;
|
|
unsigned int n_pixels;
|
|
unsigned int min_bits;
|
|
unsigned int i;
|
|
|
|
data_unit_id = p[0];
|
|
data_unit_length = p[1];
|
|
|
|
// EN 301 775 section 4.4.2.
|
|
if (fixed_length)
|
|
assert (0x2C == data_unit_length);
|
|
|
|
// EN 301 775 table 3.
|
|
switch (data_unit_id) {
|
|
case 0x02: // "EBU Teletext non-subtitle data"
|
|
// EN 301 775 table 4.
|
|
min_bits = 2 + 1 + 5 + 8 + 336;
|
|
assert (0xC0 == (p[2] & 0xC0));
|
|
++*n_sliced_dus;
|
|
break;
|
|
|
|
case 0x03: // "EBU Teletext subtitle data"
|
|
// Not supported by libzvbi.
|
|
assert (0);
|
|
|
|
case 0xB4: /* DATA_UNIT_ZVBI_WSS_CPR1204 */
|
|
// Should not appear here.
|
|
assert (0);
|
|
|
|
case 0xB5: /* DATA_UNIT_ZVBI_CLOSED_CAPTION_525 */
|
|
// Should not appear here.
|
|
assert (0);
|
|
|
|
case 0xB6: /* DATA_UNIT_ZVBI_MONOCHROME_SAMPLES_525 */
|
|
// Should not appear here.
|
|
assert (0);
|
|
|
|
case 0xC0: // "Inverted Teletext"
|
|
case 0xC1: // "Reserved"? Teletext? (EN 301 775 table 1)
|
|
// Not supported by libzvbi.
|
|
assert (0);
|
|
|
|
case 0xC3: // "VPS"
|
|
// EN 301 775 table 6.
|
|
min_bits = 2 + 1 + 5 + 104;
|
|
assert (0xC0 == (p[2] & 0xC0));
|
|
++*n_sliced_dus;
|
|
break;
|
|
|
|
case 0xC4: // "WSS"
|
|
// EN 301 775 table 8.
|
|
min_bits = 2 + 1 + 5 + 14 + 2;
|
|
assert (0xC0 == (p[2] & 0xC0));
|
|
assert (0x03 == (p[4] & 0x03));
|
|
++*n_sliced_dus;
|
|
break;
|
|
|
|
case 0xC5: // "Closed Captioning"
|
|
// EN 301 775 table 10.
|
|
min_bits = 2 + 1 + 5 + 16;
|
|
assert (0xC0 == (p[2] & 0xC0));
|
|
++*n_sliced_dus;
|
|
break;
|
|
|
|
case 0xC6: // "monochrome 4:2:2 samples"
|
|
n_pixels = p[5];
|
|
min_bits = 1 + 1 + 1 + 5 + 16 + 8 + 8 * n_pixels;
|
|
++*n_raw_dus;
|
|
break;
|
|
|
|
case 0xFF: // "stuffing"
|
|
// EN 301 775 table 1.
|
|
min_bits = 0;
|
|
++*n_stuffing_dus;
|
|
break;
|
|
|
|
default:
|
|
assert (0);
|
|
}
|
|
|
|
/* Our mux should not generate stuffing data units
|
|
between other data units. */
|
|
if (0xFF != data_unit_id)
|
|
assert (0 == *n_stuffing_dus);
|
|
|
|
assert (data_unit_length >= min_bits / 8);
|
|
|
|
assert (n_bytes >= 2 + data_unit_length);
|
|
|
|
// EN 301 775 table 1: N * stuffing_byte [8].
|
|
for (i = min_bits / 8; i < data_unit_length; ++i)
|
|
assert (0xFF == p[2 + i]);
|
|
|
|
p += 2 + data_unit_length;
|
|
n_bytes -= 2 + data_unit_length;
|
|
}
|
|
|
|
assert (0 == n_bytes);
|
|
}
|
|
|
|
static void
|
|
assert_raw_data_units_ok (unsigned int * n_raw_dus,
|
|
unsigned int * n_stuffing_dus,
|
|
const uint8_t * p,
|
|
unsigned int n_bytes,
|
|
vbi_bool fixed_length,
|
|
const uint8_t * raw,
|
|
unsigned int raw_offset,
|
|
vbi_videostd_set videostd_set,
|
|
unsigned int frame_line,
|
|
unsigned int first_pixel_position_0,
|
|
unsigned int n_pixels_total)
|
|
{
|
|
unsigned int f2_start;
|
|
unsigned int next_first_pixel_position;
|
|
|
|
*n_raw_dus = 0;
|
|
*n_stuffing_dus = 0;
|
|
|
|
if (0 != (videostd_set & VBI_VIDEOSTD_SET_525_60)) {
|
|
assert (0 == (videostd_set & VBI_VIDEOSTD_SET_625_50));
|
|
f2_start = 263;
|
|
} else if (0 != (videostd_set & VBI_VIDEOSTD_SET_625_50)) {
|
|
f2_start = 313;
|
|
} else {
|
|
assert (0);
|
|
}
|
|
|
|
next_first_pixel_position = first_pixel_position_0 + raw_offset;
|
|
|
|
while (n_bytes >= 2) {
|
|
unsigned int data_unit_id;
|
|
unsigned int data_unit_length;
|
|
unsigned int min_bits;
|
|
unsigned int first_segment_flag;
|
|
unsigned int last_segment_flag;
|
|
unsigned int field_parity;
|
|
unsigned int line_offset;
|
|
unsigned int first_pixel_position;
|
|
unsigned int n_pixels;
|
|
unsigned int i;
|
|
|
|
data_unit_id = p[0];
|
|
data_unit_length = p[1];
|
|
|
|
// EN 301 775 section 4.4.2.
|
|
if (fixed_length)
|
|
assert (0x2C == data_unit_length);
|
|
|
|
// EN 301 775 table 3.
|
|
switch (data_unit_id) {
|
|
case 0x02: // "EBU Teletext non-subtitle data"
|
|
case 0x03: // "EBU Teletext subtitle data"
|
|
case 0xC0: // "Inverted Teletext"
|
|
case 0xC1: // "Reserved"? Teletext? (EN 301 775 table 1)
|
|
case 0xC3: // "VPS"
|
|
case 0xC4: // "WSS"
|
|
case 0xC5: // "Closed Captioning"
|
|
// Should not appear here.
|
|
assert (0);
|
|
|
|
case 0xC6: // "monochrome 4:2:2 samples"
|
|
// EN 301 775 table 12.
|
|
first_segment_flag = !!(p[2] & 0x80);
|
|
last_segment_flag = !!(p[2] & 0x40);
|
|
field_parity = !!(p[2] & 0x20);
|
|
line_offset = p[2] & 0x1F;
|
|
first_pixel_position = p[3] * 256 + p[4];
|
|
n_pixels = p[5];
|
|
|
|
// EN 301 775 section 4.9.2
|
|
assert ((first_pixel_position
|
|
== first_pixel_position_0)
|
|
== first_segment_flag);
|
|
|
|
// EN 301 775 section 4.9.2
|
|
assert ((first_pixel_position + n_pixels
|
|
== (first_pixel_position_0
|
|
+ n_pixels_total))
|
|
== last_segment_flag);
|
|
|
|
assert (field_parity == (frame_line < f2_start));
|
|
if (0 == field_parity)
|
|
assert (line_offset == frame_line - f2_start);
|
|
else
|
|
assert (line_offset == frame_line);
|
|
|
|
// EN 301 775 table 12, section 4.9.2.
|
|
assert (first_pixel_position <= 719);
|
|
|
|
/* EN 301 775 section 4.9.2: "If this segment
|
|
is followed by another (i.e. last_segment_flag
|
|
equals '0'), the value of first_pixel_position
|
|
of the next segment shall equal the sum of the
|
|
current values of first_pixel_position and
|
|
n_pixels." */
|
|
assert (first_pixel_position
|
|
== next_first_pixel_position);
|
|
|
|
next_first_pixel_position =
|
|
first_pixel_position + n_pixels;
|
|
|
|
// EN 301 775 table 12, section 4.9.2.
|
|
assert (n_pixels >= 1);
|
|
assert (n_pixels <= 251);
|
|
|
|
assert (0 == memcmp (raw, p + 6, n_pixels));
|
|
raw += n_pixels;
|
|
|
|
// EN 301 775 table 12.
|
|
min_bits = 1 + 1 + 1 + 5 + 16 + 8 + n_pixels * 8;
|
|
|
|
++*n_raw_dus;
|
|
|
|
break;
|
|
|
|
case 0xFF: // "stuffing"
|
|
// EN 301 775 table 1.
|
|
min_bits = 0;
|
|
++*n_stuffing_dus;
|
|
break;
|
|
|
|
default:
|
|
assert (0);
|
|
}
|
|
|
|
/* Our mux should not generate stuffing data units
|
|
between other data units. */
|
|
if (0xFF != data_unit_id)
|
|
assert (0 == *n_stuffing_dus);
|
|
|
|
assert (data_unit_length >= min_bits / 8);
|
|
|
|
assert (n_bytes >= 2 + data_unit_length);
|
|
|
|
// EN 301 775 table 1: N * stuffing_byte [8].
|
|
for (i = min_bits / 8; i < data_unit_length; ++i)
|
|
assert (0xFF == p[2 + i]);
|
|
|
|
p += 2 + data_unit_length;
|
|
n_bytes -= 2 + data_unit_length;
|
|
}
|
|
|
|
assert (0 == n_bytes);
|
|
}
|
|
|
|
static void
|
|
assert_pes_packet_ok (unsigned int * n_sliced_dus,
|
|
unsigned int * n_raw_dus,
|
|
unsigned int * n_stuffing_dus,
|
|
const uint8_t * p,
|
|
unsigned int n_bytes,
|
|
unsigned int data_identifier,
|
|
unsigned int min_size,
|
|
unsigned int max_size)
|
|
{
|
|
unsigned int PES_packet_length;
|
|
unsigned int PES_header_data_length;
|
|
vbi_bool fixed_length;
|
|
unsigned int i;
|
|
|
|
// EN 301 775 section 4.4.2.
|
|
fixed_length = (data_identifier >= 0x10
|
|
&& data_identifier <= 0x1F);
|
|
|
|
assert (n_bytes >= 46);
|
|
|
|
/* packet_start_code_prefix [24],
|
|
stream_id [8] */
|
|
assert (0x00 == p[0]);
|
|
assert (0x00 == p[1]);
|
|
assert (0x01 == p[2]);
|
|
assert (0xBD == p[3]);
|
|
|
|
PES_packet_length = p[4] * 256 + p[5];
|
|
|
|
// EN 301 775 section 4.3.
|
|
assert (0 == (PES_packet_length + 6) % 184);
|
|
|
|
assert (PES_packet_length + 6 >= min_size);
|
|
assert (PES_packet_length + 6 <= max_size);
|
|
|
|
/* '10',
|
|
PES_scrambling_control [2],
|
|
PES_priority,
|
|
data_alignment_indicator,
|
|
copyright,
|
|
original_or_copy */
|
|
assert (0x84 == p[6]);
|
|
|
|
/* PTS_DTS_flags [2],
|
|
ESCR_flag,
|
|
ES_rate_flag
|
|
DSM_trick_mode_flag,
|
|
additional_copy_info_flag,
|
|
PES_CRC_flag,
|
|
PES_extension_flag */
|
|
assert (0x80 == p[7]);
|
|
|
|
PES_header_data_length = p[8];
|
|
|
|
// EN 301 775 section 4.3.
|
|
assert (0x24 == PES_header_data_length);
|
|
|
|
/* '0010',
|
|
PTS 32...30 [3]
|
|
marker_bit,
|
|
PTS 29 ... 15 [15],
|
|
marker_bit,
|
|
PTS 14 ... 0 [15]
|
|
marker_bit */
|
|
assert (0x21 == (p[9] & 0xF1));
|
|
assert (0x01 == (p[11] & 0x01));
|
|
assert (0x01 == (p[13] & 0x01));
|
|
|
|
// EN 301 775 section 4.3. (9 + 0x24 == 45)
|
|
for (i = 14; i <= 44; ++i) {
|
|
/* stuffing_byte [8] */
|
|
assert (0xFF == p[i]);
|
|
}
|
|
|
|
assert (data_identifier == p[45]);
|
|
|
|
p += 46;
|
|
n_bytes -= 46;
|
|
|
|
assert (PES_packet_length - 40 == n_bytes);
|
|
|
|
assert_stuffing_ok (n_sliced_dus,
|
|
n_raw_dus,
|
|
n_stuffing_dus,
|
|
p,
|
|
n_bytes,
|
|
fixed_length);
|
|
}
|
|
|
|
static void
|
|
assert_same_sliced (const vbi_sliced * sliced_in,
|
|
unsigned int n_lines_in,
|
|
const vbi_sliced * sliced_out,
|
|
unsigned int n_lines_out,
|
|
vbi_service_set service_mask)
|
|
{
|
|
unsigned int i_in;
|
|
unsigned int i_out;
|
|
|
|
i_out = 0;
|
|
|
|
for (i_in = 0; i_in < n_lines_in; ++i_in) {
|
|
vbi_service_set id_in;
|
|
vbi_service_set id_out;
|
|
unsigned int payload_bits;
|
|
|
|
id_in = sliced_in[i_in].id;
|
|
id_out = sliced_out[i_out].id;
|
|
|
|
switch (id_in & service_mask) {
|
|
case VBI_SLICED_CAPTION_625_F1:
|
|
case VBI_SLICED_CAPTION_625:
|
|
assert (VBI_SLICED_CAPTION_625_F1 == id_out);
|
|
break;
|
|
|
|
case VBI_SLICED_TELETEXT_B_L10_625:
|
|
case VBI_SLICED_TELETEXT_B_L25_625:
|
|
case VBI_SLICED_TELETEXT_B_625:
|
|
assert (VBI_SLICED_TELETEXT_B_625 == id_out);
|
|
break;
|
|
|
|
case VBI_SLICED_VPS:
|
|
case VBI_SLICED_WSS_625:
|
|
assert (id_in == id_out);
|
|
break;
|
|
|
|
default:
|
|
// Was not encoded.
|
|
continue;
|
|
}
|
|
|
|
assert (i_out < n_lines_out);
|
|
|
|
assert (sliced_in[i_in].line == sliced_out[i_out].line);
|
|
|
|
payload_bits = vbi_sliced_payload_bits (id_in);
|
|
|
|
assert (payload_bits > 0);
|
|
assert ( ((payload_bits + 7) >> 3)
|
|
<= sizeof (sliced_in[0].data));
|
|
|
|
assert (0 == memcmp (sliced_in[i_in].data,
|
|
sliced_out[i_out].data,
|
|
payload_bits >> 3));
|
|
|
|
if ((payload_bits & 7) > 0) {
|
|
unsigned int last_in;
|
|
unsigned int last_out;
|
|
unsigned int mask;
|
|
|
|
last_in = sliced_in[i_in].data[payload_bits >> 3];
|
|
last_out = sliced_out[i_out].data[payload_bits >> 3];
|
|
mask = (1 << (payload_bits & 7)) - 1;
|
|
|
|
assert (0 == ((last_in ^ last_out) & mask));
|
|
}
|
|
|
|
++i_out;
|
|
}
|
|
|
|
assert (i_out == n_lines_out);
|
|
}
|
|
|
|
static void
|
|
assert_du_conversion_ok (const uint8_t * packet,
|
|
unsigned int packet_size,
|
|
const vbi_sliced * sliced_in,
|
|
unsigned int n_lines_in,
|
|
vbi_service_set service_mask)
|
|
{
|
|
vbi_sliced *sliced_out;
|
|
const uint8_t *p;
|
|
unsigned int p_left;
|
|
unsigned int n_lines_out;
|
|
unsigned int max_lines_out;
|
|
vbi_bool success;
|
|
|
|
max_lines_out = n_lines_in * 2 + 1;
|
|
sliced_out = alloc_sliced (max_lines_out);
|
|
memset_rand (sliced_out, sizeof (sliced_out));
|
|
|
|
p = packet;
|
|
p_left = packet_size;
|
|
|
|
success = _vbi_dvb_demultiplex_sliced (sliced_out,
|
|
&n_lines_out,
|
|
max_lines_out,
|
|
&p,
|
|
&p_left);
|
|
assert (TRUE == success);
|
|
assert (n_lines_out < max_lines_out);
|
|
|
|
assert (n_lines_out <= n_lines_in);
|
|
assert (0 == p_left);
|
|
|
|
assert_same_sliced (sliced_in,
|
|
n_lines_in,
|
|
sliced_out,
|
|
n_lines_out,
|
|
service_mask);
|
|
|
|
free (sliced_out);
|
|
sliced_out = (vbi_sliced *) -1;
|
|
}
|
|
|
|
static void
|
|
assert_pes_conversion_ok (const uint8_t * packet,
|
|
unsigned int packet_size,
|
|
const vbi_sliced * sliced_in,
|
|
unsigned int n_lines_in,
|
|
vbi_service_set service_mask,
|
|
int64_t pts_in)
|
|
{
|
|
vbi_dvb_demux *dx;
|
|
const uint8_t *p;
|
|
vbi_sliced *sliced_out;
|
|
unsigned int p_left;
|
|
unsigned int n_lines_out;
|
|
unsigned int max_lines_out;
|
|
int64_t pts_valid_bits;
|
|
int64_t pts_out;
|
|
|
|
max_lines_out = n_lines_in * 2 + 1;
|
|
sliced_out = alloc_sliced (max_lines_out);
|
|
memset_rand (sliced_out, sizeof (sliced_out));
|
|
|
|
pts_out = rand();
|
|
|
|
dx = vbi_dvb_pes_demux_new (/* callback */ NULL,
|
|
/* user_data */ NULL);
|
|
assert (NULL != dx);
|
|
|
|
p = packet;
|
|
p_left = packet_size;
|
|
|
|
n_lines_out = vbi_dvb_demux_cor (dx,
|
|
sliced_out,
|
|
max_lines_out,
|
|
&pts_out,
|
|
&p,
|
|
&p_left);
|
|
assert (0 == n_lines_out);
|
|
assert (0 == p_left);
|
|
|
|
p = packet;
|
|
p_left = packet_size;
|
|
|
|
n_lines_out = vbi_dvb_demux_cor (dx,
|
|
sliced_out,
|
|
max_lines_out,
|
|
&pts_out,
|
|
&p,
|
|
&p_left);
|
|
// Frame complete?
|
|
/* FIXME: Frame end may be unclear, e.g. only data
|
|
units with line_offset = 0 in the packet. */
|
|
if (0 == p_left) {
|
|
vbi_dvb_demux_delete (dx);
|
|
free (sliced_out);
|
|
return;
|
|
}
|
|
|
|
assert (n_lines_out < max_lines_out);
|
|
assert (n_lines_out <= n_lines_in);
|
|
|
|
vbi_dvb_demux_delete (dx);
|
|
dx = (vbi_dvb_demux *) -1;
|
|
|
|
assert_same_sliced (sliced_in,
|
|
n_lines_in,
|
|
sliced_out,
|
|
n_lines_out,
|
|
service_mask);
|
|
|
|
// FIXME: Compare raw data frame.
|
|
|
|
// ISO 13818-1 section 2.4.3.7.
|
|
pts_valid_bits = ((int64_t) 1 << 33) - 1;
|
|
|
|
assert (0 == ((pts_in ^ pts_out) & pts_valid_bits));
|
|
assert (0 == (pts_out & ~pts_valid_bits));
|
|
|
|
free (sliced_out);
|
|
}
|
|
|
|
/*
|
|
Test vbi_dvb_multiplex_sliced().
|
|
*/
|
|
|
|
static void
|
|
assert_multiplex_sliced (uint8_t * const p1,
|
|
const unsigned int p1_size,
|
|
const vbi_sliced * const s1,
|
|
const unsigned int s1_lines,
|
|
const vbi_service_set service_mask,
|
|
unsigned int data_identifier,
|
|
vbi_bool stuffing,
|
|
vbi_bool exp_success,
|
|
int exp_errno,
|
|
unsigned int exp_out_lines,
|
|
unsigned int exp_out_data_size,
|
|
unsigned int exp_consumed_lines)
|
|
{
|
|
uint8_t *p;
|
|
uint8_t *rand_buffer;
|
|
const vbi_sliced *s;
|
|
unsigned int p_left;
|
|
unsigned int s_left;
|
|
unsigned int fixed_length;
|
|
unsigned int n_sliced_dus;
|
|
unsigned int n_raw_dus;
|
|
unsigned int n_stuffing_dus;
|
|
vbi_bool success;
|
|
|
|
if (ANY_STUFFING == stuffing) {
|
|
assert_multiplex_sliced (p1, p1_size,
|
|
s1, s1_lines,
|
|
service_mask,
|
|
data_identifier,
|
|
/* stuffing */ FALSE,
|
|
exp_success,
|
|
exp_errno,
|
|
exp_out_lines,
|
|
exp_out_data_size,
|
|
exp_consumed_lines);
|
|
stuffing = TRUE;
|
|
|
|
if (exp_success)
|
|
exp_out_data_size = p1_size;
|
|
}
|
|
|
|
if (ANY_DATA_IDENTIFIER == data_identifier) {
|
|
assert_multiplex_sliced (p1, p1_size,
|
|
s1, s1_lines,
|
|
service_mask,
|
|
/* data_identifier */ 0x99,
|
|
stuffing,
|
|
exp_success,
|
|
exp_errno,
|
|
exp_out_lines,
|
|
exp_out_data_size,
|
|
exp_consumed_lines);
|
|
data_identifier = 0x10;
|
|
|
|
if (exp_success) {
|
|
if (0 == p1_size % 46) {
|
|
if (stuffing)
|
|
exp_out_data_size = p1_size;
|
|
else
|
|
exp_out_data_size = exp_out_lines * 46;
|
|
} else {
|
|
exp_success = FALSE;
|
|
exp_errno = VBI_ERR_BUFFER_OVERFLOW;
|
|
exp_out_lines = 0;
|
|
exp_out_data_size = 0;
|
|
exp_consumed_lines = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NULL != p1 && p1_size > 0) {
|
|
rand_buffer = (uint8_t *) xralloc (p1_size);
|
|
memcpy (p1, rand_buffer, p1_size);
|
|
} else {
|
|
rand_buffer = NULL;
|
|
}
|
|
|
|
p = p1;
|
|
p_left = p1_size;
|
|
|
|
s = s1;
|
|
s_left = s1_lines;
|
|
|
|
success = vbi_dvb_multiplex_sliced (&p, &p_left,
|
|
&s, &s_left,
|
|
service_mask,
|
|
data_identifier,
|
|
stuffing);
|
|
assert (exp_success == success);
|
|
|
|
if (!success) {
|
|
exp_errno = exp_errno;
|
|
// XXX later: assert (exp_errno == errno);
|
|
}
|
|
|
|
assert (p1 + exp_out_data_size == p);
|
|
assert (p1_size - exp_out_data_size == p_left);
|
|
|
|
assert (s1 + exp_consumed_lines == s);
|
|
assert (s1_lines - exp_consumed_lines == s_left);
|
|
|
|
if (NULL == p1)
|
|
goto finish;
|
|
|
|
assert (0 == memcmp (p, rand_buffer + exp_out_data_size,
|
|
p1_size - exp_out_data_size));
|
|
|
|
// EN 301 775 section 4.4.2.
|
|
fixed_length = (data_identifier >= 0x10
|
|
&& data_identifier <= 0x1F);
|
|
|
|
assert_stuffing_ok (&n_sliced_dus,
|
|
&n_raw_dus,
|
|
&n_stuffing_dus,
|
|
p1,
|
|
exp_out_data_size,
|
|
fixed_length);
|
|
|
|
if (success && stuffing) {
|
|
assert (exp_out_lines == n_sliced_dus);
|
|
assert (0 == n_raw_dus);
|
|
|
|
assert_du_conversion_ok (p1,
|
|
p1_size,
|
|
s1,
|
|
s1_lines - s_left,
|
|
service_mask);
|
|
} else {
|
|
assert (exp_out_lines == n_sliced_dus);
|
|
assert (0 == n_raw_dus);
|
|
assert (0 == n_stuffing_dus);
|
|
|
|
if (exp_out_data_size > 0) {
|
|
assert_du_conversion_ok (p1,
|
|
exp_out_data_size,
|
|
s1,
|
|
s1_lines - s_left,
|
|
service_mask);
|
|
}
|
|
}
|
|
|
|
finish:
|
|
free (rand_buffer);
|
|
}
|
|
|
|
static void
|
|
test_ms_stuffing (unsigned int buffer_size,
|
|
vbi_sliced * sliced,
|
|
unsigned int n_lines,
|
|
unsigned int data_identifier,
|
|
unsigned int exp_out_lines)
|
|
{
|
|
uint8_t *buffer;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size);
|
|
|
|
assert_multiplex_sliced (buffer,
|
|
buffer_size,
|
|
sliced,
|
|
n_lines,
|
|
ALL_SERVICES,
|
|
data_identifier,
|
|
STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
exp_out_lines,
|
|
/* exp_out_data_size */ buffer_size,
|
|
/* exp_consumed_lines */ exp_out_lines);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_stuffing (void)
|
|
{
|
|
vbi_sliced *sliced;
|
|
unsigned int n_lines;
|
|
unsigned int buffer_size;
|
|
|
|
sliced = alloc_sliced (n_lines = 1);
|
|
|
|
sliced[0].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[0].line = 7;
|
|
|
|
for (buffer_size = 2; buffer_size < 46; ++buffer_size) {
|
|
test_ms_stuffing (buffer_size,
|
|
sliced, n_lines,
|
|
/* data_identifier */ 0x99,
|
|
/* exp_out_lines */ 0);
|
|
}
|
|
|
|
for (buffer_size = 46; buffer_size < 300; ++buffer_size) {
|
|
test_ms_stuffing (buffer_size,
|
|
sliced, n_lines,
|
|
/* data_identifier */ 0x99,
|
|
/* exp_out_lines */ 1);
|
|
}
|
|
|
|
for (buffer_size = 1 * 46;
|
|
buffer_size <= 10 * 46; buffer_size += 46) {
|
|
test_ms_stuffing (buffer_size,
|
|
sliced, n_lines,
|
|
/* data_identifier */ 0x10,
|
|
/* exp_out_lines */ 1);
|
|
}
|
|
|
|
free (sliced);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_null_sliced (void)
|
|
{
|
|
unsigned int buffer_size;
|
|
|
|
for (buffer_size = 2; buffer_size < 300; ++buffer_size) {
|
|
test_ms_stuffing (buffer_size,
|
|
/* sliced */ NULL,
|
|
/* sliced_lines */ 1,
|
|
/* data_identifier */ 0x99,
|
|
/* exp_out_lines */ 0);
|
|
|
|
test_ms_stuffing (buffer_size,
|
|
/* sliced */ (vbi_sliced *) -1,
|
|
/* sliced_lines */ 0,
|
|
/* data_identifier */ 0x99,
|
|
/* exp_out_lines */ 0);
|
|
}
|
|
|
|
for (buffer_size = 1 * 46;
|
|
buffer_size <= 10 * 46; buffer_size += 46) {
|
|
test_ms_stuffing (buffer_size,
|
|
/* sliced */ NULL,
|
|
/* sliced_lines */ 1,
|
|
/* data_identifier */ 0x10,
|
|
/* exp_out_lines */ 0);
|
|
|
|
test_ms_stuffing (buffer_size,
|
|
/* sliced */ (vbi_sliced *) -1,
|
|
/* sliced_lines */ 0,
|
|
/* data_identifier */ 0x10,
|
|
/* exp_out_lines */ 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_ms_line (vbi_service_set service,
|
|
unsigned int line,
|
|
vbi_bool correct)
|
|
{
|
|
vbi_sliced *sliced;
|
|
uint8_t *buffer;
|
|
unsigned int buffer_size;
|
|
unsigned int n_lines;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
sliced = alloc_sliced (n_lines = 1);
|
|
|
|
sliced[0].id = service;
|
|
sliced[0].line = line;
|
|
|
|
if (0 == service) {
|
|
assert (correct);
|
|
|
|
/* Will be discarded without further checks. */
|
|
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
/* exp_out_lines */ 0,
|
|
/* exp_out_data_size */ 0,
|
|
/* exp_consumed_lines */ 1);
|
|
} else if (correct) {
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
/* data_identifier */ 0x10,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
/* exp_out_lines */ 1,
|
|
/* exp_out_data_size */ 1 * 46,
|
|
/* exp_consumed_lines */ 1);
|
|
} else {
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_LINE_NUMBER,
|
|
/* exp_out_lines */ 0,
|
|
/* exp_out_data_size */ 0,
|
|
/* exp_consumed_lines */ 0);
|
|
}
|
|
|
|
free (sliced);
|
|
free (buffer);
|
|
}
|
|
|
|
static vbi_bool
|
|
is_correct_line (vbi_service_set service,
|
|
unsigned int field,
|
|
unsigned int line_offset)
|
|
{
|
|
switch (service) {
|
|
case 0:
|
|
return TRUE;
|
|
|
|
case VBI_SLICED_TELETEXT_B_625:
|
|
case VBI_SLICED_TELETEXT_B_L10_625:
|
|
case VBI_SLICED_TELETEXT_B_L25_625:
|
|
// EN 301 775 section 4.5.2.
|
|
/* Note an undefined line (0) in the second field
|
|
is permitted, but libzvbi cannot express such
|
|
line numbers. */
|
|
if (0 == field && 0 == line_offset)
|
|
return TRUE;
|
|
return (line_offset >= 7 && line_offset <= 22);
|
|
|
|
case VBI_SLICED_VPS:
|
|
// EN 301 775 section 4.6.2.
|
|
if (0 == field)
|
|
return (16 == line_offset);
|
|
return FALSE;
|
|
|
|
case VBI_SLICED_WSS_625:
|
|
// EN 301 775 section 4.7.2.
|
|
if (0 == field)
|
|
return (23 == line_offset);
|
|
return FALSE;
|
|
|
|
case VBI_SLICED_CAPTION_625:
|
|
case VBI_SLICED_CAPTION_625_F1:
|
|
// EN 301 775 section 4.8.2.
|
|
if (0 == field)
|
|
return (21 == line_offset);
|
|
return FALSE;
|
|
|
|
case VBI_SLICED_VBI_625:
|
|
// EN 301 775 section 4.9.2.
|
|
return (line_offset >= 7 && line_offset <= 23);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
assert (0);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_line_number_checks (void)
|
|
{
|
|
vbi_sliced *sliced;
|
|
uint8_t *buffer;
|
|
vbi_service_set service;
|
|
unsigned int buffer_size;
|
|
unsigned int n_lines;
|
|
unsigned int i;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
sliced = alloc_sliced (n_lines = 1);
|
|
|
|
sliced[0].id = 0;
|
|
sliced[0].line = 100;
|
|
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
/* exp_out_lines */ 0,
|
|
/* exp_out_data_size */ 0,
|
|
/* exp_consumed_lines */ 1);
|
|
|
|
free (sliced);
|
|
sliced = (vbi_sliced *) -1;
|
|
|
|
free (buffer);
|
|
buffer = (uint8_t *) -1;
|
|
|
|
for (i = 0; i <= 31; ++i) {
|
|
unsigned int j;
|
|
|
|
for (j = 0; j < N_ELEMENTS (good_services); ++j) {
|
|
service = good_services[j];
|
|
|
|
test_ms_line (service, /* line */ i,
|
|
is_correct_line (service, 0, i));
|
|
|
|
test_ms_line (service, /* line */ i + 313,
|
|
is_correct_line (service, 1, i));
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < N_ELEMENTS (bad_line_numbers); ++i) {
|
|
unsigned int j;
|
|
|
|
for (j = 0; j < N_ELEMENTS (good_services); ++j) {
|
|
service = good_services[j];
|
|
|
|
test_ms_line (service,
|
|
/* line */ bad_line_numbers[i],
|
|
/* correct */ 0 == service);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_service_checks
|
|
(vbi_service_set service)
|
|
{
|
|
vbi_sliced *sliced;
|
|
uint8_t *buffer;
|
|
unsigned int buffer_size;
|
|
unsigned int n_lines;
|
|
unsigned int line;
|
|
unsigned int i;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
sliced = alloc_sliced (n_lines = 8);
|
|
|
|
/* Verify the data service checks. */
|
|
|
|
for (i = 0; i < 6; ++i) {
|
|
sliced[i].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[i].line = i + 7;
|
|
}
|
|
|
|
if (service & VBI_SLICED_VPS)
|
|
line = 16;
|
|
else if (service & VBI_SLICED_CAPTION_625)
|
|
line = 21;
|
|
else if (service & VBI_SLICED_WSS_625)
|
|
line = 23;
|
|
else
|
|
line = 13;
|
|
|
|
sliced[6].id = service;
|
|
sliced[6].line = line;
|
|
|
|
sliced[7].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[7].line = 320;
|
|
|
|
if (is_good_service (service)) {
|
|
unsigned int exp_out_lines;
|
|
|
|
if (VBI_SLICED_NONE == service)
|
|
exp_out_lines = n_lines - 1;
|
|
else
|
|
exp_out_lines = n_lines;
|
|
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
/* data identifier */ 0x10,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
exp_out_lines,
|
|
exp_out_lines * 46,
|
|
/* exp_consumed_lines */ n_lines);
|
|
} else {
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_INVALID_SERVICE,
|
|
/* exp_out_lines */ 6,
|
|
/* exp_out_data_size */ 6 * 46,
|
|
/* exp_consumed_lines */ 6);
|
|
}
|
|
|
|
/* Verify the service filter. */
|
|
|
|
if (-1u == service
|
|
|| (VBI_SLICED_TELETEXT_B_625
|
|
== (VBI_SLICED_TELETEXT_B_625 & service))) {
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
/* service_mask */ ~service,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
/* exp_out_lines */ 0,
|
|
/* exp_out_data_size */ 0,
|
|
/* exp_consumed_lines */ n_lines);
|
|
} else {
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
/* service_mask */ ~service,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
/* exp_out_lines */ n_lines - 1,
|
|
/* exp_out_data_size */
|
|
(n_lines - 1) * 46,
|
|
/* exp_consumed_lines */ n_lines);
|
|
}
|
|
|
|
free (sliced);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_ms_good_line_order (unsigned int nth,
|
|
unsigned int line)
|
|
{
|
|
vbi_sliced *sliced;
|
|
uint8_t *buffer;
|
|
unsigned int buffer_size;
|
|
unsigned int n_lines;
|
|
unsigned int i;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
sliced = alloc_sliced (n_lines = 8);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
sliced[i].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[i].line = i + 7;
|
|
}
|
|
|
|
for (i = 4; i < 8; ++i) {
|
|
sliced[i].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[i].line = i + 7 + 313;
|
|
}
|
|
|
|
assert (nth < n_lines);
|
|
sliced[nth].line = line;
|
|
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
/* exp_out_lines */ n_lines,
|
|
/* exp_out_data_size */ n_lines * 46,
|
|
/* exp_consumed_lines */ n_lines);
|
|
|
|
free (sliced);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_ms_bad_line_order (unsigned int nth,
|
|
unsigned int line,
|
|
unsigned int bad)
|
|
{
|
|
vbi_sliced *sliced;
|
|
uint8_t *buffer;
|
|
unsigned int buffer_size;
|
|
unsigned int n_lines;
|
|
unsigned int i;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
sliced = alloc_sliced (n_lines = 8);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
sliced[i].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[i].line = 7 + i;
|
|
}
|
|
|
|
for (i = 4; i < 8; ++i) {
|
|
sliced[i].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[i].line = 313 + 7 + i - 4;
|
|
}
|
|
|
|
assert (nth < n_lines);
|
|
sliced[nth].line = line;
|
|
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_LINE_ORDER,
|
|
/* exp_out_lines */ bad,
|
|
/* exp_out_data_size */ bad * 46,
|
|
/* exp_consumed_lines */ bad);
|
|
free (sliced);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_line_order_checks (void)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < 8; ++i)
|
|
test_ms_good_line_order (i, 0);
|
|
|
|
test_ms_bad_line_order (0, 19, 1);
|
|
test_ms_bad_line_order (0, 320, 1);
|
|
|
|
for (i = 1; i < 3; ++i) {
|
|
// 7, 8, 9, 10, 320, 321, 322, 323.
|
|
test_ms_bad_line_order (i, 19, i + 1);
|
|
test_ms_bad_line_order (i, 320 + i, i + 1);
|
|
test_ms_bad_line_order (i + 4, 7 + i, i + 4);
|
|
}
|
|
|
|
test_ms_good_line_order (3, 19);
|
|
test_ms_good_line_order (4, 19);
|
|
|
|
// No line twice.
|
|
test_ms_bad_line_order (2, 7, 2);
|
|
test_ms_bad_line_order (2, 8, 2);
|
|
test_ms_bad_line_order (2, 10, 3);
|
|
test_ms_bad_line_order (6, 320, 6);
|
|
test_ms_bad_line_order (6, 321, 6);
|
|
test_ms_bad_line_order (6, 323, 7);
|
|
}
|
|
|
|
static void
|
|
test_ms_packet_offset_size (unsigned int offset,
|
|
unsigned int buffer_size,
|
|
vbi_bool stuffing)
|
|
{
|
|
vbi_sliced *sliced;
|
|
uint8_t *buffer;
|
|
unsigned int n_lines;
|
|
unsigned int max_lines;
|
|
unsigned int exp_out_lines;
|
|
unsigned int exp_out_data_size;
|
|
vbi_bool full;
|
|
unsigned int i;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size + offset);
|
|
sliced = alloc_sliced (max_lines = 24 - 7);
|
|
|
|
n_lines = 0;
|
|
|
|
exp_out_lines = 0;
|
|
exp_out_data_size = 0;
|
|
|
|
full = FALSE;
|
|
|
|
for (i = 7; i < 16; ++i) {
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = i;
|
|
if (exp_out_data_size + 46 > buffer_size) {
|
|
full = TRUE;
|
|
} else {
|
|
exp_out_data_size += 46;
|
|
++exp_out_lines;
|
|
}
|
|
}
|
|
|
|
sliced[n_lines].id = VBI_SLICED_VPS;
|
|
sliced[n_lines++].line = 16;
|
|
if (exp_out_data_size + 16 > buffer_size) {
|
|
full = TRUE;
|
|
} else if (!full) {
|
|
exp_out_data_size += 16;
|
|
++exp_out_lines;
|
|
}
|
|
|
|
for (i = 17; i < 21; ++i) {
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = i;
|
|
if (exp_out_data_size + 46 > buffer_size) {
|
|
full = TRUE;
|
|
} else if (!full) {
|
|
exp_out_data_size += 46;
|
|
++exp_out_lines;
|
|
}
|
|
}
|
|
|
|
sliced[n_lines].id = VBI_SLICED_CAPTION_625;
|
|
sliced[n_lines++].line = 21;
|
|
if (exp_out_data_size + 5 > buffer_size) {
|
|
full = TRUE;
|
|
} else if (!full) {
|
|
exp_out_data_size += 5;
|
|
++exp_out_lines;
|
|
}
|
|
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = 22;
|
|
if (exp_out_data_size + 46 > buffer_size) {
|
|
full = TRUE;
|
|
} else if (!full) {
|
|
exp_out_data_size += 46;
|
|
++exp_out_lines;
|
|
}
|
|
|
|
sliced[n_lines].id = VBI_SLICED_WSS_625;
|
|
sliced[n_lines++].line = 23;
|
|
if (exp_out_data_size + 5 > buffer_size) {
|
|
full = TRUE;
|
|
} else if (!full) {
|
|
exp_out_data_size += 5;
|
|
++exp_out_lines;
|
|
}
|
|
|
|
assert (n_lines == max_lines);
|
|
|
|
if (stuffing)
|
|
exp_out_data_size = buffer_size;
|
|
|
|
assert_multiplex_sliced (buffer + offset, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
stuffing,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
exp_out_lines,
|
|
exp_out_data_size,
|
|
/* exp_consumed_lines */ exp_out_lines);
|
|
|
|
free (sliced);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_packet_size (void)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 2; i < 2048; (i < 300) ? ++i : i += 7) {
|
|
test_ms_packet_offset_size (0, i, STUFFING);
|
|
test_ms_packet_offset_size (0, i, NO_STUFFING);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_data_identifier_checks
|
|
(unsigned int data_identifier)
|
|
{
|
|
vbi_sliced *sliced;
|
|
unsigned int buffer_size;
|
|
unsigned int n_lines;
|
|
vbi_bool fixed_length;
|
|
|
|
sliced = alloc_sliced (n_lines = 1);
|
|
|
|
sliced[0].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[0].line = 7;
|
|
|
|
// EN 301 775 section 4.4.2.
|
|
fixed_length = (data_identifier >= 0x10
|
|
&& data_identifier <= 0x1F);
|
|
|
|
for (buffer_size = 20 * 46 - 1;
|
|
buffer_size <= 20 * 46 + 1; ++buffer_size) {
|
|
uint8_t *buffer;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size);
|
|
|
|
if (!fixed_length || 0 == buffer_size % 46) {
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
data_identifier,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
/* exp_out_lines */
|
|
n_lines,
|
|
/* exp_out_data_size */
|
|
n_lines * 46,
|
|
/* exp_consumed_lines */
|
|
n_lines);
|
|
} else {
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
data_identifier,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_BUFFER_OVERFLOW,
|
|
/* exp_out_lines */ 0,
|
|
/* exp_out_data_size */ 0,
|
|
/* exp_consumed_lines */ 0);
|
|
}
|
|
|
|
free (buffer);
|
|
buffer = (uint8_t *) -1;
|
|
}
|
|
|
|
free (sliced);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_packet_size_checks (void)
|
|
{
|
|
uint8_t *buffer;
|
|
unsigned int buffer_size;
|
|
|
|
assert_multiplex_sliced (/* buffer */ (uint8_t *) -1,
|
|
/* buffer_size */ 0,
|
|
/* sliced */ (vbi_sliced *) -1,
|
|
/* sliced_lines */ 1,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_BUFFER_OVERFLOW,
|
|
/* exp_out_lines */ 0,
|
|
/* exp_out_data_size */ 0,
|
|
/* exp_consumed_lines */ 0);
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 1);
|
|
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
/* sliced */ (vbi_sliced *) -1,
|
|
/* sliced_lines */ 1,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_BUFFER_OVERFLOW,
|
|
/* exp_out_lines */ 0,
|
|
/* exp_out_data_size */ 0,
|
|
/* exp_consumed_lines */ 0);
|
|
free (buffer);
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 2);
|
|
|
|
assert_multiplex_sliced (buffer, buffer_size,
|
|
/* sliced */ (vbi_sliced *) -1,
|
|
/* sliced_lines */ 0,
|
|
ALL_SERVICES,
|
|
/* data_identifier */ 0x99,
|
|
STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0,
|
|
/* exp_out_lines */ 0,
|
|
/* exp_out_data_size */ buffer_size,
|
|
/* exp_consumed_lines */ 0);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_unaligned_packet (void)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 1; i < 16; ++i) {
|
|
test_ms_packet_offset_size (i, 20 * 46, STUFFING);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_multiplex_sliced_null_packet_checks (void)
|
|
{
|
|
vbi_sliced *sliced;
|
|
|
|
sliced = alloc_sliced (1);
|
|
|
|
sliced[0].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[0].line = 7;
|
|
|
|
assert_multiplex_sliced (/* buffer */ NULL,
|
|
/* buffer_size */ 20 * 46,
|
|
sliced,
|
|
/* sliced_lines */ 1,
|
|
ALL_SERVICES,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_BUFFER_OVERFLOW,
|
|
/* exp_out_lines */ 0,
|
|
/* exp_out_data_size */ 0,
|
|
/* exp_consumed_lines */ 0);
|
|
|
|
free (sliced);
|
|
}
|
|
|
|
void
|
|
test_multiplex_sliced (void)
|
|
{
|
|
unsigned int i;
|
|
|
|
test_multiplex_sliced_null_packet_checks ();
|
|
test_multiplex_sliced_packet_size_checks ();
|
|
|
|
for (i = 0; i < N_ELEMENTS (data_identifiers); ++i) {
|
|
unsigned int di = data_identifiers[i];
|
|
test_multiplex_sliced_data_identifier_checks (di);
|
|
}
|
|
|
|
test_multiplex_sliced_line_order_checks ();
|
|
|
|
for (i = 0; i < N_ELEMENTS (all_services); ++i)
|
|
test_multiplex_sliced_service_checks (all_services[i]);
|
|
|
|
test_multiplex_sliced_line_number_checks ();
|
|
|
|
test_multiplex_sliced_packet_size ();
|
|
test_multiplex_sliced_unaligned_packet ();
|
|
test_multiplex_sliced_null_sliced ();
|
|
test_multiplex_sliced_stuffing ();
|
|
}
|
|
|
|
/*
|
|
Test vbi_dvb_multiplex_raw().
|
|
*/
|
|
|
|
static void
|
|
assert_multiplex_raw (uint8_t * const p1,
|
|
const unsigned int p1_size,
|
|
const uint8_t * const r1,
|
|
const unsigned int r1_size,
|
|
unsigned int data_identifier,
|
|
vbi_videostd_set videostd_set,
|
|
const unsigned int line,
|
|
const unsigned int first_pixel_position,
|
|
const unsigned int n_pixels_total,
|
|
vbi_bool stuffing,
|
|
const vbi_bool exp_success,
|
|
const int exp_errno)
|
|
{
|
|
uint8_t *p;
|
|
uint8_t *rand_buffer;
|
|
const uint8_t *r;
|
|
unsigned int p_left;
|
|
unsigned int r_left;
|
|
unsigned int exp_out_dus;
|
|
unsigned int exp_out_data_size;
|
|
unsigned int exp_consumed_samples;
|
|
unsigned int n_raw_dus;
|
|
unsigned int n_stuffing_dus;
|
|
vbi_bool fixed_length;
|
|
vbi_bool success;
|
|
|
|
if (ANY_DATA_IDENTIFIER == data_identifier) {
|
|
assert_multiplex_raw (p1, p1_size,
|
|
r1, r1_size,
|
|
/* data_identifier */ 0x10,
|
|
videostd_set,
|
|
line,
|
|
first_pixel_position,
|
|
n_pixels_total,
|
|
stuffing,
|
|
exp_success,
|
|
exp_errno);
|
|
data_identifier = 0x99;
|
|
}
|
|
|
|
if (ANY_STUFFING == stuffing) {
|
|
assert_multiplex_raw (p1, p1_size,
|
|
r1, r1_size,
|
|
data_identifier,
|
|
videostd_set,
|
|
line,
|
|
first_pixel_position,
|
|
n_pixels_total,
|
|
/* stuffing */ FALSE,
|
|
exp_success,
|
|
exp_errno);
|
|
stuffing = TRUE;
|
|
}
|
|
|
|
if (ANY_VIDEOSTD == videostd_set) {
|
|
assert_multiplex_raw (p1, p1_size,
|
|
r1, r1_size,
|
|
data_identifier,
|
|
VBI_VIDEOSTD_SET_525_60,
|
|
line,
|
|
first_pixel_position,
|
|
n_pixels_total,
|
|
stuffing,
|
|
exp_success,
|
|
exp_errno);
|
|
videostd_set = VBI_VIDEOSTD_SET_625_50;
|
|
}
|
|
|
|
if (NULL != p1 && p1_size > 0) {
|
|
rand_buffer = (uint8_t *) xralloc (p1_size);
|
|
memcpy (p1, rand_buffer, p1_size);
|
|
} else {
|
|
rand_buffer = NULL;
|
|
}
|
|
|
|
p = p1;
|
|
p_left = p1_size;
|
|
|
|
r = r1;
|
|
r_left = r1_size;
|
|
|
|
success = vbi_dvb_multiplex_raw (&p, &p_left,
|
|
&r, &r_left,
|
|
data_identifier,
|
|
videostd_set,
|
|
line,
|
|
first_pixel_position,
|
|
n_pixels_total,
|
|
stuffing);
|
|
assert (exp_success == success);
|
|
|
|
if (!success) {
|
|
(void) exp_errno;
|
|
// XXX later: assert (exp_errno == errno);
|
|
|
|
assert (p1 == p);
|
|
assert (p1_size == p_left);
|
|
|
|
assert (r1 == r);
|
|
assert (r1_size == r_left);
|
|
|
|
if (NULL != p1) {
|
|
assert (0 == memcmp (p1, rand_buffer, p1_size));
|
|
}
|
|
|
|
goto finish;
|
|
}
|
|
|
|
// EN 301 775 section 4.4.2.
|
|
fixed_length = (data_identifier >= 0x10
|
|
&& data_identifier <= 0x1F);
|
|
|
|
if (fixed_length) {
|
|
exp_out_dus = MIN (p1_size / 46, (r1_size + 39) / 40);
|
|
exp_out_data_size = exp_out_dus * 46;
|
|
exp_consumed_samples = MIN (r1_size, exp_out_dus * 40);
|
|
} else {
|
|
exp_out_dus = MIN (p1_size / 257, r1_size / 251);
|
|
exp_out_data_size = exp_out_dus * 257;
|
|
exp_consumed_samples = exp_out_dus * 251;
|
|
|
|
if (stuffing
|
|
&& exp_out_data_size + 1 == p1_size) {
|
|
/* One byte less to make room for a
|
|
stuffing data unit. */
|
|
--exp_consumed_samples;
|
|
} else if (exp_consumed_samples < r1_size
|
|
&& exp_out_data_size + 7 <= p1_size) {
|
|
unsigned int n_samples;
|
|
|
|
n_samples = MIN (r1_size - exp_consumed_samples,
|
|
p1_size - 6 - exp_out_data_size);
|
|
++exp_out_dus;
|
|
exp_out_data_size += 6 + n_samples;
|
|
exp_consumed_samples += n_samples;
|
|
}
|
|
}
|
|
|
|
if (stuffing)
|
|
exp_out_data_size = p1_size;
|
|
|
|
assert (p1 + exp_out_data_size == p);
|
|
assert (p1_size - exp_out_data_size == p_left);
|
|
|
|
assert (r1 + r1_size - r_left == r);
|
|
assert (r1_size - exp_consumed_samples == r_left);
|
|
|
|
assert (0 == memcmp (p, rand_buffer + exp_out_data_size,
|
|
p1_size - exp_out_data_size));
|
|
|
|
assert_raw_data_units_ok (&n_raw_dus,
|
|
&n_stuffing_dus,
|
|
p1,
|
|
exp_out_data_size,
|
|
fixed_length,
|
|
r1,
|
|
/* offset */ n_pixels_total - r1_size,
|
|
videostd_set,
|
|
line,
|
|
first_pixel_position,
|
|
n_pixels_total);
|
|
|
|
assert (exp_out_dus == n_raw_dus);
|
|
|
|
if (!stuffing)
|
|
assert (0 == n_stuffing_dus);
|
|
|
|
finish:
|
|
free (rand_buffer);
|
|
}
|
|
|
|
static void
|
|
test_mr_size_offset (unsigned int raw_left,
|
|
unsigned int first_pixel_position,
|
|
unsigned int n_pixels_total)
|
|
{
|
|
uint8_t *buffer;
|
|
uint8_t *raw;
|
|
unsigned int buffer_size;
|
|
vbi_bool exp_success;
|
|
|
|
raw = (uint8_t *) xralloc (720);
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
|
|
if (0 == raw_left) {
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
raw,
|
|
/* raw_size */ 0,
|
|
ANY_DATA_IDENTIFIER,
|
|
VBI_VIDEOSTD_SET_625_50,
|
|
/* line */ 10,
|
|
first_pixel_position,
|
|
n_pixels_total,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_NO_RAW_DATA);
|
|
goto finish;
|
|
}
|
|
|
|
if (0 == n_pixels_total)
|
|
exp_success = FALSE;
|
|
else if ((uint64_t) first_pixel_position + n_pixels_total
|
|
> (uint64_t) 720)
|
|
exp_success = FALSE;
|
|
else if (raw_left > n_pixels_total)
|
|
exp_success = FALSE;
|
|
else
|
|
exp_success = TRUE;
|
|
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
raw, raw_left,
|
|
ANY_DATA_IDENTIFIER,
|
|
VBI_VIDEOSTD_SET_625_50,
|
|
/* line */ 10,
|
|
first_pixel_position,
|
|
n_pixels_total,
|
|
ANY_STUFFING,
|
|
exp_success,
|
|
VBI_ERR_SAMPLE_NUMBER);
|
|
|
|
free (buffer);
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 2 * 46);
|
|
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
raw, raw_left,
|
|
ANY_DATA_IDENTIFIER,
|
|
VBI_VIDEOSTD_SET_625_50,
|
|
/* line */ 10,
|
|
first_pixel_position,
|
|
n_pixels_total,
|
|
ANY_STUFFING,
|
|
exp_success,
|
|
VBI_ERR_SAMPLE_NUMBER);
|
|
finish:
|
|
free (buffer);
|
|
free (raw);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw_size_offsets (void)
|
|
{
|
|
unsigned int i, j, k;
|
|
|
|
for (i = 0; i < N_ELEMENTS (raw_offsets); ++i) {
|
|
for (j = 0; j < N_ELEMENTS (raw_offsets); ++j) {
|
|
for (k = 0; k < N_ELEMENTS (raw_offsets); ++k) {
|
|
test_mr_size_offset (raw_offsets[i],
|
|
raw_offsets[j],
|
|
raw_offsets[k]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_mr_line (unsigned int line,
|
|
vbi_bool exp_success_525,
|
|
vbi_bool exp_success_625)
|
|
{
|
|
uint8_t *buffer;
|
|
uint8_t *raw;
|
|
unsigned int buffer_size;
|
|
unsigned int raw_size;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
raw = (uint8_t *) xralloc (raw_size = 720);
|
|
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
raw, raw_size,
|
|
ANY_DATA_IDENTIFIER,
|
|
VBI_VIDEOSTD_SET_525_60,
|
|
line,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ raw_size,
|
|
ANY_STUFFING,
|
|
exp_success_525,
|
|
VBI_ERR_LINE_NUMBER);
|
|
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
raw, raw_size,
|
|
ANY_DATA_IDENTIFIER,
|
|
VBI_VIDEOSTD_SET_625_50,
|
|
line,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ raw_size,
|
|
ANY_STUFFING,
|
|
exp_success_625,
|
|
VBI_ERR_LINE_NUMBER);
|
|
free (raw);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw_line_number_checks (void)
|
|
{
|
|
unsigned int line;
|
|
unsigned int i;
|
|
|
|
for (line = 0; line < 650; ++line) {
|
|
vbi_bool exp_success_525;
|
|
vbi_bool exp_success_625;
|
|
|
|
exp_success_525 = FALSE;
|
|
exp_success_625 = FALSE;
|
|
|
|
// EN 301 775 table 13.
|
|
if (line >= 7 && line <= 23) {
|
|
exp_success_525 = TRUE;
|
|
exp_success_625 = TRUE;
|
|
} else if (line >= 263 + 7 && line <= 263 + 23) {
|
|
exp_success_525 = TRUE;
|
|
} else if (line >= 313 + 7 && line <= 313 + 23) {
|
|
exp_success_625 = TRUE;
|
|
}
|
|
|
|
test_mr_line (line, exp_success_525, exp_success_625);
|
|
}
|
|
|
|
for (i = 0; i < N_ELEMENTS (border_uints); ++i)
|
|
test_mr_line (border_uints[i], FALSE, FALSE);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw_videostd_checks (void)
|
|
{
|
|
uint8_t *buffer;
|
|
unsigned int buffer_size;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
/* raw */ (uint8_t *) -1,
|
|
/* raw_size */ 720,
|
|
ANY_DATA_IDENTIFIER,
|
|
/* videostd_set */ 0,
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ 720,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_AMBIGUOUS_VIDEOSTD);
|
|
|
|
#if 3 == VBI_VERSION_MINOR
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
/* raw */ (uint8_t *) -1,
|
|
/* raw_size */ 720,
|
|
ANY_DATA_IDENTIFIER,
|
|
(VBI_VIDEOSTD_SET (VBI_VIDEOSTD_PAL_B) |
|
|
VBI_VIDEOSTD_SET (VBI_VIDEOSTD_NTSC_M)),
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ 720,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_AMBIGUOUS_VIDEOSTD);
|
|
#else
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
/* raw */ (uint8_t *) -1,
|
|
/* raw_size */ 720,
|
|
ANY_DATA_IDENTIFIER,
|
|
(VBI_VIDEOSTD_SET_625_50 |
|
|
VBI_VIDEOSTD_SET_525_60),
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ 720,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_AMBIGUOUS_VIDEOSTD);
|
|
#endif
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw_data_identifier
|
|
(unsigned int data_identifier)
|
|
{
|
|
uint8_t *raw;
|
|
unsigned int buffer_size;
|
|
unsigned int raw_size;
|
|
vbi_bool fixed_length;
|
|
|
|
raw = (uint8_t *) xralloc (raw_size = 720);
|
|
|
|
// EN 301 775 section 4.4.2.
|
|
fixed_length = (data_identifier >= 0x10
|
|
&& data_identifier <= 0x1F);
|
|
|
|
for (buffer_size = 20 * 46 - 1;
|
|
buffer_size <= 20 * 46 + 1; ++buffer_size) {
|
|
uint8_t *buffer;
|
|
vbi_bool exp_success;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size);
|
|
exp_success = (!fixed_length || 0 == buffer_size % 46);
|
|
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
raw, raw_size,
|
|
data_identifier,
|
|
ANY_VIDEOSTD,
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ raw_size,
|
|
ANY_STUFFING,
|
|
exp_success,
|
|
VBI_ERR_BUFFER_OVERFLOW);
|
|
free (buffer);
|
|
buffer = (uint8_t *) -1;
|
|
}
|
|
|
|
free (raw);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw_unaligned_raw (void)
|
|
{
|
|
uint8_t *buffer;
|
|
uint8_t *raw;
|
|
unsigned int buffer_size;
|
|
unsigned int raw_size;
|
|
unsigned int i;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
raw = (uint8_t *) xralloc (15 + (raw_size = 720));
|
|
|
|
for (i = 1; i < 16; ++i) {
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
raw + i,
|
|
raw_size,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_VIDEOSTD,
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ raw_size,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0);
|
|
}
|
|
|
|
free (raw);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw_null_raw_checks (void)
|
|
{
|
|
uint8_t *buffer;
|
|
unsigned int buffer_size;
|
|
|
|
buffer = (uint8_t *) xmalloc (buffer_size = 20 * 46);
|
|
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
/* raw */ NULL,
|
|
/* raw_size */ 720,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_VIDEOSTD,
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ 720,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_NO_RAW_DATA);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_mr_packet_size (unsigned int buffer_size,
|
|
unsigned int data_identifier,
|
|
vbi_bool exp_success)
|
|
{
|
|
uint8_t *buffer;
|
|
uint8_t *raw;
|
|
unsigned int raw_size;
|
|
|
|
if (0 == buffer_size) {
|
|
buffer = (uint8_t *) -1;
|
|
} else {
|
|
buffer = (uint8_t *) xmalloc (buffer_size);
|
|
}
|
|
|
|
raw = (uint8_t *) xralloc (raw_size = 720);
|
|
|
|
assert_multiplex_raw (buffer, buffer_size,
|
|
raw, raw_size,
|
|
data_identifier,
|
|
ANY_VIDEOSTD,
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ raw_size,
|
|
ANY_STUFFING,
|
|
exp_success,
|
|
VBI_ERR_BUFFER_OVERFLOW);
|
|
free (raw);
|
|
|
|
if (buffer_size > 0)
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw_packet_size_checks (void)
|
|
{
|
|
unsigned int buffer_size;
|
|
|
|
for (buffer_size = 0; buffer_size <= 1; ++buffer_size) {
|
|
test_mr_packet_size (buffer_size,
|
|
ANY_DATA_IDENTIFIER,
|
|
EXPECT_FAILURE);
|
|
}
|
|
|
|
for (buffer_size = 2; buffer_size <= 45; ++buffer_size) {
|
|
test_mr_packet_size (buffer_size,
|
|
/* data_identifier */ 0x10,
|
|
EXPECT_FAILURE);
|
|
test_mr_packet_size (buffer_size,
|
|
/* data_identifier */ 0x99,
|
|
EXPECT_SUCCESS);
|
|
}
|
|
|
|
for (buffer_size = 46; buffer_size < 900; ++buffer_size) {
|
|
test_mr_packet_size (buffer_size,
|
|
/* data_identifier */ 0x99,
|
|
EXPECT_SUCCESS);
|
|
}
|
|
|
|
for (buffer_size = 1 * 46;
|
|
buffer_size < 20 * 46; buffer_size += 46) {
|
|
test_mr_packet_size (buffer_size,
|
|
/* data_identifier */ 0x10,
|
|
EXPECT_SUCCESS);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw_unaligned_packet (void)
|
|
{
|
|
uint8_t *raw;
|
|
unsigned int raw_size;
|
|
unsigned int i;
|
|
|
|
raw = (uint8_t *) xralloc (raw_size = 720);
|
|
|
|
for (i = 1; i < 16; ++i) {
|
|
uint8_t *buffer;
|
|
unsigned int buffer_size;
|
|
|
|
buffer = (uint8_t *) xmalloc (i + (buffer_size = 20 * 46));
|
|
|
|
assert_multiplex_raw (buffer + i, buffer_size,
|
|
raw, raw_size,
|
|
ANY_DATA_IDENTIFIER,
|
|
ANY_VIDEOSTD,
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ raw_size,
|
|
ANY_STUFFING,
|
|
EXPECT_SUCCESS,
|
|
/* exp_errno */ 0);
|
|
free (buffer);
|
|
buffer = (uint8_t *) -1;
|
|
}
|
|
|
|
free (raw);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw_null_packet_checks (void)
|
|
{
|
|
assert_multiplex_raw (/* packet */ NULL,
|
|
/* packet_size */ 20 * 46,
|
|
/* raw */ (uint8_t *) -1,
|
|
/* raw_size */ 720,
|
|
ANY_DATA_IDENTIFIER,
|
|
VBI_VIDEOSTD_SET_625_50,
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ 720,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_BUFFER_OVERFLOW);
|
|
|
|
assert_multiplex_raw (/* packet */ (uint8_t *) -1,
|
|
/* packet_size */ 0,
|
|
/* raw */ (uint8_t *) -1,
|
|
/* raw_size */ 720,
|
|
ANY_DATA_IDENTIFIER,
|
|
VBI_VIDEOSTD_SET_625_50,
|
|
/* line */ 10,
|
|
/* first_pixel_position */ 0,
|
|
/* n_pixels_total */ 720,
|
|
ANY_STUFFING,
|
|
EXPECT_FAILURE,
|
|
VBI_ERR_BUFFER_OVERFLOW);
|
|
}
|
|
|
|
static void
|
|
test_multiplex_raw (void)
|
|
{
|
|
unsigned int i;
|
|
|
|
test_multiplex_raw_null_packet_checks ();
|
|
test_multiplex_raw_null_raw_checks ();
|
|
test_multiplex_raw_packet_size_checks ();
|
|
|
|
for (i = 0; i < N_ELEMENTS (data_identifiers); ++i)
|
|
test_multiplex_raw_data_identifier (data_identifiers[i]);
|
|
|
|
test_multiplex_raw_videostd_checks ();
|
|
test_multiplex_raw_line_number_checks ();
|
|
|
|
test_multiplex_raw_size_offsets ();
|
|
|
|
test_multiplex_raw_unaligned_packet ();
|
|
test_multiplex_raw_unaligned_raw ();
|
|
}
|
|
|
|
/*
|
|
Test PES/TS multiplexer.
|
|
*/
|
|
|
|
static const vbi_sampling_par
|
|
good_par_625 = {
|
|
#if 3 == VBI_VERSION_MINOR
|
|
/* videostd_set */ VBI_VIDEOSTD_SET_625_50,
|
|
/* sample_format */ VBI_PIXFMT_Y8,
|
|
/* sampling_rate */ 13500000,
|
|
/* samples_per_line */ 720,
|
|
/* bytes_per_line */ 720,
|
|
/* offset */ 132,
|
|
/* start */ { 7, 320 },
|
|
/* count */ { 17, 17 },
|
|
/* interlaced */ FALSE,
|
|
/* synchronous */ TRUE
|
|
#else
|
|
/* scanning */ 625,
|
|
/* sampling_format */ VBI_PIXFMT_YUV420,
|
|
/* sampling_rate */ 13500000,
|
|
/* bytes_per_line */ 720,
|
|
/* offset */ 132,
|
|
/* start */ { 7, 320 },
|
|
/* count */ { 17, 17 },
|
|
/* interlaced */ FALSE,
|
|
/* synchronous */ TRUE
|
|
#endif
|
|
};
|
|
|
|
static const unsigned int
|
|
packet_sizes [] = {
|
|
0,
|
|
12,
|
|
183,
|
|
184,
|
|
185,
|
|
1234,
|
|
65503,
|
|
65504,
|
|
65505,
|
|
INT_MAX,
|
|
((unsigned int) INT_MAX) + 1,
|
|
UINT_MAX,
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DVBMux {
|
|
protected:
|
|
vbi_dvb_mux * _mx;
|
|
|
|
public:
|
|
DVBMux () {
|
|
_mx = NULL;
|
|
};
|
|
|
|
~DVBMux () {
|
|
vbi_dvb_mux_delete (_mx);
|
|
};
|
|
|
|
operator vbi_dvb_mux* () const {
|
|
return _mx;
|
|
};
|
|
|
|
unsigned int get_min_pes_packet_size () {
|
|
assert (NULL != _mx);
|
|
return vbi_dvb_mux_get_min_pes_packet_size (_mx);
|
|
};
|
|
|
|
unsigned int get_max_pes_packet_size () {
|
|
assert (NULL != _mx);
|
|
return vbi_dvb_mux_get_max_pes_packet_size (_mx);
|
|
};
|
|
|
|
bool set_pes_packet_size (unsigned int min_size,
|
|
unsigned int max_size) {
|
|
assert (NULL != _mx);
|
|
return vbi_dvb_mux_set_pes_packet_size (_mx,
|
|
min_size,
|
|
max_size);
|
|
};
|
|
|
|
unsigned int get_data_identifier () {
|
|
assert (NULL != _mx);
|
|
return vbi_dvb_mux_get_data_identifier (_mx);
|
|
};
|
|
|
|
bool set_data_identifier (unsigned int di) {
|
|
assert (NULL != _mx);
|
|
return vbi_dvb_mux_set_data_identifier (_mx, di);
|
|
};
|
|
};
|
|
|
|
class DVBPESMux : public DVBMux {
|
|
public:
|
|
DVBPESMux (vbi_dvb_mux_cb * callback = NULL,
|
|
void * user_data = NULL) {
|
|
_mx = vbi_dvb_pes_mux_new (callback, user_data);
|
|
assert (NULL != _mx);
|
|
};
|
|
};
|
|
|
|
static void
|
|
alloc_init_sliced (vbi_sliced ** sliced_p,
|
|
unsigned int * n_lines_p)
|
|
{
|
|
const unsigned int max_lines = 2 * (23 - 7) + 1;
|
|
vbi_sliced *sliced;
|
|
unsigned int n_lines;
|
|
unsigned int field;
|
|
|
|
sliced = alloc_sliced (max_lines);
|
|
|
|
n_lines = 0;
|
|
|
|
for (field = 0; field < 2; ++field) {
|
|
unsigned int j;
|
|
|
|
for (j = 7; j < 15; ++j) {
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = field * 313 + j;
|
|
}
|
|
|
|
if (0 == field)
|
|
sliced[n_lines].id = VBI_SLICED_VBI_625;
|
|
else
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = field * 313 + 15;
|
|
|
|
if (0 == field)
|
|
sliced[n_lines].id = VBI_SLICED_VPS;
|
|
else
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = field * 313 + 16;
|
|
|
|
for (j = 17; j < 20; ++j) {
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = field * 313 + j;
|
|
}
|
|
|
|
if (1 == field)
|
|
sliced[n_lines].id = VBI_SLICED_VBI_625;
|
|
else
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = field * 313 + 20;
|
|
|
|
if (0 == field)
|
|
sliced[n_lines].id = VBI_SLICED_CAPTION_625;
|
|
else
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = field * 313 + 21;
|
|
|
|
sliced[n_lines].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[n_lines++].line = field * 313 + 22;
|
|
|
|
if (0 == field) {
|
|
sliced[n_lines].id = VBI_SLICED_WSS_625;
|
|
sliced[n_lines++].line = 23;
|
|
}
|
|
}
|
|
|
|
assert (n_lines == max_lines);
|
|
|
|
*sliced_p = sliced;
|
|
*n_lines_p = n_lines;
|
|
}
|
|
|
|
class DVBPESMuxTest : public DVBPESMux {
|
|
/* vbi_dvb_mux_cor() parameters. */
|
|
|
|
uint8_t * _buffer;
|
|
unsigned int _buffer_size;
|
|
bool _have_buffer;
|
|
bool _free_buffer;
|
|
|
|
vbi_sliced * _sliced;
|
|
unsigned int _sliced_lines;
|
|
bool _have_sliced;
|
|
bool _free_sliced;
|
|
|
|
uint8_t * _raw;
|
|
const vbi_sampling_par *_sp;
|
|
bool _have_raw;
|
|
bool _free_raw;
|
|
|
|
vbi_service_set _service_mask;
|
|
|
|
int64_t _pts;
|
|
|
|
/* Test status. */
|
|
|
|
bool _cb_cmp;
|
|
|
|
uint8_t * _cb_bp;
|
|
uint8_t * _cb_ts_bp;
|
|
|
|
int _cb_next_continuity_counter;
|
|
|
|
void cmp_ts_feed (const vbi_bool exp_success,
|
|
const int exp_errno,
|
|
const unsigned int exp_consumed_lines);
|
|
|
|
void cmp_ts_cor (const vbi_bool exp_success,
|
|
const int exp_errno,
|
|
const unsigned int exp_consumed_lines);
|
|
|
|
void cmp_pes_feed (const vbi_bool exp_success,
|
|
const int exp_errno,
|
|
const unsigned int exp_consumed_lines);
|
|
|
|
void copy_props (vbi_dvb_mux *mx) {
|
|
vbi_bool success;
|
|
|
|
assert (NULL != mx);
|
|
|
|
success = vbi_dvb_mux_set_data_identifier
|
|
(mx, get_data_identifier ());
|
|
assert (TRUE == success);
|
|
|
|
success = vbi_dvb_mux_set_pes_packet_size
|
|
(mx, get_min_pes_packet_size (),
|
|
get_max_pes_packet_size ());
|
|
assert (TRUE == success);
|
|
};
|
|
|
|
public:
|
|
DVBPESMuxTest () {
|
|
_have_buffer = false;
|
|
_free_buffer = false;
|
|
|
|
_have_sliced = false;
|
|
_free_sliced = false;
|
|
|
|
_have_raw = false;
|
|
_free_raw = false;
|
|
|
|
_service_mask = ALL_SERVICES;
|
|
|
|
_pts = 0x1234567;
|
|
};
|
|
|
|
~DVBPESMuxTest () {
|
|
if (_free_raw)
|
|
free (_raw);
|
|
|
|
if (_free_sliced)
|
|
free (_sliced);
|
|
|
|
if (_free_buffer)
|
|
free (_buffer);
|
|
};
|
|
|
|
bool ts_cb (const uint8_t *packet,
|
|
unsigned int packet_size);
|
|
|
|
bool pes_cb (const uint8_t *packet,
|
|
unsigned int packet_size);
|
|
|
|
void set_buffer (uint8_t *buffer,
|
|
unsigned int n_bytes) {
|
|
if (_free_buffer)
|
|
free (_buffer);
|
|
|
|
_buffer = buffer;
|
|
_buffer_size = n_bytes;
|
|
_have_buffer = true;
|
|
_free_buffer = false;
|
|
};
|
|
|
|
void set_buffer_size (unsigned int n_bytes) {
|
|
if (_free_buffer)
|
|
free (_buffer);
|
|
|
|
if (n_bytes > 0)
|
|
_buffer = (uint8_t *) xmalloc (n_bytes);
|
|
else
|
|
_buffer = NULL;
|
|
|
|
_buffer_size = n_bytes;
|
|
_have_buffer = true;
|
|
_free_buffer = true;
|
|
};
|
|
|
|
void set_sliced (vbi_sliced* sliced,
|
|
unsigned int n_lines) {
|
|
if (_free_sliced)
|
|
free (_sliced);
|
|
|
|
_sliced = sliced;
|
|
_sliced_lines = n_lines;
|
|
_have_sliced = true;
|
|
_free_sliced = false;
|
|
};
|
|
|
|
void set_raw (uint8_t *raw,
|
|
const vbi_sampling_par *sp) {
|
|
if (_free_raw)
|
|
free (_raw);
|
|
|
|
_raw = raw;
|
|
_sp = sp;
|
|
_have_raw = true;
|
|
_free_raw = false;
|
|
};
|
|
|
|
void set_sampling_par (const vbi_sampling_par *sp) {
|
|
if (_free_raw)
|
|
free (_raw);
|
|
|
|
_raw = alloc_raw_frame (sp);
|
|
_sp = sp;
|
|
_have_raw = true;
|
|
_free_raw = true;
|
|
};
|
|
|
|
void set_service_mask (vbi_service_set mask) {
|
|
_service_mask = mask;
|
|
};
|
|
|
|
void set_pts (int64_t pts) {
|
|
_pts = pts;
|
|
};
|
|
|
|
void test (const vbi_bool exp_success,
|
|
const int exp_errno,
|
|
const unsigned int exp_consumed_lines);
|
|
|
|
void test_line (const vbi_sampling_par *sp,
|
|
const vbi_service_set service,
|
|
const unsigned int line,
|
|
const vbi_bool exp_success);
|
|
|
|
void test_fail (const int exp_errno,
|
|
const unsigned int exp_consumed_lines) {
|
|
test (/* exp_success */ FALSE,
|
|
exp_errno,
|
|
exp_consumed_lines);
|
|
};
|
|
|
|
void test_pass () {
|
|
if (!_have_sliced) {
|
|
alloc_init_sliced (&_sliced,
|
|
&_sliced_lines);
|
|
_have_sliced = true;
|
|
_free_sliced = true;
|
|
}
|
|
|
|
test (/* exp_success */ TRUE,
|
|
/* exp_errno */ 0,
|
|
/* exp_consumed_lines */ _sliced_lines);
|
|
};
|
|
};
|
|
|
|
bool
|
|
DVBPESMuxTest::pes_cb (const uint8_t * packet,
|
|
unsigned int packet_size)
|
|
{
|
|
assert (0 == packet_size % 184);
|
|
assert (packet_size >= get_min_pes_packet_size ());
|
|
assert (packet_size <= get_max_pes_packet_size ());
|
|
|
|
if (_cb_cmp) {
|
|
// Compare against the output of the PES mux coroutine.
|
|
assert (0 == memcmp (_cb_bp, packet, packet_size));
|
|
} else {
|
|
unsigned int n_sliced_dus;
|
|
unsigned int n_raw_dus;
|
|
unsigned int n_stuffing_dus;
|
|
|
|
// For the TS feed test.
|
|
memcpy (_cb_bp, packet, packet_size);
|
|
|
|
assert_pes_packet_ok (&n_sliced_dus,
|
|
&n_raw_dus,
|
|
&n_stuffing_dus,
|
|
packet,
|
|
packet_size,
|
|
get_data_identifier (),
|
|
get_min_pes_packet_size (),
|
|
get_max_pes_packet_size ());
|
|
|
|
assert (0 == n_sliced_dus);
|
|
assert (0 == n_raw_dus);
|
|
assert (n_stuffing_dus > 0);
|
|
}
|
|
|
|
_cb_bp += packet_size;
|
|
|
|
return true;
|
|
}
|
|
|
|
static vbi_bool
|
|
dvb_mux_pes_cb (vbi_dvb_mux * mx,
|
|
void * user_data,
|
|
const uint8_t * packet,
|
|
unsigned int packet_size)
|
|
{
|
|
DVBPESMuxTest *tmx = (DVBPESMuxTest *) user_data;
|
|
|
|
mx = mx; /* unused */
|
|
|
|
return tmx->pes_cb (packet, packet_size);
|
|
}
|
|
|
|
bool
|
|
DVBPESMuxTest::ts_cb (const uint8_t * packet,
|
|
unsigned int packet_size)
|
|
{
|
|
unsigned int payload_unit_start_indicator;
|
|
unsigned int continuity_counter;
|
|
|
|
assert (188 == packet_size);
|
|
|
|
/* sync_byte [8],
|
|
transport_error_indicator,
|
|
payload_unit_start_indicator,
|
|
transport_priority,
|
|
PID [13] == 0x1234,
|
|
transport_scrambling_control [2] == '00' (not scrambled),
|
|
adaptation_field_control [2] == '01'
|
|
(payload only, no adaption field),
|
|
continuity_counter [4] */
|
|
assert (0x47 == packet[0]);
|
|
assert (0x12 == (packet[1] & ~0x40));
|
|
assert (0x34 == packet[2]);
|
|
assert (0x10 == (packet[3] & ~0x0F));
|
|
|
|
payload_unit_start_indicator = !!(packet[1] & 0x40);
|
|
|
|
assert ((0x00 == packet[4] &&
|
|
0x00 == packet[5] &&
|
|
0x01 == packet[6] &&
|
|
0xBD == packet[7]) == payload_unit_start_indicator);
|
|
|
|
continuity_counter = packet[3] & 0x0F;
|
|
|
|
if (-1 != _cb_next_continuity_counter) {
|
|
assert ((unsigned int) _cb_next_continuity_counter
|
|
== continuity_counter);
|
|
}
|
|
|
|
_cb_next_continuity_counter = (continuity_counter + 1) & 0xF;
|
|
|
|
if (_cb_cmp) {
|
|
// Compare against the output of the PES mux coroutine.
|
|
assert (0 == memcmp (_cb_bp, packet + 4, 184));
|
|
_cb_bp += 184;
|
|
|
|
// Compare against the output of the TS mux coroutine.
|
|
assert (0 == memcmp (_cb_ts_bp, packet, 188));
|
|
_cb_ts_bp += 188;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static vbi_bool
|
|
dvb_mux_ts_cb (vbi_dvb_mux * mx,
|
|
void * user_data,
|
|
const uint8_t * packet,
|
|
unsigned int packet_size)
|
|
{
|
|
DVBPESMuxTest *tmx = (DVBPESMuxTest *) user_data;
|
|
|
|
mx = mx; /* unused */
|
|
|
|
return tmx->ts_cb (packet, packet_size);
|
|
}
|
|
|
|
void
|
|
DVBPESMuxTest::test (const vbi_bool exp_success,
|
|
const int exp_errno,
|
|
const unsigned int exp_consumed_lines)
|
|
{
|
|
uint8_t *rand_buffer;
|
|
uint8_t *ts_buffer;
|
|
uint8_t *ts_rand_buffer;
|
|
unsigned int ts_buffer_size;
|
|
|
|
if (!_have_buffer)
|
|
set_buffer_size (4 << 10);
|
|
|
|
if (!_have_sliced) {
|
|
alloc_init_sliced (&_sliced, &_sliced_lines);
|
|
_have_sliced = true;
|
|
_free_sliced = true;
|
|
}
|
|
|
|
if (!_have_raw)
|
|
set_sampling_par (&good_par_625);
|
|
|
|
if (NULL != _buffer) {
|
|
rand_buffer = (uint8_t *) xralloc (_buffer_size);
|
|
memcpy (_buffer, rand_buffer, _buffer_size);
|
|
|
|
ts_buffer_size = _buffer_size * 188 / 184;
|
|
ts_buffer = (uint8_t *) xmalloc (ts_buffer_size);
|
|
|
|
ts_rand_buffer = (uint8_t *) xralloc (ts_buffer_size);
|
|
memcpy (ts_buffer, ts_rand_buffer, ts_buffer_size);
|
|
} else {
|
|
rand_buffer = NULL;
|
|
|
|
ts_buffer = NULL;
|
|
ts_rand_buffer = NULL;
|
|
ts_buffer_size = 0;
|
|
}
|
|
|
|
uint8_t *p = _buffer;
|
|
unsigned int p_left = _buffer_size;
|
|
|
|
const vbi_sliced *s = _sliced;
|
|
unsigned int s_left = _sliced_lines;
|
|
|
|
vbi_bool success = vbi_dvb_mux_cor (*this,
|
|
&p, &p_left,
|
|
&s, &s_left,
|
|
_service_mask,
|
|
_raw, _sp,
|
|
_pts);
|
|
|
|
if (NULL == _buffer || 0 == _buffer_size
|
|
|| NULL == _sliced || 0 == _sliced_lines)
|
|
assert (FALSE == success);
|
|
else
|
|
assert (exp_success == success);
|
|
|
|
unsigned int pes_bytes_out = _buffer_size - p_left;
|
|
|
|
assert (_buffer + pes_bytes_out == p);
|
|
|
|
assert (_sliced + exp_consumed_lines == s);
|
|
assert (_sliced_lines - exp_consumed_lines == s_left);
|
|
|
|
if (success) {
|
|
unsigned int n_sliced_dus;
|
|
unsigned int n_raw_dus;
|
|
unsigned int n_stuffing_dus;
|
|
|
|
assert_pes_packet_ok (&n_sliced_dus,
|
|
&n_raw_dus,
|
|
&n_stuffing_dus,
|
|
_buffer,
|
|
pes_bytes_out,
|
|
get_data_identifier (),
|
|
get_min_pes_packet_size (),
|
|
get_max_pes_packet_size ());
|
|
|
|
assert (_sliced_lines >= n_sliced_dus);
|
|
|
|
if (0 == _service_mask) {
|
|
assert (0 == n_sliced_dus);
|
|
assert (0 == n_raw_dus);
|
|
}
|
|
|
|
if (NULL == _raw || NULL == _sp)
|
|
assert (0 == n_raw_dus);
|
|
|
|
assert_pes_conversion_ok (_buffer,
|
|
pes_bytes_out,
|
|
_sliced,
|
|
_sliced_lines,
|
|
_service_mask,
|
|
_pts);
|
|
} else {
|
|
(void) exp_errno;
|
|
// assert (exp_errno == errno);
|
|
|
|
assert (0 == pes_bytes_out);
|
|
}
|
|
|
|
if (NULL != _buffer) {
|
|
assert (0 == memcmp (p, rand_buffer + pes_bytes_out,
|
|
_buffer_size - pes_bytes_out));
|
|
}
|
|
|
|
if (NULL != _buffer && _buffer_size > 0) {
|
|
vbi_dvb_mux *mx;
|
|
unsigned int exp_bytes_out;
|
|
|
|
// Verify that the PES callback gives the same result.
|
|
|
|
mx = vbi_dvb_pes_mux_new (/* callback */ dvb_mux_pes_cb,
|
|
/* user_data */ this);
|
|
assert (NULL != mx);
|
|
|
|
copy_props (mx);
|
|
|
|
_cb_bp = _buffer;
|
|
_cb_cmp = (NULL != _sliced && _sliced_lines > 0);
|
|
|
|
success = vbi_dvb_mux_feed (mx,
|
|
_sliced, _sliced_lines,
|
|
_service_mask,
|
|
_raw, _sp,
|
|
_pts);
|
|
|
|
assert (exp_success == success);
|
|
|
|
if (_cb_cmp) {
|
|
exp_bytes_out = pes_bytes_out;
|
|
} else if (success) {
|
|
// Stuffing.
|
|
exp_bytes_out = get_min_pes_packet_size ();
|
|
} else {
|
|
exp_bytes_out = 0;
|
|
}
|
|
|
|
assert (_cb_bp == _buffer + exp_bytes_out);
|
|
|
|
if (!success) {
|
|
(void) exp_errno;
|
|
// assert (exp_errno == errno);
|
|
}
|
|
|
|
vbi_dvb_mux_delete (mx);
|
|
}
|
|
|
|
{
|
|
vbi_dvb_mux *mx;
|
|
|
|
// Test the TS coroutine.
|
|
|
|
mx = vbi_dvb_ts_mux_new (/* pid */ 0x1234,
|
|
/* callback */ NULL,
|
|
/* user_data */ NULL);
|
|
assert (NULL != mx);
|
|
|
|
copy_props (mx);
|
|
|
|
p = ts_buffer;
|
|
p_left = ts_buffer_size;
|
|
|
|
s = _sliced;
|
|
s_left = _sliced_lines;
|
|
|
|
success = vbi_dvb_mux_cor (mx,
|
|
&p, &p_left,
|
|
&s, &s_left,
|
|
_service_mask,
|
|
_raw, _sp,
|
|
_pts);
|
|
|
|
if (NULL == ts_buffer || 0 == ts_buffer_size
|
|
|| NULL == _sliced || 0 == _sliced_lines)
|
|
assert (FALSE == success);
|
|
else
|
|
assert (exp_success == success);
|
|
|
|
unsigned int ts_bytes_out = ts_buffer_size - p_left;
|
|
|
|
assert (pes_bytes_out * 188 / 184 == ts_bytes_out);
|
|
|
|
assert (ts_buffer + ts_bytes_out == p);
|
|
|
|
assert (_sliced + exp_consumed_lines == s);
|
|
assert (_sliced_lines - exp_consumed_lines == s_left);
|
|
|
|
if (!success) {
|
|
(void) exp_errno;
|
|
// assert (exp_errno == errno);
|
|
|
|
assert (0 == ts_bytes_out);
|
|
}
|
|
|
|
if (NULL != ts_buffer) {
|
|
assert (0 == memcmp (p, ts_rand_buffer + ts_bytes_out,
|
|
ts_buffer_size - ts_bytes_out));
|
|
}
|
|
|
|
vbi_dvb_mux_delete (mx);
|
|
}
|
|
|
|
if (NULL != _buffer && _buffer_size > 0) {
|
|
vbi_dvb_mux *mx;
|
|
unsigned int exp_bytes_out;
|
|
|
|
/* Verify that the TS callback and the TS coroutine give
|
|
the same result as the PES coroutine. */
|
|
|
|
mx = vbi_dvb_ts_mux_new (/* pid */ 0x1234,
|
|
/* callback */ dvb_mux_ts_cb,
|
|
/* user_data */ this);
|
|
assert (NULL != mx);
|
|
|
|
copy_props (mx);
|
|
|
|
_cb_bp = _buffer;
|
|
_cb_cmp = (NULL != _sliced && _sliced_lines > 0);
|
|
|
|
_cb_ts_bp = ts_buffer;
|
|
|
|
_cb_next_continuity_counter = -1;
|
|
|
|
success = vbi_dvb_mux_feed (mx,
|
|
_sliced, _sliced_lines,
|
|
_service_mask,
|
|
_raw, _sp,
|
|
_pts);
|
|
|
|
assert (exp_success == success);
|
|
|
|
if (_cb_cmp) {
|
|
exp_bytes_out = pes_bytes_out;
|
|
} else if (success) {
|
|
// Stuffing.
|
|
exp_bytes_out = get_min_pes_packet_size ();
|
|
} else {
|
|
exp_bytes_out = 0;
|
|
}
|
|
|
|
assert (_cb_bp == _buffer + pes_bytes_out);
|
|
assert (_cb_ts_bp == ts_buffer + pes_bytes_out * 188 / 184);
|
|
|
|
if (!success) {
|
|
(void) exp_errno;
|
|
// assert (exp_errno == errno);
|
|
}
|
|
|
|
vbi_dvb_mux_delete (mx);
|
|
}
|
|
|
|
free (ts_rand_buffer);
|
|
free (ts_buffer);
|
|
free (rand_buffer);
|
|
}
|
|
|
|
void
|
|
DVBPESMuxTest::test_line (const vbi_sampling_par *sp,
|
|
const vbi_service_set service,
|
|
const unsigned int line,
|
|
const vbi_bool exp_success)
|
|
{
|
|
if (!_free_sliced) {
|
|
_sliced = alloc_sliced (1);
|
|
_sliced_lines = 1;
|
|
_have_sliced = true;
|
|
_free_sliced = true;
|
|
}
|
|
|
|
_sliced[0].id = service;
|
|
_sliced[0].line = line;
|
|
|
|
set_sampling_par (sp);
|
|
|
|
test (exp_success,
|
|
VBI_ERR_LINE_NUMBER,
|
|
/* exp_consumed_lines */ exp_success ? 1 : 0);
|
|
};
|
|
|
|
static void
|
|
test_dvb_mux_cor_partial_reads_and_reset
|
|
(unsigned int pid)
|
|
{
|
|
static const unsigned int steps [] = {
|
|
1, 46, 184, 188, 999999, INT_MAX,
|
|
(unsigned int) INT_MAX + 1, UINT_MAX
|
|
};
|
|
vbi_dvb_mux *mx;
|
|
vbi_sliced *sliced;
|
|
const vbi_sliced *s;
|
|
uint8_t *buffer1;
|
|
uint8_t *buffer2;
|
|
uint8_t *p;
|
|
uint8_t *raw;
|
|
unsigned int buffer_size;
|
|
unsigned int n_lines;
|
|
unsigned int p_left;
|
|
unsigned int s_left;
|
|
unsigned int i;
|
|
vbi_bool success;
|
|
|
|
if (0 == pid) {
|
|
mx = vbi_dvb_pes_mux_new (/* callback */ NULL,
|
|
/* user_data */ NULL);
|
|
buffer_size = 68 * 46;
|
|
} else {
|
|
mx = vbi_dvb_ts_mux_new (pid,
|
|
/* callback */ NULL,
|
|
/* user_data */ NULL);
|
|
buffer_size = 68 * 46 * 188 / 184;
|
|
}
|
|
|
|
assert (NULL != mx);
|
|
|
|
alloc_init_sliced (&sliced, &n_lines);
|
|
|
|
raw = alloc_raw_frame (&good_par_625);
|
|
|
|
buffer1 = (uint8_t *) xralloc (buffer_size);
|
|
buffer2 = (uint8_t *) xmalloc (buffer_size);
|
|
|
|
p = buffer1;
|
|
p_left = buffer_size;
|
|
|
|
s = sliced;
|
|
s_left = n_lines;
|
|
|
|
success = vbi_dvb_mux_cor (mx,
|
|
&p, &p_left,
|
|
&s, &s_left,
|
|
ALL_SERVICES,
|
|
raw,
|
|
&good_par_625,
|
|
/* pts */ 0x1234567);
|
|
assert (TRUE == success);
|
|
assert (0 == p_left);
|
|
assert (0 == s_left);
|
|
|
|
for (i = 0; i < N_ELEMENTS (steps); ++i) {
|
|
p = buffer2;
|
|
p_left = buffer_size / 2;
|
|
|
|
s = sliced;
|
|
s_left = n_lines;
|
|
|
|
success = vbi_dvb_mux_cor (mx,
|
|
&p, &p_left,
|
|
&s, &s_left,
|
|
ALL_SERVICES,
|
|
raw,
|
|
&good_par_625,
|
|
/* pts */ 0x1234567);
|
|
assert (TRUE == success);
|
|
|
|
// Discard the second half.
|
|
vbi_dvb_mux_reset (mx);
|
|
|
|
memset_rand (buffer2, buffer_size);
|
|
|
|
p = buffer2;
|
|
|
|
s = sliced;
|
|
s_left = n_lines;
|
|
|
|
do {
|
|
p_left = steps[i];
|
|
|
|
success = vbi_dvb_mux_cor (mx,
|
|
&p, &p_left,
|
|
&s, &s_left,
|
|
ALL_SERVICES,
|
|
raw,
|
|
&good_par_625,
|
|
/* pts */ 0x1234567);
|
|
assert (TRUE == success);
|
|
} while (s_left > 0);
|
|
|
|
assert (buffer2 + buffer_size == p);
|
|
|
|
if (0 == pid) {
|
|
assert (0 == memcmp (buffer1, buffer2, buffer_size));
|
|
} else {
|
|
unsigned int j;
|
|
|
|
for (j = 0; j < buffer_size; j += 188) {
|
|
assert (buffer1[j + 0] == buffer2[j + 0]);
|
|
assert (buffer1[j + 1] == buffer2[j + 1]);
|
|
assert (buffer1[j + 2] == buffer2[j + 2]);
|
|
|
|
/* Ignore continuity_counter change
|
|
due to the reset. (The function
|
|
intentionally resets not to zero.) */
|
|
assert (0 == ((buffer1[j + 3]
|
|
^ buffer2[j + 3]) & 0xF0));
|
|
|
|
assert (0 == memcmp (buffer1 + j + 4,
|
|
buffer2 + j + 4, 184));
|
|
}
|
|
|
|
assert (j == buffer_size);
|
|
}
|
|
}
|
|
|
|
free (buffer2);
|
|
free (buffer1);
|
|
free (raw);
|
|
free (sliced);
|
|
|
|
vbi_dvb_mux_delete (mx);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_service_mask (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
|
|
mx.set_service_mask (VBI_SLICED_VPS |
|
|
VBI_SLICED_WSS_625);
|
|
mx.test_pass ();
|
|
|
|
mx.set_service_mask (0);
|
|
mx.test_pass ();
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_pts (void)
|
|
{
|
|
static const int64_t ptss [] = {
|
|
0x8000000000000000ll, -1, 0, 0x7FFFFFFFFFFFFFFFll,
|
|
};
|
|
DVBPESMuxTest mx;
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < N_ELEMENTS (ptss); ++i) {
|
|
mx.set_pts (ptss[i]);
|
|
mx.test_pass ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_mx_raw_offset (unsigned int bytes_per_line,
|
|
unsigned int samples_per_line,
|
|
unsigned int offset)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
vbi_sampling_par sp;
|
|
|
|
sp = good_par_625;
|
|
sp.bytes_per_line = bytes_per_line;
|
|
sp.sp_samples_per_line = samples_per_line;
|
|
sp.offset = offset;
|
|
|
|
if (offset < 132
|
|
|| (uint64_t) offset + samples_per_line > 132 + 720
|
|
|| 0 == samples_per_line
|
|
|| samples_per_line > bytes_per_line) {
|
|
mx.set_sliced (/* sliced */ (vbi_sliced *) -1,
|
|
/* sliced_lines */ 17);
|
|
mx.set_raw ((uint8_t *) -1, &sp);
|
|
mx.test_fail (VBI_ERR_SAMPLING_PAR,
|
|
/* exp_consumed_lines */ 0);
|
|
} else if (bytes_per_line < INT_MAX) {
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_pass ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_sampling_parameter_checks (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
vbi_sampling_par sp;
|
|
unsigned int i;
|
|
|
|
// FIXME: Test vbi_valid_sampling_par_log().
|
|
|
|
#if 3 == VBI_VERSION_MINOR
|
|
sp = good_par_625;
|
|
sp.videostd_set = 0;
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_fail (VBI_ERR_SAMPLING_PAR,
|
|
/* exp_consumed_lines */ 0);
|
|
|
|
sp = good_par_625;
|
|
sp.videostd_set = VBI_VIDEOSTD_SET_525_60;
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_fail (VBI_ERR_SAMPLING_PAR,
|
|
/* exp_consumed_lines */ 0);
|
|
|
|
sp = good_par_625;
|
|
sp.videostd_set = (VBI_VIDEOSTD_SET (VBI_VIDEOSTD_PAL_B) |
|
|
VBI_VIDEOSTD_SET (VBI_VIDEOSTD_NTSC_M));
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_fail (VBI_ERR_SAMPLING_PAR,
|
|
/* exp_consumed_lines */ 0);
|
|
#else
|
|
sp = good_par_625;
|
|
sp.scanning = 0;
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_fail (VBI_ERR_SAMPLING_PAR,
|
|
/* exp_consumed_lines */ 0);
|
|
|
|
sp = good_par_625;
|
|
sp.scanning = 525;
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_fail (VBI_ERR_SAMPLING_PAR,
|
|
/* exp_consumed_lines */ 0);
|
|
#endif
|
|
|
|
sp = good_par_625;
|
|
sp.sp_sample_format = VBI_PIXFMT_YUYV;
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_fail (VBI_ERR_SAMPLING_PAR,
|
|
/* exp_consumed_lines */ 0);
|
|
|
|
sp = good_par_625;
|
|
sp.sampling_rate = 27000000;
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_fail (VBI_ERR_SAMPLING_PAR,
|
|
/* exp_consumed_lines */ 0);
|
|
|
|
sp = good_par_625;
|
|
sp.synchronous = FALSE;
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_fail (VBI_ERR_SAMPLING_PAR,
|
|
/* exp_consumed_lines */ 0);
|
|
|
|
for (i = 0; i < N_ELEMENTS (raw_offsets); ++i) {
|
|
unsigned int j;
|
|
|
|
for (j = 0; j < N_ELEMENTS (raw_offsets); ++j) {
|
|
unsigned int k;
|
|
|
|
for (k = 0; k < N_ELEMENTS (raw_offsets); ++k) {
|
|
test_mx_raw_offset (raw_offsets[i],
|
|
raw_offsets[j],
|
|
raw_offsets[k]);
|
|
}
|
|
}
|
|
}
|
|
|
|
sp = good_par_625;
|
|
sp.interlaced = TRUE;
|
|
mx.set_sampling_par (&sp);
|
|
mx.test_pass ();
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_unaligned_raw (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
uint8_t *raw;
|
|
unsigned int n_lines;
|
|
unsigned int size;
|
|
unsigned int i;
|
|
|
|
n_lines = good_par_625.count[0] + good_par_625.count[1];
|
|
size = 15 + n_lines * good_par_625.bytes_per_line;
|
|
raw = (uint8_t *) xralloc (size);
|
|
|
|
for (i = 1; i < 16; ++i) {
|
|
mx.set_raw (raw + i, &good_par_625);
|
|
mx.test_pass ();
|
|
}
|
|
|
|
free (raw);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_null_raw_or_sp_checks (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
uint8_t *raw;
|
|
|
|
mx.set_raw (/* raw */ NULL, &good_par_625);
|
|
mx.test_fail (VBI_ERR_NO_RAW_DATA,
|
|
/* exp_consumed_lines */ 15 - 7);
|
|
|
|
raw = alloc_raw_frame (&good_par_625);
|
|
|
|
mx.set_raw (raw, /* sp */ NULL);
|
|
mx.test_fail (VBI_ERR_NO_RAW_DATA,
|
|
/* exp_consumed_lines */ 15 - 7);
|
|
|
|
free (raw);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_sp_line_number_checks (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
vbi_sampling_par sp;
|
|
|
|
sp = good_par_625;
|
|
sp.count[0] = 0;
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 7,
|
|
/* exp_success */ FALSE);
|
|
|
|
sp = good_par_625;
|
|
sp.count[1] = 0;
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 320,
|
|
/* exp_success */ FALSE);
|
|
|
|
sp = good_par_625;
|
|
sp.start[0] = 8;
|
|
sp.count[0] = 22 - 8 + 1;
|
|
sp.start[1] = 313 + 8;
|
|
sp.count[1] = 22 - 8 + 1;
|
|
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 7,
|
|
/* exp_success */ FALSE);
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 8,
|
|
/* exp_success */ TRUE);
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 22,
|
|
/* exp_success */ TRUE);
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 23,
|
|
/* exp_success */ FALSE);
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 313 + 7,
|
|
/* exp_success */ FALSE);
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 313 + 8,
|
|
/* exp_success */ TRUE);
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 313 + 22,
|
|
/* exp_success */ TRUE);
|
|
mx.test_line (&sp, VBI_SLICED_VBI_625, 313 + 23,
|
|
/* exp_success */ FALSE);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_line_number_checks (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
unsigned int i;
|
|
|
|
mx.test_line (&good_par_625,
|
|
/* service */ 0,
|
|
/* line (bad) */ 100,
|
|
/* exp_success */ TRUE);
|
|
|
|
for (i = 0; i <= 31; ++i) {
|
|
unsigned int j;
|
|
|
|
for (j = 0; j < N_ELEMENTS (good_services); ++j) {
|
|
vbi_service_set service = good_services[j];
|
|
|
|
mx.test_line (&good_par_625, service,
|
|
/* line */ i,
|
|
is_correct_line (service, 0, i));
|
|
mx.test_line (&good_par_625, service,
|
|
/* line */ i + 313,
|
|
is_correct_line (service, 1, i));
|
|
}
|
|
|
|
vbi_service_set service = VBI_SLICED_VBI_625;
|
|
|
|
mx.test_line (&good_par_625, service,
|
|
/* line */ i,
|
|
is_correct_line (service, 0, i));
|
|
mx.test_line (&good_par_625, service,
|
|
/* line */ i + 313,
|
|
is_correct_line (service, 1, i));
|
|
}
|
|
|
|
for (i = 0; i < N_ELEMENTS (bad_line_numbers); ++i) {
|
|
unsigned int j;
|
|
|
|
for (j = 0; j < N_ELEMENTS (good_services); ++j) {
|
|
vbi_service_set service = good_services[j];
|
|
|
|
mx.test_line (&good_par_625, service,
|
|
bad_line_numbers[i],
|
|
/* correct */ 0 == service);
|
|
}
|
|
|
|
mx.test_line (&good_par_625,
|
|
VBI_SLICED_VBI_625,
|
|
bad_line_numbers[i],
|
|
/* correct */ false);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_service_checks (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
vbi_sliced *sliced;
|
|
unsigned int n_lines;
|
|
unsigned int i;
|
|
|
|
sliced = alloc_sliced (n_lines = 8);
|
|
|
|
for (i = 0; i < 6; ++i) {
|
|
sliced[i].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[i].line = i + 7;
|
|
}
|
|
|
|
sliced[7].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[7].line = 320;
|
|
|
|
for (i = 0; i < N_ELEMENTS (all_services); ++i) {
|
|
vbi_service_set service;
|
|
unsigned int line;
|
|
|
|
service = all_services[i];
|
|
|
|
if (service & VBI_SLICED_VPS)
|
|
line = 16;
|
|
else if (service & VBI_SLICED_CAPTION_625)
|
|
line = 21;
|
|
else if (service & VBI_SLICED_WSS_625)
|
|
line = 23;
|
|
else
|
|
line = 13;
|
|
|
|
sliced[6].id = service;
|
|
sliced[6].line = line;
|
|
|
|
mx.set_sliced (sliced, n_lines);
|
|
|
|
if (VBI_SLICED_VBI_625 == service
|
|
|| is_good_service (service)) {
|
|
mx.test_pass ();
|
|
} else {
|
|
mx.test_fail (VBI_ERR_INVALID_SERVICE,
|
|
/* exp_consumed_lines */ 6);
|
|
}
|
|
}
|
|
|
|
free (sliced);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_line_order_checks (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
vbi_sliced *sliced;
|
|
unsigned int n_lines;
|
|
|
|
alloc_init_sliced (&sliced, &n_lines);
|
|
|
|
assert (VBI_SLICED_TELETEXT_B_625 == sliced[1].id);
|
|
assert (8 == sliced[1].line);
|
|
assert (VBI_SLICED_TELETEXT_B_625 == sliced[2].id);
|
|
assert (9 == sliced[2].line);
|
|
assert (VBI_SLICED_TELETEXT_B_625 == sliced[3].id);
|
|
assert (10 == sliced[3].line);
|
|
|
|
sliced[1].line = 0;
|
|
sliced[2].line = 0;
|
|
mx.set_sliced (sliced, n_lines);
|
|
mx.test_pass ();
|
|
|
|
sliced[1].line = 10;
|
|
sliced[2].line = 0;
|
|
mx.set_sliced (sliced, n_lines);
|
|
mx.test_fail (VBI_ERR_LINE_ORDER, 3);
|
|
|
|
sliced[1].line = 8;
|
|
sliced[2].line = 8;
|
|
mx.set_sliced (sliced, n_lines);
|
|
mx.test_fail (VBI_ERR_LINE_ORDER, 2);
|
|
|
|
sliced[1].line = 55;
|
|
sliced[2].line = 9;
|
|
mx.set_sliced (sliced, n_lines);
|
|
mx.test_fail (VBI_ERR_LINE_ORDER, 2);
|
|
|
|
sliced[1].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[1].line = 11;
|
|
sliced[2].id = VBI_SLICED_VBI_625;
|
|
sliced[2].line = 9;
|
|
mx.set_sliced (sliced, n_lines);
|
|
mx.test_fail (VBI_ERR_LINE_ORDER, 2);
|
|
|
|
sliced[1].id = VBI_SLICED_VBI_625;
|
|
sliced[1].line = 11;
|
|
sliced[2].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[2].line = 9;
|
|
mx.set_sliced (sliced, n_lines);
|
|
mx.test_fail (VBI_ERR_LINE_ORDER, 2);
|
|
|
|
sliced[1].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[1].line = 8;
|
|
sliced[2].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[2].line = 9;
|
|
|
|
assert (VBI_SLICED_TELETEXT_B_625 == sliced[17 + 1].id);
|
|
assert (313 + 8 == sliced[17 + 1].line);
|
|
assert (VBI_SLICED_TELETEXT_B_625 == sliced[17 + 2].id);
|
|
assert (313 + 9 == sliced[17 + 2].line);
|
|
|
|
sliced[17 + 1].line = 313 + 10;
|
|
mx.set_sliced (sliced, n_lines);
|
|
mx.test_fail (VBI_ERR_LINE_ORDER, 17 + 2);
|
|
|
|
free (sliced);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_packet_overflow_checks (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
vbi_sliced *sliced;
|
|
unsigned int max_size;
|
|
unsigned int n_lines;
|
|
unsigned int i;
|
|
|
|
mx.set_pes_packet_size (0, UINT_MAX);
|
|
max_size = mx.get_max_pes_packet_size ();
|
|
|
|
// Cannot fit because the header takes another 46 bytes.
|
|
n_lines = max_size / 46;
|
|
sliced = alloc_sliced (n_lines);
|
|
|
|
for (i = 0; i < n_lines; ++i) {
|
|
sliced[i].id = VBI_SLICED_TELETEXT_B_625;
|
|
sliced[i].line = 0;
|
|
}
|
|
|
|
mx.set_buffer_size ((n_lines + 1) * 46);
|
|
mx.set_sliced (sliced, n_lines);
|
|
mx.test_fail (VBI_ERR_BUFFER_OVERFLOW,
|
|
/* exp_consumed_lines */ n_lines - 1);
|
|
|
|
free (sliced);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_null_sliced_checks (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
vbi_sliced *sliced;
|
|
unsigned int n_lines;
|
|
|
|
alloc_init_sliced (&sliced, &n_lines);
|
|
|
|
mx.set_sliced (NULL, n_lines);
|
|
mx.test (/* exp_success */ TRUE,
|
|
/* exp_errno */ 0,
|
|
/* exp_consumed_lines */ 0);
|
|
|
|
mx.set_sliced (sliced, /* n_lines */ 0);
|
|
mx.test_pass ();
|
|
|
|
free (sliced);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_unaligned_packet (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
uint8_t *buffer;
|
|
unsigned int buffer_size;
|
|
unsigned int i;
|
|
|
|
buffer_size = 4 << 10;
|
|
buffer = (uint8_t *) xmalloc (15 + buffer_size);
|
|
|
|
for (i = 1; i < 16; ++i) {
|
|
mx.set_buffer (buffer + i, buffer_size);
|
|
mx.test_pass ();
|
|
}
|
|
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_cor_null_packet_checks (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
|
|
mx.set_buffer (NULL, /* buffer_size */ 4 << 10);
|
|
mx.test_fail (VBI_ERR_BUFFER_OVERFLOW,
|
|
/* exp_consumed_lines */ 0);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_feed_no_callback_checks (void)
|
|
{
|
|
vbi_dvb_mux *mx;
|
|
vbi_sliced *sliced;
|
|
uint8_t *raw;
|
|
unsigned int n_lines;
|
|
vbi_bool success;
|
|
|
|
mx = vbi_dvb_pes_mux_new (/* callback */ NULL,
|
|
/* user_data */ NULL);
|
|
|
|
alloc_init_sliced (&sliced, &n_lines);
|
|
raw = alloc_raw_frame (&good_par_625);
|
|
|
|
success = vbi_dvb_mux_feed (mx,
|
|
sliced, n_lines,
|
|
ALL_SERVICES,
|
|
raw, &good_par_625,
|
|
/* pts */ 0x1234567);
|
|
assert (FALSE == success);
|
|
// XXX Later
|
|
// assert (VBI_ERR_NO_CALLBACK == errno);
|
|
|
|
free (raw);
|
|
free (sliced);
|
|
|
|
vbi_dvb_mux_delete (mx);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_data_identifier_accessors (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
unsigned int di_tested;
|
|
unsigned int i;
|
|
|
|
// Default.
|
|
assert (0x10 == mx.get_data_identifier ());
|
|
|
|
for (i = 0; i < 300; ++i) {
|
|
unsigned int old_di;
|
|
unsigned int new_di;
|
|
vbi_bool success;
|
|
|
|
old_di = 0x1F ^ (i & 0xF);
|
|
mx.set_data_identifier (old_di);
|
|
|
|
success = mx.set_data_identifier (i);
|
|
|
|
// EN 300 775 table 2.
|
|
assert (success == ((i >= 0x10 && i <= 0x1F)
|
|
|| (i >= 0x99 && i <= 0x9B)));
|
|
|
|
new_di = mx.get_data_identifier ();
|
|
|
|
if (success) {
|
|
assert (i == new_di);
|
|
} else {
|
|
// No change.
|
|
assert (old_di == new_di);
|
|
}
|
|
}
|
|
|
|
di_tested = 0;
|
|
|
|
for (i = 0; i < N_ELEMENTS (data_identifiers); ++i) {
|
|
unsigned int di;
|
|
|
|
di = data_identifiers[i];
|
|
if (!mx.set_data_identifier (di))
|
|
continue;
|
|
|
|
di_tested |= 1 << (di >= 0x99);
|
|
|
|
mx.test_pass ();
|
|
}
|
|
|
|
assert (3 == di_tested);
|
|
}
|
|
|
|
static void
|
|
test_mx_packet_size (unsigned int min_size,
|
|
unsigned int max_size)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
uint8_t *buffer;
|
|
vbi_sliced *sliced;
|
|
unsigned int n_lines;
|
|
vbi_bool success;
|
|
|
|
success = mx.set_pes_packet_size (min_size, max_size);
|
|
assert (TRUE == success);
|
|
|
|
buffer = (uint8_t *) xmalloc (max_size);
|
|
alloc_init_sliced (&sliced, &n_lines);
|
|
|
|
if (max_size <= 184)
|
|
n_lines = 1;
|
|
|
|
mx.set_buffer (buffer, max_size);
|
|
mx.set_sliced (sliced, n_lines);
|
|
mx.test_pass ();
|
|
|
|
free (sliced);
|
|
free (buffer);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_packet_size_accessors (void)
|
|
{
|
|
DVBPESMuxTest mx;
|
|
unsigned int min;
|
|
unsigned int max;
|
|
unsigned int i;
|
|
|
|
min = mx.get_min_pes_packet_size ();
|
|
max = mx.get_max_pes_packet_size ();
|
|
|
|
// Defaults.
|
|
assert (184 == min);
|
|
assert (65504 == max);
|
|
|
|
for (i = 0; i < N_ELEMENTS (packet_sizes); ++i) {
|
|
unsigned int j;
|
|
|
|
for (j = 0; j < N_ELEMENTS (packet_sizes); ++j) {
|
|
vbi_bool success;
|
|
|
|
success = mx.set_pes_packet_size (packet_sizes[i],
|
|
packet_sizes[j]);
|
|
assert (TRUE == success);
|
|
|
|
min = mx.get_min_pes_packet_size ();
|
|
max = mx.get_max_pes_packet_size ();
|
|
|
|
assert (0 == min % 184);
|
|
assert (0 == max % 184);
|
|
assert (min >= 184);
|
|
assert (max <= 65504);
|
|
assert (min <= max);
|
|
|
|
if (packet_sizes[i] <= 65504)
|
|
assert (min >= packet_sizes[i]);
|
|
|
|
if (packet_sizes[j] >= min) // sic
|
|
assert (max <= packet_sizes[j]);
|
|
}
|
|
}
|
|
|
|
test_mx_packet_size (184, 184);
|
|
test_mx_packet_size (184, 65504);
|
|
test_mx_packet_size (65504, 65504);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux_new_pid_checks (void)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0x0000; i <= 0x2000; ++i) {
|
|
vbi_dvb_mux *mx;
|
|
|
|
mx = vbi_dvb_ts_mux_new (/* pid */ i,
|
|
/* callback */ NULL,
|
|
/* user_data */ NULL);
|
|
assert ((NULL != mx) == (i >= 0x0010 && i <= 0x1FFE));
|
|
|
|
vbi_dvb_mux_delete (mx);
|
|
mx = (vbi_dvb_mux *) -1;
|
|
}
|
|
|
|
assert (NULL == vbi_dvb_ts_mux_new (0x123456, NULL, NULL));
|
|
assert (NULL == vbi_dvb_ts_mux_new (UINT_MAX, NULL, NULL));
|
|
}
|
|
|
|
static void
|
|
test_dvb_ts_mux_malloc (void)
|
|
{
|
|
vbi_dvb_mux *mx;
|
|
|
|
mx = vbi_dvb_ts_mux_new (/* pid */ 0x1234,
|
|
/* callback */ NULL,
|
|
/* user_data */ NULL);
|
|
assert (ENOMEM == errno);
|
|
assert (NULL == mx);
|
|
}
|
|
|
|
static void
|
|
test_dvb_pes_mux_malloc (void)
|
|
{
|
|
vbi_dvb_mux *mx;
|
|
|
|
mx = vbi_dvb_pes_mux_new (/* callback */ NULL,
|
|
/* user_data */ NULL);
|
|
assert (ENOMEM == errno);
|
|
assert (NULL == mx);
|
|
}
|
|
|
|
static void
|
|
test_dvb_mux (void)
|
|
{
|
|
test_malloc (test_dvb_pes_mux_malloc, /* n_cycles */ 2);
|
|
test_malloc (test_dvb_ts_mux_malloc, /* n_cycles */ 2);
|
|
|
|
test_dvb_mux_new_pid_checks ();
|
|
|
|
test_dvb_mux_packet_size_accessors ();
|
|
test_dvb_mux_data_identifier_accessors ();
|
|
|
|
test_dvb_mux_feed_no_callback_checks ();
|
|
test_dvb_mux_cor_null_packet_checks ();
|
|
test_dvb_mux_cor_null_sliced_checks ();
|
|
test_dvb_mux_cor_packet_overflow_checks ();
|
|
test_dvb_mux_cor_line_order_checks ();
|
|
test_dvb_mux_cor_service_checks ();
|
|
test_dvb_mux_cor_line_number_checks ();
|
|
test_dvb_mux_cor_null_raw_or_sp_checks ();
|
|
test_dvb_mux_cor_sampling_parameter_checks ();
|
|
test_dvb_mux_cor_sp_line_number_checks ();
|
|
|
|
test_dvb_mux_cor_unaligned_packet ();
|
|
test_dvb_mux_cor_unaligned_raw ();
|
|
test_dvb_mux_cor_service_mask ();
|
|
test_dvb_mux_cor_partial_reads_and_reset (/* pid */ 0);
|
|
test_dvb_mux_cor_partial_reads_and_reset (/* pid */ 0x1234);
|
|
test_dvb_mux_cor_pts ();
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
test_multiplex_sliced ();
|
|
test_multiplex_raw ();
|
|
test_dvb_mux ();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
Local variables:
|
|
c-set-style: K&R
|
|
c-basic-offset: 8
|
|
End:
|
|
*/
|