Skip to content

Commit b565b27

Browse files
committed
Add t35_identifier_length and move descr to hrsd
1 parent 7dbb3ef commit b565b27

File tree

13 files changed

+314
-225
lines changed

13 files changed

+314
-225
lines changed

IsoLib/isoiff_tool/w32/isoiff/isoiff.dsp

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

IsoLib/libisomediafile/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ add_library(
7171
src/H263SpecificInfoAtom.c
7272
src/HandlerAtom.c
7373
src/HEVCConfigAtom.c
74+
src/HumanReadableStreamDescriptionAtom.c
7475
src/LHEVCConfigAtom.c
7576
src/VVCConfigAtom.c
7677
src/VVCNALUConfigAtom.c

IsoLib/libisomediafile/linux/libisomediafile/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ sources = \
158158
TextMetaSampleEntry.c \
159159
XMLMetaSampleEntry.c \
160160
BitRateAtom.c \
161+
HumanReadableStreamDescriptionAtom.c \
161162
AMRWPSpecificInfoAtom.c \
162163
AMRSpecificInfoAtom.c \
163164
H263SpecificInfoAtom.c \

IsoLib/libisomediafile/macosx/libisomediafile/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ sources = \
158158
TextMetaSampleEntry.c \
159159
XMLMetaSampleEntry.c \
160160
BitRateAtom.c \
161+
HumanReadableStreamDescriptionAtom.c \
161162
AMRWPSpecificInfoAtom.c \
162163
AMRSpecificInfoAtom.c \
163164
H263SpecificInfoAtom.c \
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*
2+
Copyright 2024 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
/*
17+
$Id: HumanReadableStreamDescriptionAtom.c,v 1.0 2026/03/05 17:00:48 erapefh Exp $
18+
*/
19+
20+
#include "MP4Atoms.h"
21+
#include <stdlib.h>
22+
23+
static void destroy(MP4AtomPtr s)
24+
{
25+
MP4HumanReadableStreamDescriptionAtomPtr self;
26+
self = (MP4HumanReadableStreamDescriptionAtomPtr)s;
27+
if(self == NULL) return;
28+
29+
if(self->description)
30+
{
31+
free(self->description);
32+
self->description = NULL;
33+
}
34+
35+
if(self->super) self->super->destroy(s);
36+
}
37+
38+
static MP4Err serialize(struct MP4Atom *s, char *buffer)
39+
{
40+
MP4Err err;
41+
MP4HumanReadableStreamDescriptionAtomPtr self = (MP4HumanReadableStreamDescriptionAtomPtr)s;
42+
err = MP4NoErr;
43+
44+
err = MP4SerializeCommonBaseAtomFields(s, buffer);
45+
if(err) goto bail;
46+
buffer += self->bytesWritten;
47+
assert(self->type == MP4HumanReadableStreamDescriptionAtomType);
48+
49+
/* Write description as null-terminated UTF-8 string */
50+
if(self->description != NULL)
51+
{
52+
u32 descLen = (u32)strlen(self->description) + 1; /* Include null terminator */
53+
PUTBYTES(self->description, descLen);
54+
}
55+
else
56+
{
57+
/* Empty description: just write '\0' */
58+
u8 nullByte = 0;
59+
PUT8_V(nullByte);
60+
}
61+
62+
assert(self->bytesWritten == self->size);
63+
bail:
64+
TEST_RETURN(err);
65+
66+
return err;
67+
}
68+
69+
static MP4Err calculateSize(struct MP4Atom *s)
70+
{
71+
MP4Err err;
72+
MP4HumanReadableStreamDescriptionAtomPtr self = (MP4HumanReadableStreamDescriptionAtomPtr)s;
73+
err = MP4NoErr;
74+
75+
err = MP4CalculateBaseAtomFieldSize(s);
76+
if(err) goto bail;
77+
/* Add description size (null-terminated string) */
78+
if(self->description != NULL)
79+
{
80+
self->size += (u32)strlen(self->description) + 1; /* Including '\0' */
81+
}
82+
else
83+
{
84+
self->size += 1; /* Just '\0' */
85+
}
86+
bail:
87+
TEST_RETURN(err);
88+
89+
return err;
90+
}
91+
92+
static MP4Err createFromInputStream(MP4AtomPtr s, MP4AtomPtr proto, MP4InputStreamPtr inputStream)
93+
{
94+
MP4Err err;
95+
MP4HumanReadableStreamDescriptionAtomPtr self = (MP4HumanReadableStreamDescriptionAtomPtr)s;
96+
s64 bytesToRead;
97+
u32 descLen;
98+
u32 i;
99+
100+
if(self == NULL) BAILWITHERROR(MP4BadParamErr)
101+
err = self->super->createFromInputStream(s, proto, (char *)inputStream);
102+
if(err) goto bail;
103+
104+
/* Calculate remaining bytes to read */
105+
bytesToRead = (s64)(self->size - self->bytesRead);
106+
if(bytesToRead < 0) BAILWITHERROR(MP4BadDataErr);
107+
108+
if(bytesToRead > 0)
109+
{
110+
/* Read description (null-terminated UTF-8 string) */
111+
/* First, scan for null terminator to find description length */
112+
descLen = 0;
113+
for(i = 0; i < (u32)bytesToRead; i++)
114+
{
115+
u8 byte;
116+
err = inputStream->read8(inputStream, (u32 *)&byte, NULL);
117+
if(err) goto bail;
118+
descLen++;
119+
self->bytesRead++;
120+
if(byte == 0) break;
121+
}
122+
123+
/* Allocate and read description - we need to re-read the bytes */
124+
/* Rewind by backing up bytesRead */
125+
self->bytesRead -= descLen;
126+
err = inputStream->rewindData(inputStream, descLen, NULL);
127+
128+
self->description = (char *)calloc(descLen, 1);
129+
TESTMALLOC(self->description);
130+
err = inputStream->readData(inputStream, descLen, (char *)self->description, NULL);
131+
if(err) goto bail;
132+
self->bytesRead += descLen;
133+
}
134+
135+
bail:
136+
TEST_RETURN(err);
137+
138+
return err;
139+
}
140+
141+
MP4Err
142+
MP4CreateHumanReadableStreamDescriptionAtom(MP4HumanReadableStreamDescriptionAtomPtr *outAtom)
143+
{
144+
MP4Err err;
145+
MP4HumanReadableStreamDescriptionAtomPtr self;
146+
147+
self = (MP4HumanReadableStreamDescriptionAtomPtr)calloc(
148+
1, sizeof(MP4HumanReadableStreamDescriptionAtom));
149+
TESTMALLOC(self);
150+
151+
err = MP4CreateBaseAtom((MP4AtomPtr)self);
152+
if(err) goto bail;
153+
self->type = MP4HumanReadableStreamDescriptionAtomType;
154+
self->name = "HumanReadableStreamDescription";
155+
self->createFromInputStream = (cisfunc)createFromInputStream;
156+
self->destroy = destroy;
157+
self->calculateSize = calculateSize;
158+
self->serialize = serialize;
159+
*outAtom = self;
160+
bail:
161+
TEST_RETURN(err);
162+
163+
return err;
164+
}

IsoLib/libisomediafile/src/ISOMovies.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -872,26 +872,6 @@ extern "C"
872872
MP4Track videoTrack, u32 trackReferenceType, MP4Track *outTrack,
873873
MP4Media *outMedia);
874874

875-
/**
876-
* @brief Read the t35_identifier and description from a serialized T.35 sample entry handle.
877-
* @ingroup SampleDescr
878-
*
879-
* Properly deserializes the handle returned by MP4GetMediaSampleDescription() and extracts
880-
* the T.35 identifier bytes and optional description string. The caller is responsible for
881-
* freeing *outIdentifier and *outDescription with free().
882-
*
883-
* @param sampleEntryH Handle containing the serialized 'it35' sample entry.
884-
* @param outIdentifier Output; receives a newly allocated copy of the t35_identifier bytes.
885-
* @param outIdentifierSize Output; receives the number of bytes in *outIdentifier.
886-
* @param outDescription Optional output; receives a newly allocated description string, or NULL
887-
* if no description is present. Pass NULL to ignore.
888-
* @return MP4NoErr on success, MP4NotFoundErr if no identifier is present, MP4BadParamErr on
889-
* invalid input.
890-
*/
891-
ISO_EXTERN(ISOErr)
892-
ISOGetT35SampleEntryFields(MP4Handle sampleEntryH, u8 **outIdentifier, u32 *outIdentifierSize,
893-
char **outDescription);
894-
895875
/*************************************************************************************************
896876
* VVC Sample descriptions
897877
************************************************************************************************/

IsoLib/libisomediafile/src/ISOSampleDescriptions.c

Lines changed: 39 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -46,43 +46,28 @@ MP4Err MP4ParseAtomUsingProtoList(MP4InputStreamPtr inputStream, u32 *protoList,
4646
MP4AtomPtr *outAtom);
4747

4848
#ifdef ISMACrypt
49-
u32 MP4SampleEntryProtos[] = {MP4MPEGSampleEntryAtomType,
50-
MP4VisualSampleEntryAtomType,
51-
MP4AudioSampleEntryAtomType,
52-
MP4EncAudioSampleEntryAtomType,
53-
MP4EncVisualSampleEntryAtomType,
54-
MP4XMLMetaSampleEntryAtomType,
55-
MP4TextMetaSampleEntryAtomType,
56-
MP4AMRSampleEntryAtomType,
57-
MP4AWBSampleEntryAtomType,
58-
MP4AMRWPSampleEntryAtomType,
59-
MP4H263SampleEntryAtomType,
60-
MP4RestrictedVideoSampleEntryAtomType,
61-
MP4BoxedMetadataSampleEntryType,
62-
ISOAVCSampleEntryAtomType,
63-
ISOHEVCSampleEntryAtomType,
64-
ISOVVCSampleEntryAtomTypeInBand,
65-
ISOVVCSampleEntryAtomTypeOutOfBand,
66-
ISOVVCSubpicSampleEntryAtomType,
67-
0};
49+
u32 MP4SampleEntryProtos[] = {
50+
MP4MPEGSampleEntryAtomType, MP4VisualSampleEntryAtomType,
51+
MP4AudioSampleEntryAtomType, MP4EncAudioSampleEntryAtomType,
52+
MP4EncVisualSampleEntryAtomType, MP4XMLMetaSampleEntryAtomType,
53+
MP4TextMetaSampleEntryAtomType, MP4AMRSampleEntryAtomType,
54+
MP4AWBSampleEntryAtomType, MP4AMRWPSampleEntryAtomType,
55+
MP4H263SampleEntryAtomType, MP4RestrictedVideoSampleEntryAtomType,
56+
MP4BoxedMetadataSampleEntryType, MP4T35SampleGroupEntry,
57+
ISOAVCSampleEntryAtomType, ISOHEVCSampleEntryAtomType,
58+
ISOVVCSampleEntryAtomTypeInBand, ISOVVCSampleEntryAtomTypeOutOfBand,
59+
ISOVVCSubpicSampleEntryAtomType, 0};
6860
#else
69-
u32 MP4SampleEntryProtos[] = {MP4MPEGSampleEntryAtomType,
70-
MP4VisualSampleEntryAtomType,
71-
MP4AudioSampleEntryAtomType,
72-
MP4XMLMetaSampleEntryAtomType,
73-
MP4TextMetaSampleEntryAtomType,
74-
MP4AMRSampleEntryAtomType,
75-
MP4AWBSampleEntryAtomType,
76-
MP4AMRWPSampleEntryAtomType,
77-
MP4H263SampleEntryAtomType,
78-
MP4RestrictedVideoSampleEntryAtomType,
79-
MP4BoxedMetadataSampleEntryType,
80-
ISOAVCSampleEntryAtomType,
81-
ISOHEVCSampleEntryAtomType,
82-
ISOVVCSampleEntryAtomTypeInBand,
83-
ISOVVCSampleEntryAtomTypeOutOfBand,
84-
ISOVVCSubpicSampleEntryAtomType,
85-
0};
61+
u32 MP4SampleEntryProtos[] = {
62+
MP4MPEGSampleEntryAtomType, MP4VisualSampleEntryAtomType,
63+
MP4AudioSampleEntryAtomType, MP4XMLMetaSampleEntryAtomType,
64+
MP4TextMetaSampleEntryAtomType, MP4AMRSampleEntryAtomType,
65+
MP4AWBSampleEntryAtomType, MP4AMRWPSampleEntryAtomType,
66+
MP4H263SampleEntryAtomType, MP4RestrictedVideoSampleEntryAtomType,
67+
MP4BoxedMetadataSampleEntryType, MP4T35SampleGroupEntry,
68+
ISOAVCSampleEntryAtomType, ISOHEVCSampleEntryAtomType,
69+
ISOVVCSampleEntryAtomTypeInBand, ISOVVCSampleEntryAtomTypeOutOfBand,
70+
ISOVVCSubpicSampleEntryAtomType, 0};
8671
#endif
8772

8873
MP4Err sampleEntryHToAtomPtr(MP4Handle sampleEntryH, MP4AtomPtr *entryPtr, u32 defaultType)
@@ -2505,6 +2490,7 @@ ISONewT35SampleDescription(MP4T35MetadataSampleEntryPtr *outSE, u32 dataReferenc
25052490
{
25062491
MP4Err err;
25072492
MP4T35MetadataSampleEntryPtr it35;
2493+
MP4HumanReadableStreamDescriptionAtomPtr hrsd;
25082494
u8 *identifier = NULL;
25092495
u32 identifierSize = 0;
25102496
char *description = NULL;
@@ -2520,10 +2506,23 @@ ISONewT35SampleDescription(MP4T35MetadataSampleEntryPtr *outSE, u32 dataReferenc
25202506
if(err) goto bail;
25212507
it35->dataReferenceIndex = dataReferenceIndex;
25222508

2523-
/* Set description and t35_identifier fields */
2524-
it35->description = description;
2525-
it35->t35_identifier = identifier;
2526-
it35->t35_identifier_size = identifierSize;
2509+
/* Set t35_identifier_length and t35_identifier fields */
2510+
it35->t35_identifier_length = identifierSize;
2511+
it35->t35_identifier = identifier;
2512+
2513+
if(description != NULL && description[0] != '\0')
2514+
{
2515+
err = MP4MakeLinkedList(&it35->ExtensionAtomList);
2516+
if(err) goto bail;
2517+
2518+
err = MP4CreateHumanReadableStreamDescriptionAtom(&hrsd);
2519+
if(err) goto bail;
2520+
hrsd->description = strdup(description);
2521+
TESTMALLOC(hrsd->description);
2522+
2523+
err = MP4AddListEntry((void *)hrsd, it35->ExtensionAtomList);
2524+
if(err) goto bail;
2525+
}
25272526

25282527
*outSE = it35;
25292528

@@ -2606,41 +2605,3 @@ ISONewT35MetadataTrack(MP4Movie theMovie, u32 timescale, const char *t35_prefix_
26062605
TEST_RETURN(err);
26072606
return err;
26082607
}
2609-
2610-
ISO_EXTERN(ISOErr)
2611-
ISOGetT35SampleEntryFields(MP4Handle sampleEntryH, u8 **outIdentifier, u32 *outIdentifierSize,
2612-
char **outDescription)
2613-
{
2614-
MP4Err err;
2615-
MP4T35MetadataSampleEntryPtr it35 = NULL;
2616-
2617-
if(sampleEntryH == NULL || outIdentifier == NULL || outIdentifierSize == NULL)
2618-
BAILWITHERROR(MP4BadParamErr);
2619-
2620-
*outIdentifier = NULL;
2621-
*outIdentifierSize = 0;
2622-
if(outDescription) *outDescription = NULL;
2623-
2624-
err = sampleEntryHToAtomPtr(sampleEntryH, (MP4AtomPtr *)&it35, MP4T35MetadataSampleEntryType);
2625-
if(err) goto bail;
2626-
2627-
if(it35->t35_identifier == NULL || it35->t35_identifier_size == 0) BAILWITHERROR(MP4NotFoundErr);
2628-
2629-
*outIdentifier = (u8 *)calloc(it35->t35_identifier_size, 1);
2630-
TESTMALLOC(*outIdentifier);
2631-
memcpy(*outIdentifier, it35->t35_identifier, it35->t35_identifier_size);
2632-
*outIdentifierSize = it35->t35_identifier_size;
2633-
2634-
if(outDescription && it35->description && it35->description[0] != '\0')
2635-
{
2636-
u32 len = (u32)strlen(it35->description) + 1;
2637-
*outDescription = (char *)calloc(len, 1);
2638-
TESTMALLOC(*outDescription);
2639-
memcpy(*outDescription, it35->description, len);
2640-
}
2641-
2642-
bail:
2643-
if(it35) it35->destroy((MP4AtomPtr)it35);
2644-
TEST_RETURN(err);
2645-
return err;
2646-
}

IsoLib/libisomediafile/src/MP4Atoms.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,11 @@ MP4Err MP4CreateAtom(u32 atomType, MP4AtomPtr *outAtom)
628628
err = MP4CreateBitRateAtom((MP4BitRateAtomPtr *)&newAtom);
629629
break;
630630

631+
case MP4HumanReadableStreamDescriptionAtomType:
632+
err = MP4CreateHumanReadableStreamDescriptionAtom(
633+
(MP4HumanReadableStreamDescriptionAtomPtr *)&newAtom);
634+
break;
635+
631636
case MP4ItemPropertiesAtomType:
632637
err = MP4CreateItemPropertiesAtom((MP4ItemPropertiesAtomPtr *)&newAtom);
633638
break;

0 commit comments

Comments
 (0)