Skip to content

Commit eb90d77

Browse files
author
Haibo Chen
committed
DVR: support mp3 audio codec
1 parent a830289 commit eb90d77

6 files changed

+167
-13
lines changed

trunk/src/app/srs_app_dvr.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ srs_error_t SrsDvrMp4Segmenter::encode_audio(SrsSharedPtrMessage* audio, SrsForm
462462
SrsAudioChannels channels = format->acodec->sound_type;
463463

464464
SrsAudioAacFrameTrait ct = format->audio->aac_packet_type;
465-
if (ct == SrsAudioAacFrameTraitSequenceHeader) {
465+
if (ct == SrsAudioAacFrameTraitSequenceHeader || (ct == SrsAudioMp3FrameTrait)) {
466466
enc->acodec = sound_format;
467467
enc->sample_rate = sound_rate;
468468
enc->sound_bits = sound_size;

trunk/src/kernel/srs_kernel_codec.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,7 @@ srs_error_t SrsFormat::audio_mp3_demux(SrsBuffer* stream, int64_t timestamp)
13491349

13501350
audio->cts = 0;
13511351
audio->dts = timestamp;
1352+
audio->aac_packet_type = SrsAudioMp3FrameTrait;
13521353

13531354
// @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
13541355
int8_t sound_format = stream->read_1bytes();

trunk/src/kernel/srs_kernel_codec.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ enum SrsAudioAacFrameTrait
167167
SrsAudioOpusFrameTraitRaw = 2,
168168
SrsAudioOpusFrameTraitSamplingRate = 4,
169169
SrsAudioOpusFrameTraitAudioLevel = 8,
170+
171+
// 16/32 reserved for g711a/g711u
172+
173+
// For MP3
174+
SrsAudioMp3FrameTrait = 64,
170175
};
171176

172177
/**

trunk/src/kernel/srs_kernel_mp4.cpp

+33-12
Original file line numberDiff line numberDiff line change
@@ -1812,11 +1812,17 @@ SrsAudioCodecId SrsMp4TrackBox::soun_codec()
18121812
if (box->entry_count() == 0) {
18131813
return SrsAudioCodecIdForbidden;
18141814
}
1815-
1816-
SrsMp4SampleEntry* entry = box->entrie_at(0);
1817-
switch(entry->type) {
1818-
case SrsMp4BoxTypeMP4A: return SrsAudioCodecIdAAC;
1819-
default: return SrsAudioCodecIdForbidden;
1815+
1816+
SrsMp4EsdsBox* esds_box = mp4a()->esds();
1817+
switch (esds_box->es->decConfigDescr.objectTypeIndication)
1818+
{
1819+
case SrsMp4ObjectTypeAac:
1820+
return SrsAudioCodecIdAAC;
1821+
case SrsMp4ObjectTypeMp3:
1822+
case SrsMp4ObjectTypeMp1a:
1823+
return SrsAudioCodecIdMP3;
1824+
default:
1825+
return SrsAudioCodecIdForbidden;
18201826
}
18211827
}
18221828

@@ -3429,7 +3435,7 @@ srs_error_t SrsMp4DecoderConfigDescriptor::encode_payload(SrsBuffer* buf)
34293435
buf->write_3bytes(bufferSizeDB);
34303436
buf->write_4bytes(maxBitrate);
34313437
buf->write_4bytes(avgBitrate);
3432-
3438+
34333439
if (decSpecificInfo && (err = decSpecificInfo->encode(buf)) != srs_success) {
34343440
return srs_error_wrap(err, "encode des specific info");
34353441
}
@@ -3440,7 +3446,7 @@ srs_error_t SrsMp4DecoderConfigDescriptor::encode_payload(SrsBuffer* buf)
34403446
srs_error_t SrsMp4DecoderConfigDescriptor::decode_payload(SrsBuffer* buf)
34413447
{
34423448
srs_error_t err = srs_success;
3443-
3449+
34443450
objectTypeIndication = (SrsMp4ObjectType)buf->read_1bytes();
34453451

34463452
uint8_t v = buf->read_1bytes();
@@ -5488,7 +5494,7 @@ srs_error_t SrsMp4Decoder::parse_moov(SrsMp4MovieBox* moov)
54885494
if (vide && !avcc) {
54895495
return srs_error_new(ERROR_MP4_ILLEGAL_MOOV, "missing video sequence header");
54905496
}
5491-
if (soun && !asc) {
5497+
if (soun && (soun->soun_codec() == SrsAudioCodecIdAAC && !asc)) {
54925498
return srs_error_new(ERROR_MP4_ILLEGAL_MOOV, "missing audio sequence header");
54935499
}
54945500

@@ -5910,13 +5916,15 @@ srs_error_t SrsMp4Encoder::flush()
59105916
es->ES_ID = 0x02;
59115917

59125918
SrsMp4DecoderConfigDescriptor& desc = es->decConfigDescr;
5913-
desc.objectTypeIndication = SrsMp4ObjectTypeAac;
5919+
desc.objectTypeIndication = get_audio_object_type();
59145920
desc.streamType = SrsMp4StreamTypeAudioStream;
59155921
srs_freep(desc.decSpecificInfo);
59165922

5917-
SrsMp4DecoderSpecificInfo* asc = new SrsMp4DecoderSpecificInfo();
5918-
desc.decSpecificInfo = asc;
5919-
asc->asc = pasc;;
5923+
if (SrsMp4ObjectTypeAac == desc.objectTypeIndication) {
5924+
SrsMp4DecoderSpecificInfo* asc = new SrsMp4DecoderSpecificInfo();
5925+
desc.decSpecificInfo = asc;
5926+
asc->asc = pasc;
5927+
}
59205928
}
59215929

59225930
if ((err = samples->write(moov)) != srs_success) {
@@ -6043,6 +6051,19 @@ srs_error_t SrsMp4Encoder::do_write_sample(SrsMp4Sample* ps, uint8_t* sample, ui
60436051
mdat_bytes += nb_sample;
60446052

60456053
return err;
6054+
}
6055+
6056+
SrsMp4ObjectType SrsMp4Encoder::get_audio_object_type()
6057+
{
6058+
switch (acodec)
6059+
{
6060+
case SrsAudioCodecIdAAC:
6061+
return SrsMp4ObjectTypeAac;
6062+
case SrsAudioCodecIdMP3:
6063+
return (srs_flv_srates[sample_rate] > 24000) ? SrsMp4ObjectTypeMp1a : SrsMp4ObjectTypeMp3; // 11172 - 3
6064+
default:
6065+
return SrsMp4ObjectTypeForbidden;
6066+
}
60466067
}
60476068

60486069
SrsMp4M2tsInitEncoder::SrsMp4M2tsInitEncoder()

trunk/src/kernel/srs_kernel_mp4.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -1369,6 +1369,10 @@ enum SrsMp4ObjectType
13691369
SrsMp4ObjectTypeForbidden = 0x00,
13701370
// Audio ISO/IEC 14496-3
13711371
SrsMp4ObjectTypeAac = 0x40,
1372+
// Audio ISO/IEC 13818-3
1373+
SrsMp4ObjectTypeMp3 = 0x69,
1374+
// Audio ISO/IEC 11172-3
1375+
SrsMp4ObjectTypeMp1a = 0x6B,
13721376
};
13731377

13741378
// Table 6 — streamType Values
@@ -2072,6 +2076,7 @@ class SrsMp4Encoder
20722076
private:
20732077
virtual srs_error_t copy_sequence_header(SrsFormat* format, bool vsh, uint8_t* sample, uint32_t nb_sample);
20742078
virtual srs_error_t do_write_sample(SrsMp4Sample* ps, uint8_t* sample, uint32_t nb_sample);
2079+
virtual SrsMp4ObjectType get_audio_object_type();
20752080
};
20762081

20772082
// A fMP4 encoder, to write the init.mp4 with sequence header.

trunk/src/utest/srs_utest_kernel.cpp

+122
Original file line numberDiff line numberDiff line change
@@ -5033,6 +5033,8 @@ VOID TEST(KernelMP4Test, CoverMP4CodecSingleFrame)
50335033
));
50345034
}
50355035

5036+
enc.acodec = SrsAudioCodecIdAAC;
5037+
50365038
HELPER_EXPECT_SUCCESS(enc.flush());
50375039
//mock_print_mp4(string(f.data(), f.filesize()));
50385040
}
@@ -5147,6 +5149,8 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleVideos)
51475149
));
51485150
}
51495151

5152+
enc.acodec = SrsAudioCodecIdAAC;
5153+
51505154
// Flush encoder.
51515155
HELPER_EXPECT_SUCCESS(enc.flush());
51525156
//mock_print_mp4(string(f.data(), f.filesize()));
@@ -5245,6 +5249,8 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleCTTs)
52455249
));
52465250
}
52475251

5252+
enc.acodec = SrsAudioCodecIdAAC;
5253+
52485254
// Flush encoder.
52495255
HELPER_EXPECT_SUCCESS(enc.flush());
52505256
//mock_print_mp4(string(f.data(), f.filesize()));
@@ -5357,6 +5363,8 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleAVs)
53575363
));
53585364
}
53595365

5366+
enc.acodec = SrsAudioCodecIdAAC;
5367+
53605368
// Flush encoder.
53615369
HELPER_EXPECT_SUCCESS(enc.flush());
53625370
//mock_print_mp4(string(f.data(), f.filesize()));
@@ -5397,6 +5405,120 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleAVs)
53975405
}
53985406
}
53995407

5408+
VOID TEST(KernelMP4Test, CoverMP4MultipleAVsWithMp3)
5409+
{
5410+
srs_error_t err;
5411+
5412+
MockSrsFileWriter f;
5413+
5414+
// Encode frames.
5415+
// V-A V-V
5416+
if (true) {
5417+
SrsMp4Encoder enc; SrsFormat fmt;
5418+
HELPER_EXPECT_SUCCESS(enc.initialize(&f));
5419+
HELPER_EXPECT_SUCCESS(fmt.initialize());
5420+
5421+
// Sequence header, V-A
5422+
if (true) {
5423+
uint8_t raw[] = {
5424+
0x17, 0x00, 0x00, 0x00, 0x00, 0x01, 0x64, 0x00, 0x20, 0xff, 0xe1, 0x00, 0x19, 0x67, 0x64, 0x00, 0x20, 0xac, 0xd9, 0x40, 0xc0, 0x29, 0xb0, 0x11, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x32, 0x0f, 0x18, 0x31, 0x96, 0x01, 0x00, 0x05, 0x68, 0xeb, 0xec, 0xb2, 0x2c
5425+
};
5426+
HELPER_EXPECT_SUCCESS(fmt.on_video(0, (char*)raw, sizeof(raw)));
5427+
HELPER_EXPECT_SUCCESS(enc.write_sample(
5428+
&fmt, SrsMp4HandlerTypeVIDE, fmt.video->frame_type, fmt.video->avc_packet_type, 0, 0, (uint8_t*)fmt.raw, fmt.nb_raw
5429+
));
5430+
EXPECT_EQ(768, (int)enc.width); EXPECT_EQ(320, (int)enc.height);
5431+
}
5432+
5433+
if (true) {
5434+
uint8_t raw[] = {
5435+
0xaf, 0x00, 0x12, 0x10
5436+
};
5437+
HELPER_EXPECT_SUCCESS(fmt.on_audio(0, (char*)raw, sizeof(raw)));
5438+
HELPER_EXPECT_SUCCESS(enc.write_sample(
5439+
&fmt, SrsMp4HandlerTypeSOUN, 0x00, fmt.audio->aac_packet_type, 0, 0, (uint8_t*)fmt.raw, fmt.nb_raw
5440+
));
5441+
}
5442+
5443+
// Frame group #0, V-A-A-V
5444+
if (true) {
5445+
uint8_t raw[] = {
5446+
0x17, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x7b, 0x41, 0x9a, 0x21, 0x6c, 0x42, 0x1f, 0x00, 0x00, 0xf1, 0x68, 0x1a, 0x35, 0x84, 0xb3, 0xee, 0xe0, 0x61, 0xba, 0x4e, 0xa8, 0x52, 0x48, 0x50, 0x59, 0x75, 0x42, 0xd9, 0x96, 0x4a, 0x51, 0x38, 0x2c, 0x63, 0x5e, 0x41, 0xc9, 0x70, 0x60, 0x9d, 0x13, 0x53, 0xc2, 0xa8, 0xf5, 0x45, 0x86, 0xc5, 0x3e, 0x28, 0x1a, 0x69, 0x5f, 0x71, 0x1e, 0x51, 0x74, 0x0e, 0x31, 0x47, 0x3c, 0xd3, 0xd2, 0x10, 0x25, 0x45, 0xc5, 0xb7, 0x31, 0xec, 0x7f, 0xd8, 0x02, 0xae, 0xa4, 0x77, 0x6d, 0xcb, 0xc6, 0x1e, 0x2f, 0xa2, 0xd1, 0x12, 0x08, 0x34, 0x52, 0xea, 0xe8, 0x0b, 0x4f, 0x81, 0x21, 0x4f, 0x71, 0x3f, 0xf2, 0xad, 0x02, 0x58, 0xdf, 0x9e, 0x31, 0x86, 0x9b, 0x1b, 0x41, 0xbf, 0x2a, 0x09, 0x00, 0x43, 0x5c, 0xa1, 0x7e, 0x76, 0x59, 0xef, 0xa6, 0xfc, 0x82, 0xb2, 0x72, 0x5a
5447+
};
5448+
HELPER_EXPECT_SUCCESS(fmt.on_video(0, (char*)raw, sizeof(raw)));
5449+
HELPER_EXPECT_SUCCESS(enc.write_sample(
5450+
&fmt, SrsMp4HandlerTypeVIDE, fmt.video->frame_type, fmt.video->avc_packet_type, 0, 0, (uint8_t*)fmt.raw, fmt.nb_raw
5451+
));
5452+
}
5453+
5454+
if (true) {
5455+
uint8_t raw[] = {
5456+
0xaf, 0x01, 0x21, 0x11, 0x45, 0x00, 0x14, 0x50, 0x01, 0x46, 0xf3, 0xf1, 0x0a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e
5457+
};
5458+
HELPER_EXPECT_SUCCESS(fmt.on_audio(0, (char*)raw, sizeof(raw)));
5459+
HELPER_EXPECT_SUCCESS(enc.write_sample(
5460+
&fmt, SrsMp4HandlerTypeSOUN, 0x00, fmt.audio->aac_packet_type, 0, 0, (uint8_t*)fmt.raw, fmt.nb_raw
5461+
));
5462+
}
5463+
5464+
if (true) {
5465+
uint8_t raw[] = {
5466+
0xaf, 0x01, 0x21, 0x11, 0x45, 0x00, 0x14, 0x50, 0x01, 0x46, 0xf3, 0xf1, 0x0a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e
5467+
};
5468+
HELPER_EXPECT_SUCCESS(fmt.on_audio(0, (char*)raw, sizeof(raw)));
5469+
HELPER_EXPECT_SUCCESS(enc.write_sample(
5470+
&fmt, SrsMp4HandlerTypeSOUN, 0x00, fmt.audio->aac_packet_type, 20, 20, (uint8_t*)fmt.raw, fmt.nb_raw
5471+
));
5472+
}
5473+
5474+
if (true) {
5475+
uint8_t raw[] = {
5476+
0x27, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x7b, 0x41, 0x9a, 0x21, 0x6c, 0x42, 0x1f, 0x00, 0x00, 0xf1, 0x68, 0x1a, 0x35, 0x84, 0xb3, 0xee, 0xe0, 0x61, 0xba, 0x4e, 0xa8, 0x52, 0x48, 0x50, 0x59, 0x75, 0x42, 0xd9, 0x96, 0x4a, 0x51, 0x38, 0x2c, 0x63, 0x5e, 0x41, 0xc9, 0x70, 0x60, 0x9d, 0x13, 0x53, 0xc2, 0xa8, 0xf5, 0x45, 0x86, 0xc5, 0x3e, 0x28, 0x1a, 0x69, 0x5f, 0x71, 0x1e, 0x51, 0x74, 0x0e, 0x31, 0x47, 0x3c, 0xd3, 0xd2, 0x10, 0x25, 0x45, 0xc5, 0xb7, 0x31, 0xec, 0x7f, 0xd8, 0x02, 0xae, 0xa4, 0x77, 0x6d, 0xcb, 0xc6, 0x1e, 0x2f, 0xa2, 0xd1, 0x12, 0x08, 0x34, 0x52, 0xea, 0xe8, 0x0b, 0x4f, 0x81, 0x21, 0x4f, 0x71, 0x3f, 0xf2, 0xad, 0x02, 0x58, 0xdf, 0x9e, 0x31, 0x86, 0x9b, 0x1b, 0x41, 0xbf, 0x2a, 0x09, 0x00, 0x43, 0x5c, 0xa1, 0x7e, 0x76, 0x59, 0xef, 0xa6, 0xfc, 0x82, 0xb2, 0x72, 0x5a
5477+
};
5478+
HELPER_EXPECT_SUCCESS(fmt.on_video(0, (char*)raw, sizeof(raw)));
5479+
HELPER_EXPECT_SUCCESS(enc.write_sample(
5480+
&fmt, SrsMp4HandlerTypeVIDE, fmt.video->frame_type, fmt.video->avc_packet_type, 40, 40, (uint8_t*)fmt.raw, fmt.nb_raw
5481+
));
5482+
}
5483+
5484+
enc.acodec = SrsAudioCodecIdMP3;
5485+
5486+
// Flush encoder.
5487+
HELPER_EXPECT_SUCCESS(enc.flush());
5488+
//mock_print_mp4(string(f.data(), f.filesize()));
5489+
}
5490+
5491+
// Decode frames.
5492+
if (true) {
5493+
MockSrsFileReader fr((const char*)f.data(), f.filesize());
5494+
SrsMp4Decoder dec; HELPER_EXPECT_SUCCESS(dec.initialize(&fr));
5495+
5496+
SrsMp4HandlerType ht; uint16_t ft, ct; uint32_t dts, pts, nb_sample; uint8_t* sample = NULL;
5497+
5498+
// Sequence header.
5499+
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
5500+
EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsVideoAvcFrameTraitSequenceHeader, ct);
5501+
srs_freepa(sample);
5502+
5503+
// Frames order by dts asc.
5504+
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
5505+
EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioMp3FrameTrait, ct);
5506+
srs_freepa(sample);
5507+
5508+
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
5509+
EXPECT_EQ(0, (int)dts); EXPECT_EQ(87, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsVideoAvcFrameTraitSequenceHeader, ct);
5510+
srs_freepa(sample);
5511+
5512+
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
5513+
EXPECT_EQ(20, (int)dts); EXPECT_EQ(87, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsVideoAvcFrameTraitSequenceHeader, ct);
5514+
srs_freepa(sample);
5515+
5516+
HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample));
5517+
EXPECT_EQ(40, (int)dts); EXPECT_EQ(40, (int)pts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioMp3FrameTrait, ct);
5518+
srs_freepa(sample);
5519+
}
5520+
}
5521+
54005522
VOID TEST(KernelMP4Test, CoverMP4CodecErrorNoFrames)
54015523
{
54025524
srs_error_t err;

0 commit comments

Comments
 (0)