Skip to content

Commit c300a53

Browse files
committed
[origin] Bump up to 2024.05.30 [113.2.1]
2024-05-30: - Fixed a mistake that caused the config file "config.raspberrypi" to not appear in the distribution. (It's there now.) 2024-05-15: - Added a new config file "config.raspberrypi" that is known to work for building the code on/for a Raspberry Pi 5. 2024-05-05: - Updated "QuickTimeFileSink" to add support for recording H.265 video streams. (This is not fully working yet; it appears to have some bugs.)
1 parent 919da29 commit c300a53

11 files changed

+584
-40
lines changed

BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
1919
#ifndef _BASICUSAGEENVIRONMENT_VERSION_HH
2020
#define _BASICUSAGEENVIRONMENT_VERSION_HH
2121

22-
#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING "2024.04.19"
23-
#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT 1713484800
22+
#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING "2024.05.30"
23+
#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT 1717027200
2424

2525
extern char const* const BasicUsageEnvironmentLibraryVersionStr;
2626
extern int const BasicUsageEnvironmentLibraryVersionInt;

UsageEnvironment/include/UsageEnvironment_version.hh

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
1919
#ifndef _USAGEENVIRONMENT_VERSION_HH
2020
#define _USAGEENVIRONMENT_VERSION_HH
2121

22-
#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING "2024.04.19"
23-
#define USAGEENVIRONMENT_LIBRARY_VERSION_INT 1713484800
22+
#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING "2024.05.30"
23+
#define USAGEENVIRONMENT_LIBRARY_VERSION_INT 1717027200
2424

2525
extern char const* const UsageEnvironmentLibraryVersionStr;
2626
extern int const UsageEnvironmentLibraryVersionInt;

config.linux-with-shared-libraries

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# One or more interfaces were added, but no existing interfaces were changed or removed => CURRENT += 1; REVISION = 0; AGE += 1
55

66
libliveMedia_VERSION_CURRENT=113
7-
libliveMedia_VERSION_REVISION=1
7+
libliveMedia_VERSION_REVISION=2
88
libliveMedia_VERSION_AGE=1
99
libliveMedia_LIB_SUFFIX=so.$(shell expr $(libliveMedia_VERSION_CURRENT) - $(libliveMedia_VERSION_AGE)).$(libliveMedia_VERSION_AGE).$(libliveMedia_VERSION_REVISION)
1010

config.raspberrypi

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
COMPILE_OPTS = $(INCLUDES) -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -DNO_OPENSSL=1 -DNO_STD_LIB=1
2+
C = c
3+
C_COMPILER = cc
4+
C_FLAGS = $(COMPILE_OPTS) $(CPPFLAGS) $(CFLAGS)
5+
CPP = cpp
6+
CPLUSPLUS_COMPILER = c++
7+
CPLUSPLUS_FLAGS = $(COMPILE_OPTS) -Wall -DBSD=1 $(CPPFLAGS) $(CXXFLAGS)
8+
OBJ = o
9+
LINK = c++ -o
10+
LINK_OPTS = -L. $(LDFLAGS)
11+
CONSOLE_LINK_OPTS = $(LINK_OPTS)
12+
LIBRARY_LINK = ar cr
13+
LIBRARY_LINK_OPTS =
14+
LIB_SUFFIX = a
15+
LIBS_FOR_CONSOLE_APPLICATION =
16+
LIBS_FOR_GUI_APPLICATION =
17+
EXE =

groupsock/include/groupsock_version.hh

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
1919
#ifndef _GROUPSOCK_VERSION_HH
2020
#define _GROUPSOCK_VERSION_HH
2121

22-
#define GROUPSOCK_LIBRARY_VERSION_STRING "2024.04.19"
23-
#define GROUPSOCK_LIBRARY_VERSION_INT 1713484800
22+
#define GROUPSOCK_LIBRARY_VERSION_STRING "2024.05.30"
23+
#define GROUPSOCK_LIBRARY_VERSION_INT 1717027200
2424

2525
extern char const* const groupsockLibraryVersionStr;
2626
extern int const groupsockLibraryVersionInt;

liveMedia/QuickTimeFileSink.cpp

+160-31
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ along with this library; if not, write to the Free Software Foundation, Inc.,
2626
#include "H263plusVideoRTPSource.hh" // for the special header
2727
#include "MPEG4GenericRTPSource.hh" //for "samplingFrequencyFromAudioSpecificConfig()"
2828
#include "MPEG4LATMAudioRTPSource.hh" // for "parseGeneralConfigStr()"
29+
#include "H264or5VideoStreamFramer.hh" // for "removeH264or5EmulationBytes()"
2930
#include "Base64.hh"
3031

3132
#include <ctype.h>
3233

3334
#define fourChar(x,y,z,w) ( ((x)<<24)|((y)<<16)|((z)<<8)|(w) )
3435

35-
#define H264_IDR_FRAME 0x65 //bit 8 == 0, bits 7-6 (ref) == 3, bits 5-0 (type) == 5
36+
#define H264_IDR_FRAME 0x65 //bit 8 == 0, bits 7-6 (ref) == 3, bits 5-1 (type) == 5
37+
#define isIDRFrame(firstByte) (firstByte == H264_IDR_FRAME || ((firstByte&0x7E)>>1) == 19 || ((firstByte&0x7E)>>1) == 20)
3638

3739
////////// SubsessionIOState, ChunkDescriptor ///////////
3840
// A structure used to represent the I/O state of each input 'subsession':
@@ -653,6 +655,10 @@ Boolean SubsessionIOState::setQTstate() {
653655
fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_avc1;
654656
fQTTimeScale = 600;
655657
fQTTimeUnitsPerSample = fQTTimeScale/fOurSink.fMovieFPS;
658+
} else if (strcmp(fOurSubsession.codecName(), "H265") == 0) {
659+
fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_hvc1;
660+
fQTTimeScale = 600;
661+
fQTTimeUnitsPerSample = fQTTimeScale/fOurSink.fMovieFPS;
656662
} else if (strcmp(fOurSubsession.codecName(), "MP4V-ES") == 0) {
657663
fQTMediaDataAtomCreator = &QuickTimeFileSink::addAtom_mp4v;
658664
fQTTimeScale = 600;
@@ -801,15 +807,18 @@ void SubsessionIOState::useFrame(SubsessionBuffer& buffer) {
801807
struct timeval const& presentationTime = buffer.presentationTime();
802808
int64_t const destFileOffset = TellFile64(fOurSink.fOutFid);
803809
unsigned sampleNumberOfFrameStart = fQTTotNumSamples + 1;
804-
Boolean avcHack = fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_avc1;
810+
Boolean h264or5Hack =
811+
fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_avc1 ||
812+
fQTMediaDataAtomCreator == &QuickTimeFileSink::addAtom_hvc1;
813+
805814

806815
// If we're not syncing streams, or this subsession is not video, then
807816
// just give this frame a fixed duration:
808817
if (!fOurSink.fSyncStreams
809818
|| fQTcomponentSubtype != fourChar('v','i','d','e')) {
810819
unsigned const frameDuration = fQTTimeUnitsPerSample*fQTSamplesPerFrame;
811820
unsigned frameSizeToUse = frameSize;
812-
if (avcHack) frameSizeToUse += 4; // H.264/AVC gets the frame size prefix
821+
if (h264or5Hack) frameSizeToUse += 4; // H.264/5 gets the frame size prefix
813822

814823
fQTTotNumSamples += useFrame1(frameSizeToUse, presentationTime, frameDuration, destFileOffset);
815824
} else {
@@ -825,15 +834,15 @@ void SubsessionIOState::useFrame(SubsessionBuffer& buffer) {
825834
unsigned frameDuration
826835
= (unsigned)((2*duration*fQTTimeScale+1)/2); // round
827836
unsigned frameSizeToUse = fPrevFrameState.frameSize;
828-
if (avcHack) frameSizeToUse += 4; // H.264/AVC gets the frame size prefix
837+
if (h264or5Hack) frameSizeToUse += 4; // H.264/5 gets the frame size prefix
829838

830839
unsigned numSamples
831840
= useFrame1(frameSizeToUse, ppt, frameDuration, fPrevFrameState.destFileOffset);
832841
fQTTotNumSamples += numSamples;
833842
sampleNumberOfFrameStart = fQTTotNumSamples + 1;
834843
}
835844

836-
if (avcHack && (*frameSource == H264_IDR_FRAME)) {
845+
if (h264or5Hack && isIDRFrame(*frameSource)) {
837846
SyncFrame* newSyncFrame = new SyncFrame(fQTTotNumSamples + 1);
838847
if (fTailSyncFrame == NULL) {
839848
fHeadSyncFrame = newSyncFrame;
@@ -849,7 +858,7 @@ void SubsessionIOState::useFrame(SubsessionBuffer& buffer) {
849858
fPrevFrameState.destFileOffset = destFileOffset;
850859
}
851860

852-
if (avcHack) fOurSink.addWord(frameSize);
861+
if (h264or5Hack) fOurSink.addWord(frameSize);
853862

854863
// Write the data into the file:
855864
fwrite(frameSource, 1, frameSize, fOurSink.fOutFid);
@@ -1119,7 +1128,7 @@ Boolean SubsessionIOState::syncOK(struct timeval presentationTime) {
11191128

11201129
// if audio is in sync, wait for the next IDR frame to start
11211130
unsigned char* const frameSource = fBuffer->dataStart();
1122-
if (*frameSource != H264_IDR_FRAME) return False;
1131+
if (!isIDRFrame(*frameSource)) return False;
11231132
}
11241133
// But now we are
11251134
fHaveBeenSynced = True;
@@ -1888,45 +1897,165 @@ addAtom(avc1);
18881897
addAtomEnd;
18891898

18901899
addAtom(avcC);
1891-
// Begin by Base-64 decoding the "sprop" parameter sets strings:
1900+
// Begin by Base-64 decoding the "sprop" parameter sets strings:
18921901
char* psets = strDup(fCurrentIOState->fOurSubsession.fmtp_spropparametersets());
18931902
if (psets == NULL) return 0;
18941903

1904+
char const* spsBase64 = psets;
18951905
size_t comma_pos = strcspn(psets, ",");
18961906
psets[comma_pos] = '\0';
1897-
char const* sps_b64 = psets;
1898-
char const* pps_b64 = &psets[comma_pos+1];
1899-
unsigned sps_count;
1900-
unsigned char* sps_data = base64Decode(sps_b64, sps_count, false);
1901-
unsigned pps_count;
1902-
unsigned char* pps_data = base64Decode(pps_b64, pps_count, false);
1903-
1904-
// Then add the decoded data:
1907+
1908+
char const* ppsBase64 = &psets[comma_pos+1];
1909+
1910+
unsigned spsSize;
1911+
unsigned char* sps = base64Decode(spsBase64, spsSize, false);
1912+
1913+
unsigned ppsSize;
1914+
unsigned char* pps = base64Decode(ppsBase64, ppsSize, false);
1915+
1916+
// We use some of the data from the "SPS". Remove any 'emulation bytes' from it first:
1917+
if (spsSize == 0) return 0;
1918+
u_int8_t* spsWEB = new u_int8_t[spsSize]; // "WEB" means "Without Emulation Bytes"
1919+
unsigned spsWEBSize = removeH264or5EmulationBytes(spsWEB, spsSize, sps, spsSize);
1920+
if (spsWEBSize < 4) { // Bad SPS size
1921+
delete[] spsWEB;
1922+
return 0;
1923+
}
1924+
1925+
// Then add the decoded data:
19051926
size += addByte(0x01); // configuration version
1906-
size += addByte(sps_data[1]); // profile
1907-
size += addByte(sps_data[2]); // profile compat
1908-
size += addByte(sps_data[3]); // level
1927+
size += addByte(spsWEB[1]); // profile
1928+
size += addByte(spsWEB[2]); // profile compat
1929+
size += addByte(spsWEB[3]); // level
19091930
size += addByte(0xff); /* 0b11111100 | lengthsize = 0x11 */
1910-
size += addByte(0xe0 | (sps_count > 0 ? 1 : 0) );
1911-
if (sps_count > 0) {
1912-
size += addHalfWord(sps_count);
1913-
for (unsigned i = 0; i < sps_count; i++) {
1914-
size += addByte(sps_data[i]);
1931+
size += addByte(0xe0 | (spsSize > 0 ? 1 : 0) );
1932+
if (spsSize > 0) {
1933+
size += addHalfWord(spsSize);
1934+
for (unsigned i = 0; i < spsSize; i++) {
1935+
size += addByte(sps[i]);
19151936
}
19161937
}
1917-
size += addByte(pps_count > 0 ? 1 : 0);
1918-
if (pps_count > 0) {
1919-
size += addHalfWord(pps_count);
1920-
for (unsigned i = 0; i < pps_count; i++) {
1921-
size += addByte(pps_data[i]);
1938+
size += addByte(ppsSize > 0 ? 1 : 0);
1939+
if (ppsSize > 0) {
1940+
size += addHalfWord(ppsSize);
1941+
for (unsigned i = 0; i < ppsSize; i++) {
1942+
size += addByte(pps[i]);
19221943
}
19231944
}
19241945

1925-
// Finally, delete the data that we allocated:
1926-
delete[] pps_data; delete[] sps_data;
1946+
// Finally, delete the data that we allocated:
1947+
delete[] spsWEB;
1948+
delete[] pps; delete[] sps;
19271949
delete[] psets;
19281950
addAtomEnd;
19291951

1952+
addAtom(hvc1);
1953+
// General sample description fields:
1954+
size += addWord(0x00000000); // Reserved
1955+
size += addWord(0x00000001); // Reserved+Data reference index
1956+
// Video sample description fields:
1957+
size += addWord(0x00000000); // Version+Revision level
1958+
size += add4ByteString("appl"); // Vendor
1959+
size += addWord(0x00000000); // Temporal quality
1960+
size += addWord(0x00000000); // Spatial quality
1961+
unsigned const widthAndHeight = (fMovieWidth<<16)|fMovieHeight;
1962+
size += addWord(widthAndHeight); // Width+height
1963+
size += addWord(0x00480000); // Horizontal resolution
1964+
size += addWord(0x00480000); // Vertical resolution
1965+
size += addWord(0x00000000); // Data size
1966+
size += addWord(0x00010548); // Frame count+Compressor name (start)
1967+
// "H.265"
1968+
size += addWord(0x2e323635); // Compressor name (continued)
1969+
size += addZeroWords(6); // Compressor name (continued - zero)
1970+
size += addWord(0x00000018); // Compressor name (final)+Depth
1971+
size += addHalfWord(0xffff); // Color table id
1972+
size += addAtom_hvcC();
1973+
addAtomEnd;
1974+
1975+
addAtom(hvcC);
1976+
// Begin by Base-64 decoding the "sprop" parameter sets strings:
1977+
char const* vpsBase64 = strDup(fCurrentIOState->fOurSubsession.fmtp_spropvps());
1978+
char const* spsBase64 = strDup(fCurrentIOState->fOurSubsession.fmtp_spropsps());
1979+
char const* ppsBase64 = strDup(fCurrentIOState->fOurSubsession.fmtp_sproppps());
1980+
if (vpsBase64 == NULL || spsBase64 == NULL || ppsBase64 == NULL) return 0;
1981+
1982+
unsigned vpsSize;
1983+
unsigned char* vps = base64Decode(vpsBase64, vpsSize, false);
1984+
1985+
unsigned spsSize;
1986+
unsigned char* sps = base64Decode(spsBase64, spsSize, false);
1987+
1988+
unsigned ppsSize;
1989+
unsigned char* pps = base64Decode(ppsBase64, ppsSize, false);
1990+
1991+
// We use some of the data from the "VPS". Remove any 'emulation bytes' from it first:
1992+
if (vpsSize == 0) return 0;
1993+
u_int8_t* vpsWEB = new u_int8_t[vpsSize]; // "WEB" means "Without Emulation Bytes"
1994+
unsigned vpsWEBSize = removeH264or5EmulationBytes(vpsWEB, vpsSize, vps, vpsSize);
1995+
if (vpsWEBSize < 6/*'profile_tier_level' offset*/ + 12/*num 'profile_tier_level' bytes*/) {
1996+
// Bad VPS size
1997+
delete[] vpsWEB;
1998+
return 0;
1999+
}
2000+
2001+
// Then add the decoded data:
2002+
size += addByte(0x01); // configurationVersion = 1
2003+
2004+
u_int8_t const* profileTierLevelHeaderBytes = &vpsWEB[6];
2005+
size += addByte(profileTierLevelHeaderBytes[0]);
2006+
// general_profile_space + general_tier_flag + general_profile_idc
2007+
2008+
u_int8_t const* general_profile_compatibility_flags = &profileTierLevelHeaderBytes[1];
2009+
for (unsigned i = 0; i < 4; ++i) size += addByte(general_profile_compatibility_flags[i]);
2010+
// general_profile_compatibility_flags
2011+
2012+
u_int8_t const* general_constraint_indicator_flags = &profileTierLevelHeaderBytes[5];
2013+
for (unsigned i = 0; i < 6; ++i) size += addByte(general_constraint_indicator_flags[i]);
2014+
// general_constraint_indicator_flags
2015+
2016+
size += addByte(profileTierLevelHeaderBytes[11]); // general_level_idc
2017+
size += addHalfWord(0xF000); // min_spatial_segmentation_idc = 0 ???
2018+
size += addByte(0xFC); // parallelismType = 0 ???
2019+
size += addByte(0xFD); // chroma_format_idc = 1 ???
2020+
size += addByte(0xF8); // bit_depth_luma_minus8 = 0 ???
2021+
size += addByte(0xF8); // bit_depth_chroma_minus8 = 0 ???
2022+
size += addHalfWord(0x0000); // avgFrameRate = 0
2023+
size += addByte(0x0F);
2024+
// constantFrameRate = 0; numTemporalLayers = 1; temporalIdNested = 1; lengthSizeMinusOne = 3 ???
2025+
size += addByte(1 + (spsSize > 0) + (ppsSize > 0)); // numOfArrays
2026+
2027+
if (vpsSize > 0) {
2028+
size += addByte(0x20); // array_completeness = 0; NAL_unit_type = VPS
2029+
size += addHalfWord(1); // numNalus
2030+
size += addHalfWord(vpsSize);
2031+
for (unsigned i = 0; i < vpsSize; i++) {
2032+
size += addByte(vps[i]);
2033+
}
2034+
}
2035+
2036+
if (spsSize > 0) {
2037+
size += addByte(0x21); // array_completeness = 0; NAL_unit_type = SPS
2038+
size += addHalfWord(1); // numNalus
2039+
size += addHalfWord(spsSize);
2040+
for (unsigned i = 0; i < spsSize; i++) {
2041+
size += addByte(sps[i]);
2042+
}
2043+
}
2044+
2045+
if (ppsSize > 0) {
2046+
size += addByte(0x22); // array_completeness = 0; NAL_unit_type = PPS
2047+
size += addHalfWord(1); // numNalus
2048+
size += addHalfWord(ppsSize);
2049+
for (unsigned i = 0; i < ppsSize; i++) {
2050+
size += addByte(pps[i]);
2051+
}
2052+
}
2053+
2054+
// Finally, delete the data that we allocated:
2055+
delete[] vpsWEB;
2056+
delete[] vps; delete[] pps; delete[] sps;
2057+
addAtomEnd;
2058+
19302059
addAtom(mp4v);
19312060
// General sample description fields:
19322061
size += addWord(0x00000000); // Reserved

0 commit comments

Comments
 (0)