From cc115afc1da6347b008b25903e56dd0b508807eb Mon Sep 17 00:00:00 2001 From: ChenGH Date: Mon, 2 Jun 2025 09:56:42 +0800 Subject: [PATCH] Script: Use clang-format to unify the coding style. v7.0.38 (#4366) 1. add clang-format config file 2. add clang_format.sh file, use to format cpp code before pr merged. --------- Co-authored-by: winlin --- .clang-format | 296 ++++++++++++++++++ trunk/doc/CHANGELOG.md | 1 + trunk/scripts/clang_format.sh | 27 ++ trunk/src/core/srs_core_version7.hpp | 2 +- .../src/protocol/srs_protocol_rtmp_stack.cpp | 102 +++--- 5 files changed, 379 insertions(+), 49 deletions(-) create mode 100644 .clang-format create mode 100755 trunk/scripts/clang_format.sh diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..4bd768aac --- /dev/null +++ b/.clang-format @@ -0,0 +1,296 @@ +# This file is generated by `clang-format -style=llvm -dump-config > .clang-format` and modified to fit srs project's style guide. +# the modifications are: +# AccessModifierOffset: -4 +# BreakBeforeBraces: Linux +# ColumnLimit: 0 +# IndentWidth: 4 +# TabWidth: 4 +# refer to https://clang.llvm.org/docs/ClangFormatStyleOptions.html for more details. +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: true + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseArrows: false + AlignCaseColons: false +AlignConsecutiveTableGenBreakingDAGArgColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenCondOperatorColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenDefinitionColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowBreakBeforeNoexceptSpecifier: Never +AllowShortBlocksOnASingleLine: Never +AllowShortCaseExpressionOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AllowShortNamespacesOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: BinPack +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakAfterReturnType: None +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Linux +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakBinaryOperations: Never +BreakConstructorInitializers: BeforeColon +BreakFunctionDefinitionParameters: false +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +BreakTemplateDeclarations: MultiLine +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExportBlock: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: true + AtStartOfFile: true +KeepFormFeed: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MainIncludeChar: Quote +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakBeforeMemberAccess: 150 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: Always +RemoveBracesLLVM: false +RemoveEmptyLinesInUnwrappedLines: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + ExceptDoubleParentheses: false + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: c++03 +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TableGenBreakInsideDAGArg: DontBreak +TabWidth: 4 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +WrapNamespaceBodyWithEmptyLines: Leave +... + diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 494f0749b..346fa5348 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 7.0 Changelog +* v7.0, 2025-06-01, Merge [#4366](https://github.com/ossrs/srs/pull/4366): Script: Use clang-format to unify the coding style. v7.0.38 (#4366) * v7.0, 2025-05-29, Merge [#4356](https://github.com/ossrs/srs/pull/4356): RTMP: Use extended timestamp as delta when chunk fmt=1/2. v7.0.37 (#4356) * v7.0, 2025-05-29, Merge [#4363](https://github.com/ossrs/srs/pull/4363): Fix error about TestRtcPublish_HttpFlvPlay. v7.0.36 (#4363) * v7.0, 2025-05-29, Merge [#4362](https://github.com/ossrs/srs/pull/4362): Update VSCode launch configuration to support GDB on Linux and LLDB on macOS. v7.0.35 (#4362) diff --git a/trunk/scripts/clang_format.sh b/trunk/scripts/clang_format.sh new file mode 100755 index 000000000..f0ce9a358 --- /dev/null +++ b/trunk/scripts/clang_format.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# work_dir is the root directory of the project +work_dir=$(cd -P $(dirname $0) && cd ../.. && pwd) && cd $work_dir && echo "Run clang-format in ${work_dir}" + +# Check if clang-format is installed +if ! command -v clang-format &> /dev/null; then + echo "clang-format could not be found, please install it first." + exit 1 +fi + +# Check if the trunk directory exists +if [ ! -d "trunk" ]; then + echo "trunk directory does not exist, please run this script from the project root." + exit 1 +fi +# Find all .cpp, .hpp, and .h files in the trunk directory, excluding 3rdparty +# and format them using clang-format with the style defined in .clang-format file +if [ ! -f ".clang-format" ]; then + echo ".clang-format file does not exist, please create one in the project root." + exit 1 +fi + +echo "Formatting source files in trunk directory..." +# Exclude the 3rdparty directory and format all .cpp, and .hpp +# Use -i to edit files in place +find trunk/src -name "*.*pp" | xargs clang-format -style=file -i diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp index 4ec17a9cf..ab0fb882e 100644 --- a/trunk/src/core/srs_core_version7.hpp +++ b/trunk/src/core/srs_core_version7.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 7 #define VERSION_MINOR 0 -#define VERSION_REVISION 37 +#define VERSION_REVISION 38 #endif \ No newline at end of file diff --git a/trunk/src/protocol/srs_protocol_rtmp_stack.cpp b/trunk/src/protocol/srs_protocol_rtmp_stack.cpp index 7c0c0c5c7..869404de1 100644 --- a/trunk/src/protocol/srs_protocol_rtmp_stack.cpp +++ b/trunk/src/protocol/srs_protocol_rtmp_stack.cpp @@ -1033,28 +1033,6 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt) // timestamp header' MUST be present. Otherwise, this value SHOULD be // the entire delta. chunk->has_extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP); - if (!chunk->has_extended_timestamp) { - // Extended timestamp: 0 or 4 bytes - // This field MUST be sent when the normal timsestamp is set to - // 0xffffff, it MUST NOT be sent if the normal timestamp is set to - // anything else. So for values less than 0xffffff the normal - // timestamp field SHOULD be used in which case the extended timestamp - // MUST NOT be present. For values greater than or equal to 0xffffff - // the normal timestamp field MUST NOT be used and MUST be set to - // 0xffffff and the extended timestamp MUST be sent. - if (fmt == RTMP_FMT_TYPE0) { - // 6.1.2.1. Type 0 - // For a type-0 chunk, the absolute timestamp of the message is sent - // here. - chunk->header.timestamp = chunk->header.timestamp_delta; - } else { - // 6.1.2.2. Type 1 - // 6.1.2.3. Type 2 - // For a type-1 or type-2 chunk, the difference between the previous - // chunk's timestamp and the current chunk's timestamp is sent here. - chunk->header.timestamp += chunk->header.timestamp_delta; - } - } if (fmt <= RTMP_FMT_TYPE1) { int32_t payload_length = 0; @@ -1083,16 +1061,10 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt) pp[3] = *p++; } } - } else { - // update the timestamp even fmt=3 for first chunk packet - if (is_first_chunk_of_msg && !chunk->has_extended_timestamp) { - chunk->header.timestamp += chunk->header.timestamp_delta; - } } // read extended-timestamp if (chunk->has_extended_timestamp) { - mh_size += 4; if ((err = in_buffer->grow(skt, 4)) != srs_success) { return srs_error_wrap(err, "read 4 bytes ext timestamp"); } @@ -1111,44 +1083,78 @@ srs_error_t SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt) timestamp &= 0x7fffffff; /** - * RTMP specification and ffmpeg/librtmp is false, - * but, adobe changed the specification, so flash/FMLE/FMS always true. - * default to true to support flash/FMLE/FMS. + * For the RTMP v1 2009 version + * 6.1.3. Extended Timestamp, This field is transmitted only when the normal time + * stamp in the chunk message header is set to 0x00ffffff. If normal time stamp is + * set to any value less than 0x00ffffff, this field MUST NOT be present. This field + * MUST NOT be present if the timestamp field is not present. Type 3 chunks MUST + * NOT have this field. * - * ffmpeg/librtmp may donot send this filed, need to detect the value. + * For the RTMP v1 2012 version + * 5.3.1.3. Extended Timestamp, The Extended Timestamp field is used to encode + * timestamps or timestamp deltas that are greater than 16777215 (0xFFFFFF); that + * is, for timestamps or timestamp deltas that don’t fit in the 24 bit fields of + * Type 0, 1, or 2 chunks. This field encodes the complete 32-bit timestamp or + * timestamp delta. The presence of this field is indicated by setting the timestamp + * field of a Type 0 chunk, or the timestamp delta field of a Type 1 or 2 chunk, to + * 16777215 (0xFFFFFF). This field is present in Type 3 chunks when the most recent + * Type 0, 1, or 2 chunk for the same chunk stream ID indicated the presence of an + * extended timestamp field. + * + * FMLE/FMS/Flash Player always send the extended-timestamp, followed the 2012 version, + * which means always send the extended timestamp in Type 3 chunks. + * + * librtmp may donot send this filed, need to detect the value. * @see also: http://blog.csdn.net/win_lin/article/details/13363699 * compare to the chunk timestamp, which is set by chunk message header * type 0,1 or 2. * - * @remark, nginx send the extended-timestamp in sequence-header, + * @remark, ffmpeg/nginx send the extended-timestamp in sequence-header, * and timestamp delta in continue C1 chunks, and so compatible with ffmpeg, * that is, there is no continue chunks and extended-timestamp in nginx-rtmp. * * @remark, srs always send the extended-timestamp, to keep simple, * and compatible with adobe products. + * + * If the extended timestamp is present (RTMP v1 2012 version), it MUST be equal to the + * previous one in the same chunk. Should skip back 4 bytes if the extended timestamp + * is not present (RTMP v1 2009 version). See https://github.com/veovera/enhanced-rtmp/issues/42 + * for details. */ uint32_t chunk_extended_timestamp = (uint32_t)chunk->extended_timestamp; - - /** - * if chunk_timestamp<=0, the chunk previous packet has no extended-timestamp, - * always use the extended timestamp. - */ - /** - * about the is_first_chunk_of_msg. - * @remark, for the first chunk of message, always use the extended timestamp. - */ if (!is_first_chunk_of_msg && chunk_extended_timestamp > 0 && chunk_extended_timestamp != timestamp) { - mh_size -= 4; in_buffer->skip(-4); } else { chunk->extended_timestamp = timestamp; - if (fmt == RTMP_FMT_TYPE0) { - chunk->header.timestamp = timestamp; - } else if (is_first_chunk_of_msg) { - chunk->header.timestamp += timestamp; - } } } + + // fmt: 0 + // timestamp: 3 bytes + // If the timestamp is greater than or equal to 16777215 + // (hexadecimal 0x00ffffff), this value MUST be 16777215, and the + // 'extended timestamp header' MUST be present. Otherwise, this value + // SHOULD be the entire timestamp. + // + // fmt: 1 or 2 + // timestamp delta: 3 bytes + // If the delta is greater than or equal to 16777215 (hexadecimal + // 0x00ffffff), this value MUST be 16777215, and the 'extended + // timestamp header' MUST be present. Otherwise, this value SHOULD be + // the entire delta. + uint32_t timestamp = chunk->has_extended_timestamp ? chunk->extended_timestamp : chunk->header.timestamp_delta; + if (fmt == RTMP_FMT_TYPE0) { + // 6.1.2.1. Type 0 + // For a type-0 chunk, the absolute timestamp of the message is sent + // here. + chunk->header.timestamp = timestamp; + } else if (is_first_chunk_of_msg) { + // 6.1.2.2. Type 1 + // 6.1.2.3. Type 2 + // For a type-1 or type-2 chunk, the difference between the previous + // chunk's timestamp and the current chunk's timestamp is sent here. + chunk->header.timestamp += timestamp; + } // the extended-timestamp must be unsigned-int, // 24bits timestamp: 0xffffff = 16777215ms = 16777.215s = 4.66h