Skip to content

Commit 577cd29

Browse files
authoredDec 25, 2022
MP3: Fix bug for TS or HLS with mp3 codec. v4.0.269 (#296) (#3333)
* MP3: Fix bug for TS or HLS with mp3 codec. v4.0.269 (#296) 1. Refresh HLS audio codec if changed in stream. 2. Refresh TS audio codec if changed in stream. 3. Fix mp3 demux bug in SrsFormat::audio_mp3_demux. 4. Use 3(MPEG1) not 4(MPEG2) as PMT stream type, follow FFmpeg. 5. MP3: Update utest for mp3 sample parsing. 6. MP3: Ignore empty frame sample. 7. UTest: Fix utest failed, do not copy files.
1 parent 2573a25 commit 577cd29

10 files changed

+109
-38
lines changed
 

‎trunk/Dockerfile

-16
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,6 @@ COPY . /srs
1818
WORKDIR /srs/trunk
1919
RUN ./configure --srt=on --jobs=${JOBS} && make -j${JOBS} && make install
2020

21-
# All config files for SRS.
22-
RUN cp -R conf /usr/local/srs/conf && \
23-
cp research/api-server/static-dir/index.html /usr/local/srs/objs/nginx/html/ && \
24-
cp research/api-server/static-dir/favicon.ico /usr/local/srs/objs/nginx/html/ && \
25-
cp research/players/crossdomain.xml /usr/local/srs/objs/nginx/html/ && \
26-
cp -R research/console /usr/local/srs/objs/nginx/html/ && \
27-
cp -R research/players /usr/local/srs/objs/nginx/html/ && \
28-
cp -R 3rdparty/signaling/www/demos /usr/local/srs/objs/nginx/html/
29-
30-
# Copy the shared libraries for FFmpeg.
31-
RUN mkdir -p /usr/local/shared && \
32-
cp $(ldd /usr/local/bin/ffmpeg |grep libxml2 |awk '{print $3}') /usr/local/shared/ && \
33-
cp $(ldd /usr/local/bin/ffmpeg |grep libicuuc |awk '{print $3}') /usr/local/shared/ && \
34-
cp $(ldd /usr/local/bin/ffmpeg |grep libicudata |awk '{print $3}') /usr/local/shared/
35-
3621
############################################################
3722
# dist
3823
############################################################
@@ -46,7 +31,6 @@ RUN echo "BUILDPLATFORM: $BUILDPLATFORM, TARGETPLATFORM: $TARGETPLATFORM"
4631
EXPOSE 1935 1985 8080 8000/udp 10080/udp
4732

4833
# FFMPEG 4.1
49-
COPY --from=build /usr/local/shared/* /lib/
5034
COPY --from=build /usr/local/bin/ffmpeg /usr/local/srs/objs/ffmpeg/bin/ffmpeg
5135
# SRS binary, config files and srs-console.
5236
COPY --from=build /usr/local/srs /usr/local/srs

‎trunk/doc/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ The changelog for SRS.
88

99
## SRS 4.0 Changelog
1010

11+
* v4.0, 2022-12-24, For [#296](https://github.com/ossrs/srs/issues/296): MP3: Fix bug for TS or HLS with mp3 codec. v4.0.269
1112
* v4.0, 2022-11-22, Pick [#3079](https://github.com/ossrs/srs/issues/3079): WebRTC: Fix no audio and video issue for Firefox. v4.0.268
1213
* v4.0, 2022-10-10, For [#2901](https://github.com/ossrs/srs/issues/2901): Edge: Fast disconnect and reconnect. v4.0.267
1314
* v4.0, 2022-09-27, For [#3167](https://github.com/ossrs/srs/issues/3167): WebRTC: Refine sequence jitter algorithm. v4.0.266

‎trunk/src/app/srs_app_hls.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ SrsHlsMuxer::SrsHlsMuxer()
202202
async = new SrsAsyncCallWorker();
203203
context = new SrsTsContext();
204204
segments = new SrsFragmentWindow();
205+
latest_acodec_ = SrsAudioCodecIdForbidden;
205206

206207
memset(key, 0, 16);
207208
memset(iv, 0, 16);
@@ -263,6 +264,24 @@ int SrsHlsMuxer::deviation()
263264
return deviation_ts;
264265
}
265266

267+
SrsAudioCodecId SrsHlsMuxer::latest_acodec()
268+
{
269+
// If current context writer exists, we query from it.
270+
if (current && current->tscw) return current->tscw->acodec();
271+
272+
// Get the configured or updated config.
273+
return latest_acodec_;
274+
}
275+
276+
void SrsHlsMuxer::set_latest_acodec(SrsAudioCodecId v)
277+
{
278+
// Refresh the codec in context writer for current segment.
279+
if (current && current->tscw) current->tscw->set_acodec(v);
280+
281+
// Refresh the codec for future segments.
282+
latest_acodec_ = v;
283+
}
284+
266285
srs_error_t SrsHlsMuxer::initialize()
267286
{
268287
return srs_success;
@@ -371,6 +390,8 @@ srs_error_t SrsHlsMuxer::segment_open()
371390
srs_warn("hls: use aac for other codec=%s", default_acodec_str.c_str());
372391
}
373392
}
393+
// Now that we know the latest audio codec in stream, use it.
394+
if (latest_acodec_ != SrsAudioCodecIdForbidden) default_acodec = latest_acodec_;
374395

375396
// load the default vcodec from config.
376397
SrsVideoCodecId default_vcodec = SrsVideoCodecIdAVC;
@@ -963,6 +984,13 @@ srs_error_t SrsHlsController::on_sequence_header()
963984
srs_error_t SrsHlsController::write_audio(SrsAudioFrame* frame, int64_t pts)
964985
{
965986
srs_error_t err = srs_success;
987+
988+
// Refresh the codec ASAP.
989+
if (muxer->latest_acodec() != frame->acodec()->id) {
990+
srs_trace("HLS: Switch audio codec %d(%s) to %d(%s)", muxer->latest_acodec(), srs_audio_codec_id2str(muxer->latest_acodec()).c_str(),
991+
frame->acodec()->id, srs_audio_codec_id2str(frame->acodec()->id).c_str());
992+
muxer->set_latest_acodec(frame->acodec()->id);
993+
}
966994

967995
// write audio to cache.
968996
if ((err = tsmc->cache_audio(frame, pts)) != srs_success) {

‎trunk/src/app/srs_app_hls.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ class SrsHlsMuxer
156156
SrsHlsSegment* current;
157157
// The ts context, to keep cc continous between ts.
158158
SrsTsContext* context;
159+
private:
160+
// Latest audio codec, parsed from stream.
161+
SrsAudioCodecId latest_acodec_;
159162
public:
160163
SrsHlsMuxer();
161164
virtual ~SrsHlsMuxer();
@@ -166,6 +169,9 @@ class SrsHlsMuxer
166169
virtual std::string ts_url();
167170
virtual srs_utime_t duration();
168171
virtual int deviation();
172+
public:
173+
SrsAudioCodecId latest_acodec();
174+
void set_latest_acodec(SrsAudioCodecId v);
169175
public:
170176
// Initialize the hls muxer.
171177
virtual srs_error_t initialize();

‎trunk/src/app/srs_app_http_stream.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,9 @@ void SrsLiveStream::http_hooks_on_stop(ISrsHttpMessage* r)
773773
srs_error_t SrsLiveStream::streaming_send_messages(ISrsBufferEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs)
774774
{
775775
srs_error_t err = srs_success;
776-
776+
777+
// TODO: In gop cache, we know both the audio and video codec, so we should notice the encoder, which might depends
778+
// on setting the correct codec information, for example, HTTP-TS or HLS will write PMT.
777779
for (int i = 0; i < nb_msgs; i++) {
778780
SrsSharedPtrMessage* msg = msgs[i];
779781

‎trunk/src/core/srs_core_version4.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99

1010
#define VERSION_MAJOR 4
1111
#define VERSION_MINOR 0
12-
#define VERSION_REVISION 268
12+
#define VERSION_REVISION 269
1313

1414
#endif

‎trunk/src/kernel/srs_kernel_codec.cpp

+6-10
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,9 @@ srs_error_t SrsFrame::initialize(SrsCodecConfig* c)
488488
srs_error_t SrsFrame::add_sample(char* bytes, int size)
489489
{
490490
srs_error_t err = srs_success;
491+
492+
// Ignore empty sample.
493+
if (!bytes || size <= 0) return err;
491494

492495
if (nb_samples >= SrsMaxNbSamples) {
493496
return srs_error_new(ERROR_HLS_DECODE_ERROR, "Frame samples overflow");
@@ -1407,20 +1410,13 @@ srs_error_t SrsFormat::audio_mp3_demux(SrsBuffer* stream, int64_t timestamp)
14071410
// we always decode aac then mp3.
14081411
srs_assert(acodec->id == SrsAudioCodecIdMP3);
14091412

1410-
// Update the RAW MP3 data.
1413+
// Update the RAW MP3 data. Note the start is 12 bits syncword 0xFFF, so we should not skip any bytes, for detail
1414+
// please see ISO_IEC_11172-3-MP3-1993.pdf page 20 and 26.
14111415
raw = stream->data() + stream->pos();
14121416
nb_raw = stream->size() - stream->pos();
14131417

1414-
stream->skip(1);
1415-
if (stream->empty()) {
1416-
return err;
1417-
}
1418-
1419-
char* data = stream->data() + stream->pos();
1420-
int size = stream->size() - stream->pos();
1421-
14221418
// mp3 payload.
1423-
if ((err = audio->add_sample(data, size)) != srs_success) {
1419+
if ((err = audio->add_sample(raw, nb_raw)) != srs_success) {
14241420
return srs_error_wrap(err, "add audio frame");
14251421
}
14261422

‎trunk/src/kernel/srs_kernel_ts.cpp

+21-4
Original file line numberDiff line numberDiff line change
@@ -2598,8 +2598,8 @@ SrsTsContextWriter::SrsTsContextWriter(ISrsStreamWriter* w, SrsTsContext* c, Srs
25982598
{
25992599
writer = w;
26002600
context = c;
2601-
2602-
acodec = ac;
2601+
2602+
acodec_ = ac;
26032603
vcodec = vc;
26042604
}
26052605

@@ -2614,7 +2614,7 @@ srs_error_t SrsTsContextWriter::write_audio(SrsTsMessage* audio)
26142614
srs_info("hls: write audio pts=%" PRId64 ", dts=%" PRId64 ", size=%d",
26152615
audio->pts, audio->dts, audio->PES_packet_length);
26162616

2617-
if ((err = context->encode(writer, audio, vcodec, acodec)) != srs_success) {
2617+
if ((err = context->encode(writer, audio, vcodec, acodec_)) != srs_success) {
26182618
return srs_error_wrap(err, "ts: write audio");
26192619
}
26202620
srs_info("hls encode audio ok");
@@ -2629,7 +2629,7 @@ srs_error_t SrsTsContextWriter::write_video(SrsTsMessage* video)
26292629
srs_info("hls: write video pts=%" PRId64 ", dts=%" PRId64 ", size=%d",
26302630
video->pts, video->dts, video->PES_packet_length);
26312631

2632-
if ((err = context->encode(writer, video, vcodec, acodec)) != srs_success) {
2632+
if ((err = context->encode(writer, video, vcodec, acodec_)) != srs_success) {
26332633
return srs_error_wrap(err, "ts: write video");
26342634
}
26352635
srs_info("hls encode video ok");
@@ -2642,6 +2642,16 @@ SrsVideoCodecId SrsTsContextWriter::video_codec()
26422642
return vcodec;
26432643
}
26442644

2645+
SrsAudioCodecId SrsTsContextWriter::acodec()
2646+
{
2647+
return acodec_;
2648+
}
2649+
2650+
void SrsTsContextWriter::set_acodec(SrsAudioCodecId v)
2651+
{
2652+
acodec_ = v;
2653+
}
2654+
26452655
SrsEncFileWriter::SrsEncFileWriter()
26462656
{
26472657
memset(iv,0,16);
@@ -3079,6 +3089,13 @@ srs_error_t SrsTsTransmuxer::write_audio(int64_t timestamp, char* data, int size
30793089
if (format->acodec->id == SrsAudioCodecIdAAC && format->audio->aac_packet_type == SrsAudioAacFrameTraitSequenceHeader) {
30803090
return err;
30813091
}
3092+
3093+
// Switch audio codec if not AAC.
3094+
if (tscw->acodec() != format->acodec->id) {
3095+
srs_trace("TS: Switch audio codec %d(%s) to %d(%s)", tscw->acodec(), srs_audio_codec_id2str(tscw->acodec()).c_str(),
3096+
format->acodec->id, srs_audio_codec_id2str(format->acodec->id).c_str());
3097+
tscw->set_acodec(format->acodec->id);
3098+
}
30823099

30833100
// the dts calc from rtmp/flv header.
30843101
// @remark for http ts stream, the timestamp is always monotonically increase,

‎trunk/src/kernel/srs_kernel_ts.hpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ enum SrsTsPidApply
9797
SrsTsPidApplyAudio, // vor audio
9898
};
9999

100-
// Table 2-29 - Stream type assignments
100+
// Table 2-29 - Stream type assignments, hls-mpeg-ts-iso13818-1.pdf, page 66
101101
enum SrsTsStream
102102
{
103103
// ITU-T | ISO/IEC Reserved
@@ -106,8 +106,8 @@ enum SrsTsStream
106106
// ISO/IEC 11172 Video
107107
// ITU-T Rec. H.262 | ISO/IEC 13818-2 Video or ISO/IEC 11172-2 constrained parameter video stream
108108
// ISO/IEC 11172 Audio
109+
SrsTsStreamAudioMp3 = 0x03,
109110
// ISO/IEC 13818-3 Audio
110-
SrsTsStreamAudioMp3 = 0x04,
111111
// ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections
112112
// ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES packets containing private data
113113
// ISO/IEC 13522 MHEG
@@ -1243,7 +1243,7 @@ class SrsTsContextWriter
12431243
// User must config the codec in right way.
12441244
// @see https://github.com/ossrs/srs/issues/301
12451245
SrsVideoCodecId vcodec;
1246-
SrsAudioCodecId acodec;
1246+
SrsAudioCodecId acodec_;
12471247
private:
12481248
SrsTsContext* context;
12491249
ISrsStreamWriter* writer;
@@ -1259,6 +1259,10 @@ class SrsTsContextWriter
12591259
public:
12601260
// get the video codec of ts muxer.
12611261
virtual SrsVideoCodecId video_codec();
1262+
public:
1263+
// Get and set the audio codec.
1264+
SrsAudioCodecId acodec();
1265+
void set_acodec(SrsAudioCodecId v);
12621266
};
12631267

12641268
// Used for HLS Encryption

‎trunk/src/utest/srs_utest_kernel.cpp

+36-3
Original file line numberDiff line numberDiff line change
@@ -3391,11 +3391,23 @@ VOID TEST(KernelCodecTest, AVFrame)
33913391
EXPECT_TRUE(20 == f.samples[1].size);
33923392
EXPECT_TRUE(2 == f.nb_samples);
33933393
}
3394+
3395+
3396+
if (true) {
3397+
SrsAudioFrame f;
3398+
EXPECT_TRUE(0 == f.nb_samples);
3399+
3400+
HELPER_EXPECT_SUCCESS(f.add_sample((char*)1, 0));
3401+
EXPECT_TRUE(0 == f.nb_samples);
3402+
3403+
HELPER_EXPECT_SUCCESS(f.add_sample(NULL, 1));
3404+
EXPECT_TRUE(0 == f.nb_samples);
3405+
}
33943406

33953407
if (true) {
33963408
SrsAudioFrame f;
33973409
for (int i = 0; i < SrsMaxNbSamples; i++) {
3398-
HELPER_EXPECT_SUCCESS(f.add_sample((char*)(int64_t)i, i*10));
3410+
HELPER_EXPECT_SUCCESS(f.add_sample((char*)(int64_t)(i + 1), i*10 + 1));
33993411
}
34003412

34013413
srs_error_t err = f.add_sample((char*)1, 1);
@@ -3502,18 +3514,39 @@ VOID TEST(KernelCodecTest, AudioFormat)
35023514
HELPER_EXPECT_SUCCESS(f.on_audio(0, (char*)"\x00", 0));
35033515
HELPER_EXPECT_SUCCESS(f.on_audio(0, (char*)"\x00", 1));
35043516
}
3505-
3517+
3518+
// For MP3
35063519
if (true) {
35073520
SrsFormat f;
35083521
HELPER_EXPECT_SUCCESS(f.initialize());
3522+
HELPER_EXPECT_SUCCESS(f.on_audio(0, (char*)"\x20", 1));
3523+
EXPECT_TRUE(0 == f.nb_raw);
3524+
EXPECT_TRUE(0 == f.audio->nb_samples);
3525+
35093526
HELPER_EXPECT_SUCCESS(f.on_audio(0, (char*)"\x20\x00", 2));
35103527
EXPECT_TRUE(1 == f.nb_raw);
3511-
EXPECT_TRUE(0 == f.audio->nb_samples);
3528+
EXPECT_TRUE(1 == f.audio->nb_samples);
35123529

35133530
HELPER_EXPECT_SUCCESS(f.on_audio(0, (char*)"\x20\x00\x00", 3));
35143531
EXPECT_TRUE(2 == f.nb_raw);
35153532
EXPECT_TRUE(1 == f.audio->nb_samples);
35163533
}
3534+
3535+
// For AAC
3536+
if (true) {
3537+
SrsFormat f;
3538+
HELPER_EXPECT_SUCCESS(f.initialize());
3539+
HELPER_EXPECT_FAILED(f.on_audio(0, (char*)"\xa0", 1));
3540+
3541+
HELPER_EXPECT_SUCCESS(f.on_audio(0, (char*)"\xaf\x00\x12\x10", 4));
3542+
HELPER_EXPECT_SUCCESS(f.on_audio(0, (char*)"\xa0\x01", 2));
3543+
EXPECT_TRUE(0 == f.nb_raw);
3544+
EXPECT_TRUE(0 == f.audio->nb_samples);
3545+
3546+
HELPER_EXPECT_SUCCESS(f.on_audio(0, (char*)"\xa0\x01\x00", 3));
3547+
EXPECT_TRUE(1 == f.nb_raw);
3548+
EXPECT_TRUE(1 == f.audio->nb_samples);
3549+
}
35173550

35183551
if (true) {
35193552
SrsFormat f;

0 commit comments

Comments
 (0)