Commit bba83369 authored by Georgi Chorbadzhiyski's avatar Georgi Chorbadzhiyski

mpeg/psi: Add support for descriptor 0x21 (MuxCode descriptor).

parent 5e4e0888
......@@ -85,6 +85,7 @@ Supported MPEG descriptors
* Descriptor 0x1e: SL_descriptor
* Descriptor 0x1f: FMC_descriptor
* Descriptor 0x20: External ES_ID descriptor
* Descriptor 0x21: MuxCode descriptor
* Descriptor 0x23: MultiplexBuffer descriptor
* Descriptor 0x27: Metadata STD descriptor
* Descriptor 0x28: AVC video descriptor
......
......@@ -2,7 +2,6 @@ TODO items for biTStream. The items are not ordered by importance
so if you like something just do it and send a patch.
- Add support (parser, generator, example) for these MPEG descriptors:
- Descriptor 0x21 MuxCode_descriptor
- Descriptor 0x22 FmxBufferSize_descriptor
- Descriptor 0x24 content_labeling_descriptor
- Descriptor 0x25 metadata_pointer_descriptor
......
......@@ -281,6 +281,90 @@ static void build_desc20(uint8_t *desc) {
desc20_set_external_es_id(desc, 0x1234);
}
/* MPEG Descriptor 0x21: MuxCode descriptor */
static void build_desc21(uint8_t *desc) {
uint8_t n = 0, k = 0, r;
uint8_t *entry_n, *entry_k;
desc21_init(desc);
desc_set_length(desc, 255);
entry_n = desc21_get_entry(desc, n++);
desc21n_set_muxcode(entry_n, 1);
desc21n_set_version(entry_n, 1);
desc21n_set_length(entry_n, DESC21_ENTRY_HEADER_SIZE - 1);
desc21n_set_substruct_count(entry_n, 0);
entry_n = desc21_get_entry(desc, n++);
desc21n_set_muxcode(entry_n, 2);
desc21n_set_version(entry_n, 2);
desc21n_set_length(entry_n, 255);
desc21n_set_substruct_count(entry_n, 255);
{
k = 0;
entry_k = desc21n_get_substruct(entry_n, k++);
desc21k_set_repetition_count(entry_k, 1);
desc21k_set_slot_count(entry_k, 0);
entry_k = desc21n_get_substruct(entry_n, k++);
desc21k_set_repetition_count(entry_k, 5);
desc21k_set_slot_count(entry_k, 5);
for (r=0; r<desc21k_get_slot_count(entry_k); r++) {
desc21k_set_flex_mux_channel(entry_k, r, r + 10);
desc21k_set_number_of_bytes(entry_k, r, r + 20);
}
entry_k = desc21n_get_substruct(entry_n, k++);
desc21k_set_repetition_count(entry_k, 3);
desc21k_set_slot_count(entry_k, 1);
for (r=0; r<desc21k_get_slot_count(entry_k); r++) {
desc21k_set_flex_mux_channel(entry_k, r, r + 30);
desc21k_set_number_of_bytes(entry_k, r, r + 40);
}
entry_k = desc21n_get_substruct(entry_n, k);
desc21n_set_length(entry_n, entry_k - entry_n - 1);
desc21n_set_substruct_count(entry_n, k);
}
entry_n = desc21_get_entry(desc, n++);
desc21n_set_muxcode(entry_n, 3);
desc21n_set_version(entry_n, 3);
desc21n_set_length(entry_n, DESC21_ENTRY_HEADER_SIZE - 1);
desc21n_set_substruct_count(entry_n, 0);
entry_n = desc21_get_entry(desc, n++);
desc21n_set_muxcode(entry_n, 4);
desc21n_set_version(entry_n, 4);
desc21n_set_length(entry_n, 255);
desc21n_set_substruct_count(entry_n, 255);
{
k = 0;
entry_k = desc21n_get_substruct(entry_n, k++);
desc21k_set_repetition_count(entry_k, 3);
desc21k_set_slot_count(entry_k, 2);
for (r=0; r<desc21k_get_slot_count(entry_k); r++) {
desc21k_set_flex_mux_channel(entry_k, r, r + 50);
desc21k_set_number_of_bytes(entry_k, r, r + 60);
}
entry_k = desc21n_get_substruct(entry_n, k++);
desc21k_set_repetition_count(entry_k, 4);
desc21k_set_slot_count(entry_k, 4);
for (r=0; r<desc21k_get_slot_count(entry_k); r++) {
desc21k_set_flex_mux_channel(entry_k, r, r + 70);
desc21k_set_number_of_bytes(entry_k, r, r + 80);
}
entry_k = desc21n_get_substruct(entry_n, k);
desc21n_set_length(entry_n, entry_k - entry_n - 1);
desc21n_set_substruct_count(entry_n, k);
}
entry_n = desc21_get_entry(desc, n);
desc_set_length(desc, entry_n - desc - DESC_HEADER_SIZE);
}
/* MPEG Descriptor 0x23: MultiplexBuffer descriptor */
static void build_desc23(uint8_t *desc) {
desc23_init(desc);
......@@ -2427,6 +2511,9 @@ static void generate_pmt(void) {
desc = descs_get_desc(desc_loop, desc_counter++);
build_desc20(desc);
desc = descs_get_desc(desc_loop, desc_counter++);
build_desc21(desc);
desc = descs_get_desc(desc_loop, desc_counter++);
build_desc23(desc);
......
......@@ -269,6 +269,28 @@ new PMT program=20000 version=1 pcrpid=110
- desc 1f fmc es_id=0x4455 flexmux_channel=0x66
- desc 1f fmc es_id=0x7788 flexmux_channel=0x99
- desc 20 external_es_id external_es_id=0x1234
- desc 21 muxcode
- muxcode_entry length=2 muxcode=1 version=1 substruct_count=0
- muxcode_entry length=17 muxcode=2 version=2 substruct_count=3
- muxcode_substruct slot_count=0 repetition_count=1
- muxcode_substruct slot_count=5 repetition_count=5
- muxcode_substruct_entry slot=0 flex_mux_channel=10 number_of_bytes=20
- muxcode_substruct_entry slot=1 flex_mux_channel=11 number_of_bytes=21
- muxcode_substruct_entry slot=2 flex_mux_channel=12 number_of_bytes=22
- muxcode_substruct_entry slot=3 flex_mux_channel=13 number_of_bytes=23
- muxcode_substruct_entry slot=4 flex_mux_channel=14 number_of_bytes=24
- muxcode_substruct slot_count=1 repetition_count=3
- muxcode_substruct_entry slot=0 flex_mux_channel=30 number_of_bytes=40
- muxcode_entry length=2 muxcode=3 version=3 substruct_count=0
- muxcode_entry length=16 muxcode=4 version=4 substruct_count=2
- muxcode_substruct slot_count=2 repetition_count=3
- muxcode_substruct_entry slot=0 flex_mux_channel=50 number_of_bytes=60
- muxcode_substruct_entry slot=1 flex_mux_channel=51 number_of_bytes=61
- muxcode_substruct slot_count=4 repetition_count=4
- muxcode_substruct_entry slot=0 flex_mux_channel=70 number_of_bytes=80
- muxcode_substruct_entry slot=1 flex_mux_channel=71 number_of_bytes=81
- muxcode_substruct_entry slot=2 flex_mux_channel=72 number_of_bytes=82
- muxcode_substruct_entry slot=3 flex_mux_channel=73 number_of_bytes=83
- desc 23 multiplex_buffer mb_buffer_size=112233 tb_leak_rate=445566
- desc 27 metadata_std input_leak_rate=12345 buffer_size=23456 output_leak_rate=34567
- desc 2c flexmux_timing fcr_es_id=0x1234 fcr_resolution=123456789 fcr_length=55 fmx_rate_length=66
......
......@@ -483,6 +483,40 @@
<DESC id="0x20" length="2" value="1234">
<EXTERNAL_ES_ID_DESC external_es_id="0x1234"/>
</DESC>
<DESC id="0x21" length="41" value="021100112203012d0a140b150c160d170e180b1e2802330010440213323c333d244650475148524953">
<MUXCODE_DESC>
<MUXCODE_ENTRY length="2" muxcode="1" version="1" substruct_count="0">
</MUXCODE_ENTRY>
<MUXCODE_ENTRY length="17" muxcode="2" version="2" substruct_count="3">
<MUXCODE_SUBSTRUCT slot_count="0" repetition_count="1">
</MUXCODE_SUBSTRUCT>
<MUXCODE_SUBSTRUCT slot_count="5" repetition_count="5">
<MUXCODE_SUBSTRUCT_ENTRY slot="0" flex_mux_channel="10" number_of_bytes="20"/>
<MUXCODE_SUBSTRUCT_ENTRY slot="1" flex_mux_channel="11" number_of_bytes="21"/>
<MUXCODE_SUBSTRUCT_ENTRY slot="2" flex_mux_channel="12" number_of_bytes="22"/>
<MUXCODE_SUBSTRUCT_ENTRY slot="3" flex_mux_channel="13" number_of_bytes="23"/>
<MUXCODE_SUBSTRUCT_ENTRY slot="4" flex_mux_channel="14" number_of_bytes="24"/>
</MUXCODE_SUBSTRUCT>
<MUXCODE_SUBSTRUCT slot_count="1" repetition_count="3">
<MUXCODE_SUBSTRUCT_ENTRY slot="0" flex_mux_channel="30" number_of_bytes="40"/>
</MUXCODE_SUBSTRUCT>
</MUXCODE_ENTRY>
<MUXCODE_ENTRY length="2" muxcode="3" version="3" substruct_count="0">
</MUXCODE_ENTRY>
<MUXCODE_ENTRY length="16" muxcode="4" version="4" substruct_count="2">
<MUXCODE_SUBSTRUCT slot_count="2" repetition_count="3">
<MUXCODE_SUBSTRUCT_ENTRY slot="0" flex_mux_channel="50" number_of_bytes="60"/>
<MUXCODE_SUBSTRUCT_ENTRY slot="1" flex_mux_channel="51" number_of_bytes="61"/>
</MUXCODE_SUBSTRUCT>
<MUXCODE_SUBSTRUCT slot_count="4" repetition_count="4">
<MUXCODE_SUBSTRUCT_ENTRY slot="0" flex_mux_channel="70" number_of_bytes="80"/>
<MUXCODE_SUBSTRUCT_ENTRY slot="1" flex_mux_channel="71" number_of_bytes="81"/>
<MUXCODE_SUBSTRUCT_ENTRY slot="2" flex_mux_channel="72" number_of_bytes="82"/>
<MUXCODE_SUBSTRUCT_ENTRY slot="3" flex_mux_channel="73" number_of_bytes="83"/>
</MUXCODE_SUBSTRUCT>
</MUXCODE_ENTRY>
</MUXCODE_DESC>
</DESC>
<DESC id="0x23" length="6" value="01b66906cc7e">
<MULTIPLEX_BUFFER_DESC mb_buffer_size="112233" tb_leak_rate="445566"/>
</DESC>
......
/*****************************************************************************
* desc_21.h: ISO/IEC 13818-1 Descriptor 0x21 (Muxcode descriptor)
*****************************************************************************
* Copyright (C) 2021 Unix Solutions Ltd.
*
* Authors: Georgi Chorbadzhiyski <georgi@unixsol.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*****************************************************************************/
/*
* Normative references:
* - ISO/IEC 13818-1:2007(E) (MPEG-2 Systems)
* - ISO/IEC 14496-1:2001(E) (MPEG-4 Systems)
*/
#ifndef __BITSTREAM_MPEG_DESC_21_H__
#define __BITSTREAM_MPEG_DESC_21_H__
#include <bitstream/common.h>
#include <bitstream/mpeg/psi/descriptors.h>
#ifdef __cplusplus
extern "C"
{
#endif
/*****************************************************************************
* Descriptor 0x21: Muxcode descriptor
*****************************************************************************/
#define DESC21_HEADER_SIZE DESC_HEADER_SIZE
#define DESC21_ENTRY_HEADER_SIZE 3
#define DESC21_SUBSTRUCT_HEADER_SIZE 1
static inline void desc21_init(uint8_t *p_desc)
{
desc_set_tag(p_desc, 0x21);
}
static inline uint8_t desc21n_get_length(const uint8_t *p_desc_n)
{
return p_desc_n[0];
}
static inline void desc21n_set_length(uint8_t *p_desc_n, uint8_t i_length)
{
p_desc_n[0] = i_length;
}
static inline uint8_t desc21n_get_muxcode(const uint8_t *p_desc_n)
{
return (p_desc_n[1] & 0xf0) >> 4;
}
static inline void desc21n_set_muxcode(uint8_t *p_desc_n, uint8_t i_muxcode)
{
p_desc_n[1] = (i_muxcode << 4) | (p_desc_n[1] & 0x0f);
}
static inline uint8_t desc21n_get_version(const uint8_t *p_desc_n)
{
return p_desc_n[1] & 0x0f;
}
static inline void desc21n_set_version(uint8_t *p_desc_n, uint8_t i_version)
{
p_desc_n[1] = (p_desc_n[1] & 0xf0) | (i_version & 0x0f);
}
static inline uint8_t desc21n_get_substruct_count(const uint8_t *p_desc_n)
{
return p_desc_n[2];
}
static inline void desc21n_set_substruct_count(uint8_t *p_desc_n, uint8_t i_substruct_count)
{
p_desc_n[2] = i_substruct_count;
}
static inline uint8_t *desc21_get_entry(const uint8_t *p_desc, uint8_t n)
{
const uint8_t *p_desc_n = p_desc + DESC21_HEADER_SIZE;
uint8_t i_desc_size = desc_get_length(p_desc);
while (n) {
if (p_desc_n + desc21n_get_length(p_desc_n) - p_desc > i_desc_size)
return NULL;
p_desc_n += 1 + desc21n_get_length(p_desc_n);
n--;
}
if (p_desc_n - p_desc > i_desc_size)
return NULL;
return (uint8_t *)p_desc_n;
}
static inline uint8_t desc21k_get_slot_count(const uint8_t *p_desc_k)
{
return p_desc_k[0] >> 3;
}
static inline void desc21k_set_slot_count(uint8_t *p_desc_k, uint8_t i_slot_count)
{
p_desc_k[0] = (i_slot_count << 3) | (p_desc_k[0] & 0x07);
}
static inline uint8_t desc21k_get_repetition_count(const uint8_t *p_desc_k)
{
return p_desc_k[0] & 0x07;
}
static inline void desc21k_set_repetition_count(uint8_t *p_desc_k, uint8_t i_repetition_count)
{
p_desc_k[0] = (p_desc_k[0] & 0xf8) | (i_repetition_count & 0x07);
}
static inline uint8_t desc21k_get_flex_mux_channel(const uint8_t *p_desc_k, uint8_t i_index)
{
return p_desc_k[DESC21_SUBSTRUCT_HEADER_SIZE + i_index * 2];
}
static inline void desc21k_set_flex_mux_channel(uint8_t *p_desc_k, uint8_t i_index, uint8_t i_flex_mux_channel)
{
p_desc_k[DESC21_SUBSTRUCT_HEADER_SIZE + i_index * 2] = i_flex_mux_channel;
}
static inline uint8_t desc21k_get_number_of_bytes(const uint8_t *p_desc_k, uint8_t i_index)
{
return p_desc_k[DESC21_SUBSTRUCT_HEADER_SIZE + i_index * 2 + 1];
}
static inline void desc21k_set_number_of_bytes(uint8_t *p_desc_k, uint8_t i_index, uint8_t i_number_of_bytes)
{
p_desc_k[DESC21_SUBSTRUCT_HEADER_SIZE + i_index * 2 + 1] = i_number_of_bytes;
}
static inline uint8_t *desc21n_get_substruct(const uint8_t *p_desc_n, uint8_t k)
{
const uint8_t *p_desc_k = p_desc_n + DESC21_ENTRY_HEADER_SIZE;
uint8_t i_entry_size = desc21n_get_length(p_desc_n);
if (desc21n_get_substruct_count(p_desc_n) == 0)
return NULL;
if (k > desc21n_get_substruct_count(p_desc_n) - 1)
return NULL;
while (k) {
if (p_desc_k - p_desc_n > i_entry_size)
return NULL;
p_desc_k += DESC21_SUBSTRUCT_HEADER_SIZE + (2 * desc21k_get_slot_count(p_desc_k));
k--;
}
if (p_desc_n - p_desc_k > i_entry_size)
return NULL;
return (uint8_t *)p_desc_k;
}
static inline bool desc21_validate(const uint8_t *p_desc)
{
uint8_t j = 0;
uint8_t *p_desc_n;
int i_desc_length = desc_get_length(p_desc);
while ((p_desc_n = desc21_get_entry(p_desc, j++)) != NULL) {
int i_calc_entry_length = DESC21_ENTRY_HEADER_SIZE - 1;
uint8_t *p_desc_k;
uint8_t k = 0;
while ((p_desc_k = desc21n_get_substruct(p_desc_n, k++)) != NULL) {
i_calc_entry_length += DESC21_SUBSTRUCT_HEADER_SIZE + (2 * desc21k_get_slot_count(p_desc_k));
}
if (i_calc_entry_length != desc21n_get_length(p_desc_n))
return false;
i_desc_length -= desc21n_get_length(p_desc_n);
}
return i_desc_length >= 0;
}
static inline void desc21_print(const uint8_t *p_desc, f_print pf_print,
void *opaque, print_type_t i_print_type)
{
const uint8_t *p_desc_n;
uint8_t n = 0;
switch (i_print_type) {
case PRINT_XML:
pf_print(opaque, "<MUXCODE_DESC>");
break;
default:
pf_print(opaque, " - desc 21 muxcode");
}
while ((p_desc_n = desc21_get_entry(p_desc, n++)) != NULL) {
const uint8_t *p_desc_k;
uint8_t k = 0;
switch (i_print_type) {
case PRINT_XML:
pf_print(opaque,
"<MUXCODE_ENTRY length=\"%u\" muxcode=\"%u\""
" version=\"%u\" substruct_count=\"%u\">",
desc21n_get_length(p_desc_n),
desc21n_get_muxcode(p_desc_n),
desc21n_get_version(p_desc_n),
desc21n_get_substruct_count(p_desc_n)
);
break;
default:
pf_print(opaque,
" - muxcode_entry length=%u muxcode=%u"
" version=%u substruct_count=%u",
desc21n_get_length(p_desc_n),
desc21n_get_muxcode(p_desc_n),
desc21n_get_version(p_desc_n),
desc21n_get_substruct_count(p_desc_n)
);
}
while ((p_desc_k = desc21n_get_substruct(p_desc_n, k++)) != NULL) {
uint8_t i_slot_count = desc21k_get_slot_count(p_desc_k);
uint8_t i_repetition_count = desc21k_get_repetition_count(p_desc_k);
uint8_t r;
switch (i_print_type) {
case PRINT_XML:
pf_print(opaque,
"<MUXCODE_SUBSTRUCT slot_count=\"%u\" repetition_count=\"%u\">",
i_slot_count, i_repetition_count);
break;
default:
pf_print(opaque,
" - muxcode_substruct slot_count=%u repetition_count=%u",
i_slot_count, i_repetition_count);
}
for (r = 0; r < i_slot_count; r++) {
uint8_t i_flex_mux_channel = desc21k_get_flex_mux_channel(p_desc_k, r);
uint8_t i_number_of_bytes = desc21k_get_number_of_bytes(p_desc_k, r);
switch (i_print_type) {
case PRINT_XML:
pf_print(opaque,
"<MUXCODE_SUBSTRUCT_ENTRY slot=\"%u\" flex_mux_channel=\"%u\" number_of_bytes=\"%u\"/>",
r, i_flex_mux_channel, i_number_of_bytes);
break;
default:
pf_print(opaque,
" - muxcode_substruct_entry slot=%u flex_mux_channel=%u number_of_bytes=%u",
r, i_flex_mux_channel, i_number_of_bytes);
}
}
if (i_print_type == PRINT_XML)
pf_print(opaque, "</MUXCODE_SUBSTRUCT>");
}
if (i_print_type == PRINT_XML)
pf_print(opaque, "</MUXCODE_ENTRY>");
}
if (i_print_type == PRINT_XML)
pf_print(opaque, "</MUXCODE_DESC>");
}
#ifdef __cplusplus
}
#endif
#endif
......@@ -57,6 +57,7 @@
#include <bitstream/mpeg/psi/desc_1e.h>
#include <bitstream/mpeg/psi/desc_1f.h>
#include <bitstream/mpeg/psi/desc_20.h>
#include <bitstream/mpeg/psi/desc_21.h>
#include <bitstream/mpeg/psi/desc_23.h>
#include <bitstream/mpeg/psi/desc_27.h>
#include <bitstream/mpeg/psi/desc_28.h>
......
......@@ -123,6 +123,7 @@ static inline void descl_print(uint8_t *p_descl, uint16_t i_length,
CASE_DESC(1e)
CASE_DESC(1f)
CASE_DESC(20)
CASE_DESC(21)
CASE_DESC(23)
CASE_DESC(27)
CASE_DESC(28)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment