Older/MediaServer/libmpeg/source/mpeg-element-descriptor.c

720 lines
20 KiB
C
Raw Normal View History

2024-10-01 00:12:57 +08:00
// ITU-T H.222.0(06/2012)
// Information technology - Generic coding of moving pictures and associated audio information: Systems
// 2.6 Program and program element descriptors(p83)
#include "mpeg-element-descriptor.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <time.h>
/*
2.6 Program and program element descriptors
2.6.1 Semantic definition of fields in program and program element descriptors
Table 2-45 - Program and program element descriptors
tag TS PS Identification
0 n/a n/a reserved
1 n/a X forbidden
2 X X video_stream_descriptor
3 X X audio_stream_descriptor
4 X X hierarchy_descriptor
5 X X registration_descriptor
6 X X data_stream_alignment_descriptor
7 X X target_background_grid_descriptor
8 X X video_window_descriptor
9 X X CA_descriptor
10 X X ISO_639_language_descriptor
11 X X system_clock_descriptor
12 X X multiplex_buffer_utilization_descriptor
13 X X copyright_descriptor
14 X maximum_bitrate_descriptor
15 X X private_data_indicator_descriptor
16 X X smoothing_buffer_descriptor
17 X STD_descriptor
18 X X IBP_descriptor
19-26 X Defined in ISO/IEC 13818-6
27 X X MPEG-4_video_descriptor
28 X X MPEG-4_audio_descriptor
29 X X IOD_descriptor
30 X SL_descriptor
31 X X FMC_descriptor
32 X X external_ES_ID_descriptor
33 X X MuxCode_descriptor
34 X X FmxBufferSize_descriptor
35 X multiplexbuffer_descriptor
36 X X content_labeling_descriptor
37 X X metadata_pointer_descriptor
38 X X metadata_descriptor
39 X X metadata_STD_descriptor
40 X X AVC video descriptor
41 X X IPMP_descriptor (defined in ISO/IEC 13818-11, MPEG-2 IPMP)
42 X X AVC timing and HRD descriptor
43 X X MPEG-2_AAC_audio_descriptor
44 X X FlexMuxTiming_descriptor
45 X X MPEG-4_text_descriptor
46 X X MPEG-4_audio_extension_descriptor
47 X X auxiliary_video_stream_descriptor
48 X X SVC extension descriptor
49 X X MVC extension descriptor
50 X n/a J2K video descriptor
51 X X MVC operation point descriptor
52 X X MPEG2_stereoscopic_video_format_descriptor
53 X X Stereoscopic_program_info_descriptor
54 X X Stereoscopic_video_info_descriptor
55 X n/a Transport_profile_descriptor
56 X n/a HEVC video descriptor
57-63 n/a n/a Rec. ITU-T H.222.0 | ISO/IEC 13818-1 Reserved
64-255 n/a n/a User Private
*/
int mpeg_elment_descriptor(struct mpeg_bits_t* reader)
{
size_t offset;
uint8_t tag = mpeg_bits_read8(reader);
uint8_t len = mpeg_bits_read8(reader);
if (mpeg_bits_error(reader))
return -1;
offset = mpeg_bits_tell(reader);
switch(tag)
{
case 2:
video_stream_descriptor(reader, len);
break;
case 3:
audio_stream_descriptor(reader, len);
break;
case 4:
hierarchy_descriptor(reader, len);
break;
case 5:
registration_descriptor(reader, len);
break;
case 10:
language_descriptor(reader, len);
break;
case 11:
system_clock_descriptor(reader, len);
break;
case 27:
mpeg4_video_descriptor(reader, len);
break;
case 28:
mpeg4_audio_descriptor(reader, len);
break;
case 37:
metadata_pointer_descriptor(reader, len);
break;
case 38:
metadata_descriptor(reader, len);
break;
case 40:
avc_video_descriptor(reader, len);
break;
case 42:
avc_timing_hrd_descriptor(reader, len);
break;
case 43:
mpeg2_aac_descriptor(reader, len);
break;
case 48:
svc_extension_descriptor(reader, len);
break;
case 49:
mvc_extension_descriptor(reader, len);
break;
case 56:
hevc_video_descriptor(reader, len);
break;
case 57:
vvc_video_descriptor(reader, len);
break;
case 58:
evc_video_descriptor(reader, len);
break;
case 0x40:
clock_extension_descriptor(reader, len);
break;
//default:
// assert(0);
}
mpeg_bits_seek(reader, offset + len); // read all
return mpeg_bits_error(reader) ? -1 : 0;
}
int video_stream_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.2 Video stream descriptor(p85)
uint8_t v;
video_stream_descriptor_t desc;
(void)len; assert(len >= 1);
memset(&desc, 0, sizeof(desc));
v = mpeg_bits_read8(reader);
desc.multiple_frame_rate_flag = (v >> 7) & 0x01;
desc.frame_rate_code = (v >> 3) & 0x0F;
desc.MPEG_1_only_flag = (v >> 2) & 0x01;
desc.constrained_parameter_flag = (v >> 1) & 0x01;
desc.still_picture_flag = v & 0x01;
if(0 == desc.MPEG_1_only_flag)
{
desc.profile_and_level_indication = mpeg_bits_read8(reader);
v = mpeg_bits_read8(reader);
desc.chroma_format = (v >> 6) & 0x03;
desc.frame_rate_code = (v >> 5) & 0x01;
assert((0x1F & v) == 0x00); // 'xxx00000'
}
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int audio_stream_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.4 Audio stream descriptor(p86)
uint8_t v;
audio_stream_descriptor_t desc;
(void)len; assert(len >= 1);
v = mpeg_bits_read8(reader);
memset(&desc, 0, sizeof(desc));
desc.free_format_flag = (v >> 7) & 0x01;
desc.ID = (v >> 6) & 0x01;
desc.layer = (v >> 4) & 0x03;
desc.variable_rate_audio_indicator = (v >> 3) & 0x01;
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int hierarchy_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.6 Hierarchy descriptor(p86)
uint8_t v;
hierarchy_descriptor_t desc;
(void)len; assert(len >= 4);
v = mpeg_bits_read8(reader);
memset(&desc, 0, sizeof(desc));
desc.no_view_scalability_flag = (v >> 7) & 0x01;
desc.no_temporal_scalability_flag = (v >> 6) & 0x01;
desc.no_spatial_scalability_flag = (v >> 5) & 0x01;
desc.no_quality_scalability_flag = (v >> 4) & 0x01;
desc.hierarchy_type = v & 0x0F;
desc.hierarchy_layer_index = mpeg_bits_read8(reader) & 0x3F;
v = mpeg_bits_read8(reader);
desc.tref_present_flag = (v >> 7) & 0x01;
desc.hierarchy_embedded_layer_index = v & 0x3F;
desc.hierarchy_channel = mpeg_bits_read8(reader) & 0x3F;
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int registration_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.8 Registration descriptor(p94)
size_t fourcc;
(void)len; assert(len >= 4);
fourcc = mpeg_bits_read32(reader);
(void)fourcc;
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int language_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.18 ISO 639 language descriptor(p92)
uint8_t i;
uint32_t v;
for (i = 0; i + 4 < len; i += 4)
{
language_descriptor_t desc;
memset(&desc, 0, sizeof(desc));
v = mpeg_bits_read32(reader);
desc.code = v >> 8;
desc.audio = v & 0xFF;
}
return mpeg_bits_error(reader) ? -1 : 0;
}
int system_clock_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.20 System clock descriptor(p92)
uint8_t v;
system_clock_descriptor_t desc;
(void)len; assert(len >= 2);
v = mpeg_bits_read8(reader);
memset(&desc, 0, sizeof(desc));
desc.external_clock_reference_indicator = (v >> 7) & 0x01;
desc.clock_accuracy_integer = v & 0x3F;
desc.clock_accuracy_exponent = (mpeg_bits_read8(reader) >> 5) & 0x07;
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int mpeg4_video_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.36 MPEG-4 video descriptor(p96)
mpeg4_video_descriptor_t desc;
(void)len; assert(len >= 1);
memset(&desc, 0, sizeof(desc));
desc.visual_profile_and_level = mpeg_bits_read8(reader);
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int mpeg4_audio_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.38 MPEG-4 audio descriptor(p97)
mpeg4_audio_descriptor_t desc;
(void)len; assert(len >= 1);
memset(&desc, 0, sizeof(desc));
desc.profile_and_level = mpeg_bits_read8(reader);
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int metadata_pointer_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.58 Metadata pointer descriptor(p112)
uint8_t flags;
metadata_pointer_descriptor_t desc;
(void)len; assert(len >= 5);
desc.metadata_application_format_identifier = mpeg_bits_read16(reader);
if (0xFFFF == desc.metadata_application_format_identifier)
desc.metadata_application_format_identifier = mpeg_bits_read32(reader);
desc.metadata_format_identifier = mpeg_bits_read8(reader);
if (0xFF == desc.metadata_format_identifier)
desc.metadata_format_identifier = mpeg_bits_read32(reader);
desc.metadata_service_id = mpeg_bits_read8(reader);
flags = mpeg_bits_read8(reader);
desc.MPEG_carriage_flags = (flags >> 5) & 0x03;
if (flags & 0x80) // metadata_locator_record_flag
{
desc.metadata_locator_record_length = mpeg_bits_read8(reader);
mpeg_bits_skip(reader, desc.metadata_locator_record_length); // metadata_locator_record_byte
}
if (desc.MPEG_carriage_flags <= 2)
desc.program_number = mpeg_bits_read16(reader);
if (1 == desc.MPEG_carriage_flags)
{
desc.transport_stream_location = mpeg_bits_read16(reader);
desc.transport_stream_id = mpeg_bits_read16(reader);
}
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int metadata_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.60 Metadata descriptor(p115)
uint8_t flags;
metadata_descriptor_t desc;
(void)len; assert(len >= 5);
desc.metadata_application_format_identifier = mpeg_bits_read16(reader);
if (0xFFFF == desc.metadata_application_format_identifier)
desc.metadata_application_format_identifier = mpeg_bits_read32(reader);
desc.metadata_format_identifier = mpeg_bits_read8(reader);
if (0xFF == desc.metadata_format_identifier)
desc.metadata_format_identifier = mpeg_bits_read32(reader);
desc.metadata_service_id = mpeg_bits_read8(reader);
flags = mpeg_bits_read8(reader);
desc.decoder_config_flags = (flags >> 5) & 0x07;
if (flags & 0x10) // DSM-CC_flag
{
desc.service_identification_length = mpeg_bits_read8(reader);
mpeg_bits_skip(reader, desc.service_identification_length); // service_identification_record_byte
}
if (0x01 == desc.decoder_config_flags)
{
desc.decoder_config_length = mpeg_bits_read8(reader);
mpeg_bits_skip(reader, desc.decoder_config_length); // decoder_config_byte
}
else if (0x03 == desc.decoder_config_flags)
{
desc.dec_config_identification_record_length = mpeg_bits_read8(reader);
mpeg_bits_skip(reader, desc.dec_config_identification_record_length); // dec_config_identification_record_byte
}
else if (0x04 == desc.decoder_config_flags)
{
desc.decoder_config_metadata_service_id = mpeg_bits_read8(reader);
}
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int avc_video_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.64 AVC video descriptor(p110)
uint8_t v;
avc_video_descriptor_t desc;
(void)len; assert(len >= 4);
memset(&desc, 0, sizeof(desc));
desc.profile_idc = mpeg_bits_read8(reader);
v = mpeg_bits_read8(reader);
desc.constraint_set0_flag = (v >> 7) & 0x01;
desc.constraint_set1_flag = (v >> 6) & 0x01;
desc.constraint_set2_flag = (v >> 5) & 0x01;
desc.constraint_set3_flag = (v >> 4) & 0x01;
desc.constraint_set4_flag = (v >> 3) & 0x01;
desc.constraint_set5_flag = (v >> 2) & 0x01;
desc.AVC_compatible_flags = v & 0x03;
desc.level_idc = mpeg_bits_read8(reader);
v = mpeg_bits_read8(reader);
desc.AVC_still_present = (v >> 7) & 0x01;
desc.AVC_24_hour_picture_flag = (v >> 6) & 0x01;
desc.frame_packing_SEI_not_present_flag = (v >> 5) & 0x01;
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int avc_timing_hrd_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.66 AVC timing and HRD descriptor(p112)
uint8_t v;
avc_timing_hrd_descriptor_t desc;
(void)len; assert(len >= 2);
memset(&desc, 0, sizeof(desc));
v = mpeg_bits_read8(reader);
desc.hrd_management_valid_flag = (v >> 7) & 0x01;
desc.picture_and_timing_info_present = (v >> 0) & 0x01;
if(desc.picture_and_timing_info_present)
{
v = mpeg_bits_read8(reader);
desc._90kHZ_flag = (v >> 7) & 0x01;
if(0 == desc._90kHZ_flag)
{
desc.N = mpeg_bits_read32(reader);
desc.K = mpeg_bits_read32(reader);
}
desc.num_unit_in_tick = mpeg_bits_read32(reader);
}
v = mpeg_bits_read8(reader);
desc.fixed_frame_rate_flag = (v >> 7) & 0x01;
desc.temporal_poc_flag = (v >> 6) & 0x01;
desc.picture_to_display_conversion_flag = (v >> 5) & 0x01;
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int mpeg2_aac_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.68 MPEG-2 AAC audio descriptor(p113)
mpeg2_aac_descriptor_t desc;
(void)len; assert(len >= 3);
memset(&desc, 0, sizeof(desc));
desc.profile = mpeg_bits_read8(reader);
desc.channel_configuration = mpeg_bits_read8(reader);
desc.additional_information = mpeg_bits_read8(reader);
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int svc_extension_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.76 SVC extension descriptor(p116)
uint8_t v;
svc_extension_descriptor_t desc;
(void)len; assert(len >= 13);
memset(&desc, 0, sizeof(desc));
desc.width = mpeg_bits_read16(reader);
desc.height = mpeg_bits_read16(reader);
desc.frame_rate = mpeg_bits_read16(reader);
desc.average_bitrate = mpeg_bits_read16(reader);
desc.maximum_bitrate = mpeg_bits_read16(reader);
desc.dependency_id = (mpeg_bits_read8(reader) >> 5) & 0x07;
v = mpeg_bits_read8(reader);
desc.quality_id_start = (v >> 4) & 0x0F;
desc.quality_id_end = (v >> 0) & 0x0F;
v = mpeg_bits_read8(reader);
desc.temporal_id_start = (v >> 5) & 0x07;
desc.temporal_id_end = (v >> 2) & 0x07;
desc.no_sei_nal_unit_present = (v >> 1) & 0x01;
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int mvc_extension_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.78 MVC extension descriptor(p117)
uint32_t v;
mvc_extension_descriptor_t desc;
(void)len; assert(len >= 8);
memset(&desc, 0, sizeof(desc));
desc.average_bit_rate = mpeg_bits_read16(reader);
desc.maximum_bitrate = mpeg_bits_read16(reader);
v = mpeg_bits_read32(reader);
desc.view_order_index_min = (v >> 18) & 0x3FF;
desc.view_order_index_max = (v >> 8) & 0x3FF;
desc.temporal_id_start = (v >> 5) & 0x07;
desc.temporal_id_end = (v >> 2) & 0x07;
desc.no_sei_nal_unit_present = (v >> 1) & 0x01;
desc.no_prefix_nal_unit_present = (v >> 0) & 0x01;
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int hevc_video_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.95 HEVC video descriptor(p146)
uint64_t v;
hevc_video_descriptor_t desc;
(void)len; assert(len >= 13);
memset(&desc, 0, sizeof(desc));
v = mpeg_bits_read8(reader);
desc.profile_space = (v >> 6) & 0x03;
desc.tier_flag = (v >> 5) & 0x01;
desc.profile_idc = (v >> 0) & 0x1F;
desc.profile_compatibility_indication = mpeg_bits_read32(reader);
v = mpeg_bits_read64(reader);
desc.progressive_source_flag = (v >> 63) & 0x01;
desc.interlaced_source_flag = (v >> 62) & 0x01;
desc.non_packed_constraint_flag = (v >> 61) & 0x01;
desc.frame_only_constraint_flag = (v >> 60) & 0x01;
desc.copied_44bits = (v >> 16) & 0xFFFFFFFFFFFULL;
desc.level_idc = (v >> 8) & 0xFF;
desc.temporal_layer_subset_flag = (v >> 7) & 0x01;
desc.HEVC_still_present_flag = (v >> 6) & 0x01;
desc.HEVC_24hr_picture_present_flag = (v >> 5) & 0x01;
desc.sub_pic_hrd_params_not_present_flag = (v >> 4) & 0x01;
desc.HDR_WCG_idc = v & 0x03;
if (desc.temporal_layer_subset_flag) {
v = mpeg_bits_read8(reader);
desc.temporal_id_min = (v >> 5) & 0x07;
v = mpeg_bits_read8(reader);
desc.temporal_id_max = (v >> 5) & 0x07;
}
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int vvc_video_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.129 VVC video descriptor(p172)
int i;
uint8_t v;
vvc_video_descriptor_t desc;
(void)len; assert(len >= 6);
memset(&desc, 0, sizeof(desc));
v = mpeg_bits_read8(reader);
desc.profile_idc = (v >> 1) & 0x7F;
desc.tier_flag = v & 0x01;
desc.num_sub_profiles = mpeg_bits_read8(reader);
for(i = 0; i < desc.num_sub_profiles && i < sizeof(desc.sub_profile_idc)/sizeof(desc.sub_profile_idc[0]); i++)
desc.sub_profile_idc[i] = mpeg_bits_read32(reader);
v = mpeg_bits_read8(reader);
desc.progressive_source_flag = (v >> 7) & 0x01;
desc.interlaced_source_flag = (v >> 6) & 0x01;
desc.non_packed_constraint_flag = (v >> 5) & 0x01;
desc.frame_only_constraint_flag = (v >> 4) & 0x01;
desc.reserved_zero_4bits = (v >> 0) & 0x0F;
desc.level_idc = mpeg_bits_read8(reader);
v = mpeg_bits_read8(reader);
desc.temporal_layer_subset_flag = (v >> 7) & 0x01;
desc.VVC_still_present_flag = (v >> 6) & 0x01;
desc.VVC_24hr_picture_present_flag = (v >> 5) & 0x01;
v = mpeg_bits_read8(reader);
desc.HDR_WCG_idc = (v >> 6) & 0x03;
desc.video_properties_tag = v & 0x0F;
if (desc.temporal_layer_subset_flag) {
v = mpeg_bits_read8(reader);
desc.temporal_id_min = v & 0x07;
v = mpeg_bits_read8(reader);
desc.temporal_id_max = v & 0x07;
}
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
int evc_video_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
// 2.6.133 EVC video descriptor(p176)
uint8_t v;
evc_video_descriptor_t desc;
(void)len; assert(len >= 6);
memset(&desc, 0, sizeof(desc));
desc.profile_idc = mpeg_bits_read8(reader);
desc.level_idc = mpeg_bits_read8(reader);
desc.toolset_idc_h = mpeg_bits_read32(reader);
desc.toolset_idc_l = mpeg_bits_read32(reader);
v = mpeg_bits_read8(reader);
desc.progressive_source_flag = (v >> 7) & 0x01;
desc.interlaced_source_flag = (v >> 6) & 0x01;
desc.non_packed_constraint_flag = (v >> 5) & 0x01;
desc.frame_only_constraint_flag = (v >> 4) & 0x01;
desc.reserved = (v >> 3) & 0x01;
desc.temporal_layer_subset_flag = (v >> 2) & 0x01;
desc.EVC_still_present_flag = (v >> 1) & 0x01;
desc.EVC_24hr_picture_present_flag = (v >> 0) & 0x01;
v = mpeg_bits_read8(reader);
desc.HDR_WCG_idc = (v >> 6) & 0x03;
desc.video_properties_tag = v & 0x0F;
if (desc.temporal_layer_subset_flag) {
v = mpeg_bits_read8(reader);
desc.temporal_id_min = v & 0x07;
v = mpeg_bits_read8(reader);
desc.temporal_id_max = v & 0x07;
}
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
size_t service_extension_descriptor_write(uint8_t* data, size_t bytes)
{
uint8_t n;
n = (uint8_t)strlen(SERVICE_NAME);
if (bytes < 2 + n)
return 0;
data[0] = SERVICE_ID;
data[1] = n;
memcpy(data + 2, SERVICE_NAME, n);
return 2 + n;
}
typedef struct _clock_extension_descriptor_t
{
uint8_t year; // base 2000, 8-bit
uint8_t month; // 1-12, 4-bit
uint8_t day; // 1-31, 5-bit
uint8_t hour; // 0-23, 5-bit
uint8_t minute; // 0-59, 6-bit
uint8_t second; // 0-59, 6-bit
uint16_t microsecond; // 14-bit
} clock_extension_descriptor_t;
int clock_extension_descriptor(struct mpeg_bits_t* reader, uint8_t len)
{
uint32_t v;
struct tm t;
time_t clock;
(void)len; assert(len >= 9);
v = mpeg_bits_read32(reader); // skip 4-bytes leading
memset(&t, 0, sizeof(t));
t.tm_year = mpeg_bits_read8(reader) + 2000 - 1900;
v = mpeg_bits_read32(reader);
t.tm_mon = ((v >> 28) & 0x0F) - 1;
t.tm_mday = (v >> 23) & 0x1F;
t.tm_hour = (v >> 18) & 0x1F;
t.tm_min = (v >> 12) & 0x3F;
t.tm_sec = (v >> 6) & 0x3F;
//desc.microsecond = v & 0x3F;
clock = mktime(&t) * 1000;
assert(0 == mpeg_bits_error(reader));
return mpeg_bits_error(reader) ? -1 : 0;
}
size_t clock_extension_descriptor_write(uint8_t* data, size_t bytes, int64_t clock)
{
struct tm* t;
time_t seconds;
if (bytes < 16)
return 0;
seconds = (time_t)(clock / 1000);
t = localtime(&seconds);
data[0] = 0x40;
data[1] = 0x0E;
data[2] = 0x48;
data[3] = 0x4B;
data[4] = 0x01;
data[5] = 0x00;
data[6] = (uint8_t)(t->tm_year + 1900 - 2000); // base 2000
data[7] = (uint8_t)((t->tm_mon + 1) << 4) | ((t->tm_mday >> 1) & 0x0F);
data[8] = (uint8_t)((t->tm_mday & 0x01) << 7) | ((t->tm_hour & 0x1F) << 2) | ((t->tm_min >> 4) & 0x03);
data[9] = (uint8_t)((t->tm_min & 0x0F) << 4) | ((t->tm_sec >> 2) & 0x0F);
data[10] = (uint8_t)((t->tm_sec & 0x03) << 6);
data[11] = 0x00;
data[12] = 0x00;
data[13] = 0xFF;
data[14] = 0xFF;
data[15] = 0xFF;
return 16;
}