From 7584c47aafc70e20cf7b96f6bbf680adace3ea1a Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 26 Dec 2019 18:05:17 +0800 Subject: [PATCH] Fix #1105, dvr mp4 supports playing on Chrome/Safari/Firefox. 3.0.86 --- README.md | 2 ++ trunk/src/app/srs_app_dvr.cpp | 4 +-- trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_mp4.cpp | 44 +++++++++++++++++++++------- trunk/src/kernel/srs_kernel_mp4.hpp | 4 +-- trunk/src/utest/srs_utest_kernel.cpp | 8 ++--- 6 files changed, 45 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 992f7070d..0c2566e4b 100755 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For previous versions, please read: ## V3 changes +* v3.0, 2019-12-26, For [#1105][bug #1105], dvr mp4 supports playing on Chrome/Safari/Firefox. 3.0.86 * v3.0, 2019-12-26, [3.0 alpha6(3.0.85)][r3.0a6] released. 116056 lines. * v3.0, 2019-12-26, For [#1488][bug #1488], pass client ip to http callback. 3.0.85 * v3.0, 2019-12-25, For [#1537][bug #1537], [#1282][bug #1282], support aarch64 for armv8. 3.0.84 @@ -1565,6 +1566,7 @@ Winlin [bug #1537]: https://github.com/ossrs/srs/issues/1537 [bug #1538]: https://github.com/ossrs/srs/issues/1538 [bug #1282]: https://github.com/ossrs/srs/issues/1282 +[bug #1105]: https://github.com/ossrs/srs/issues/1105 [bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp index 563f7a8d8..35275994d 100644 --- a/trunk/src/app/srs_app_dvr.cpp +++ b/trunk/src/app/srs_app_dvr.cpp @@ -489,7 +489,7 @@ srs_error_t SrsDvrMp4Segmenter::encode_audio(SrsSharedPtrMessage* audio, SrsForm uint32_t nb_sample = (uint32_t)format->nb_raw; uint32_t dts = (uint32_t)audio->timestamp; - if ((err = enc->write_sample(SrsMp4HandlerTypeSOUN, 0x00, ct, dts, dts, sample, nb_sample)) != srs_success) { + if ((err = enc->write_sample(format, SrsMp4HandlerTypeSOUN, 0x00, ct, dts, dts, sample, nb_sample)) != srs_success) { return srs_error_wrap(err, "write sample"); } @@ -515,7 +515,7 @@ srs_error_t SrsDvrMp4Segmenter::encode_video(SrsSharedPtrMessage* video, SrsForm uint8_t* sample = (uint8_t*)format->raw; uint32_t nb_sample = (uint32_t)format->nb_raw; - if ((err = enc->write_sample(SrsMp4HandlerTypeVIDE, frame_type, ct, dts, pts, sample, nb_sample)) != srs_success) { + if ((err = enc->write_sample(format, SrsMp4HandlerTypeVIDE, frame_type, ct, dts, pts, sample, nb_sample)) != srs_success) { return srs_error_wrap(err, "write sample"); } diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 5c377ce52..b43971a5b 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -27,7 +27,7 @@ // The version config. #define VERSION_MAJOR 3 #define VERSION_MINOR 0 -#define VERSION_REVISION 85 +#define VERSION_REVISION 86 // The macros generated by configure script. #include diff --git a/trunk/src/kernel/srs_kernel_mp4.cpp b/trunk/src/kernel/srs_kernel_mp4.cpp index 7be957a80..cf043ee2a 100644 --- a/trunk/src/kernel/srs_kernel_mp4.cpp +++ b/trunk/src/kernel/srs_kernel_mp4.cpp @@ -2047,10 +2047,8 @@ stringstream& SrsMp4TrackHeaderBox::dumps_detail(stringstream& ss, SrsMp4DumpCon if (volume) { ss << ", volume=" << uint32_t(volume>>8) << "." << uint32_t(volume&0xFF); } - - if (width || height) { - ss << ", size=" << uint16_t(width>>16) << "x" << uint16_t(height>>16); - } + + ss << ", size=" << uint16_t(width>>16) << "x" << uint16_t(height>>16); return ss; } @@ -5528,6 +5526,26 @@ srs_error_t SrsMp4Encoder::initialize(ISrsWriteSeeker* ws) return srs_error_wrap(err, "write ftyp"); } } + + // 8B reserved free box. + if (true) { + SrsMp4FreeSpaceBox* freeb = new SrsMp4FreeSpaceBox(SrsMp4BoxTypeFREE); + SrsAutoFree(SrsMp4FreeSpaceBox, freeb); + + int nb_data = freeb->nb_bytes(); + std::vector data(nb_data); + + SrsBuffer* buffer = new SrsBuffer(&data[0], nb_data); + SrsAutoFree(SrsBuffer, buffer); + + if ((err = freeb->encode(buffer)) != srs_success) { + return srs_error_wrap(err, "encode free box"); + } + + if ((err = wsio->write(&data[0], nb_data, NULL)) != srs_success) { + return srs_error_wrap(err, "write free box"); + } + } // Write mdat box. if (true) { @@ -5564,8 +5582,10 @@ srs_error_t SrsMp4Encoder::initialize(ISrsWriteSeeker* ws) return err; } -srs_error_t SrsMp4Encoder::write_sample(SrsMp4HandlerType ht, uint16_t ft, uint16_t ct, uint32_t dts, uint32_t pts, uint8_t* sample, uint32_t nb_sample) -{ +srs_error_t SrsMp4Encoder::write_sample( + SrsFormat* format, SrsMp4HandlerType ht, uint16_t ft, uint16_t ct, uint32_t dts, uint32_t pts, + uint8_t* sample, uint32_t nb_sample +) { srs_error_t err = srs_success; SrsMp4Sample* ps = new SrsMp4Sample(); @@ -5574,7 +5594,7 @@ srs_error_t SrsMp4Encoder::write_sample(SrsMp4HandlerType ht, uint16_t ft, uint1 bool vsh = (ht == SrsMp4HandlerTypeVIDE) && (ct == (uint16_t)SrsVideoAvcFrameTraitSequenceHeader); bool ash = (ht == SrsMp4HandlerTypeSOUN) && (ct == (uint16_t)SrsAudioAacFrameTraitSequenceHeader); if (vsh || ash) { - err = copy_sequence_header(vsh, sample, nb_sample); + err = copy_sequence_header(format, vsh, sample, nb_sample); srs_freep(ps); return err; } @@ -5683,6 +5703,7 @@ srs_error_t SrsMp4Encoder::flush() avc1->width = width; avc1->height = height; + avc1->data_reference_index = 1; SrsMp4AvccBox* avcC = new SrsMp4AvccBox(); avc1->set_avcC(avcC); @@ -5741,6 +5762,7 @@ srs_error_t SrsMp4Encoder::flush() stbl->set_stsd(stsd); SrsMp4AudioSampleEntry* mp4a = new SrsMp4AudioSampleEntry(); + mp4a->data_reference_index = 1; mp4a->samplerate = uint32_t(srs_flv_srates[sample_rate]) << 16; if (sound_bits == SrsAudioSampleBits16bit) { mp4a->samplesize = 16; @@ -5826,7 +5848,7 @@ srs_error_t SrsMp4Encoder::flush() return err; } -srs_error_t SrsMp4Encoder::copy_sequence_header(bool vsh, uint8_t* sample, uint32_t nb_sample) +srs_error_t SrsMp4Encoder::copy_sequence_header(SrsFormat* format, bool vsh, uint8_t* sample, uint32_t nb_sample) { srs_error_t err = srs_success; @@ -5848,8 +5870,10 @@ srs_error_t SrsMp4Encoder::copy_sequence_header(bool vsh, uint8_t* sample, uint3 if (vsh) { pavcc = std::vector(sample, sample + nb_sample); - - // TODO: FIXME: Parse the width and height. + if (format && format->vcodec) { + width = format->vcodec->width; + height = format->vcodec->height; + } } if (!vsh) { diff --git a/trunk/src/kernel/srs_kernel_mp4.hpp b/trunk/src/kernel/srs_kernel_mp4.hpp index b39ca1fff..67608673c 100644 --- a/trunk/src/kernel/srs_kernel_mp4.hpp +++ b/trunk/src/kernel/srs_kernel_mp4.hpp @@ -2024,12 +2024,12 @@ public: // @param pts The output pts in milliseconds. // @param sample The output payload, user must free it. // @param nb_sample The output size of payload. - virtual srs_error_t write_sample(SrsMp4HandlerType ht, uint16_t ft, uint16_t ct, + virtual srs_error_t write_sample(SrsFormat* format, SrsMp4HandlerType ht, uint16_t ft, uint16_t ct, uint32_t dts, uint32_t pts, uint8_t* sample, uint32_t nb_sample); // Flush the encoder, to write the moov. virtual srs_error_t flush(); private: - virtual srs_error_t copy_sequence_header(bool vsh, uint8_t* sample, uint32_t nb_sample); + virtual srs_error_t copy_sequence_header(SrsFormat* format, bool vsh, uint8_t* sample, uint32_t nb_sample); virtual srs_error_t do_write_sample(SrsMp4Sample* ps, uint8_t* sample, uint32_t nb_sample); }; diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 47908ddae..18ac72b10 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -4589,7 +4589,7 @@ VOID TEST(KernelMP4Test, CoverMP4Codec) }; EXPECT_TRUE(srs_success == fmt.on_video(0, (char*)raw, sizeof(raw))); EXPECT_TRUE(srs_success == enc.write_sample( - SrsMp4HandlerTypeVIDE, fmt.video->frame_type, fmt.video->avc_packet_type, 0, 0, (uint8_t*)fmt.raw, fmt.nb_raw + NULL, SrsMp4HandlerTypeVIDE, fmt.video->frame_type, fmt.video->avc_packet_type, 0, 0, (uint8_t*)fmt.raw, fmt.nb_raw )); } @@ -4599,7 +4599,7 @@ VOID TEST(KernelMP4Test, CoverMP4Codec) }; EXPECT_TRUE(srs_success == fmt.on_audio(0, (char*)raw, sizeof(raw))); EXPECT_TRUE(srs_success == enc.write_sample( - SrsMp4HandlerTypeSOUN, 0x00, fmt.audio->aac_packet_type, 0, 0, (uint8_t*)fmt.raw, fmt.nb_raw + NULL, SrsMp4HandlerTypeSOUN, 0x00, fmt.audio->aac_packet_type, 0, 0, (uint8_t*)fmt.raw, fmt.nb_raw )); } @@ -4615,7 +4615,7 @@ VOID TEST(KernelMP4Test, CoverMP4Codec) }; EXPECT_TRUE(srs_success == fmt.on_audio(0, (char*)raw, sizeof(raw))); EXPECT_TRUE(srs_success == enc.write_sample( - SrsMp4HandlerTypeSOUN, 0x00, fmt.audio->aac_packet_type, 34, 34, (uint8_t*)fmt.raw, fmt.nb_raw + NULL, SrsMp4HandlerTypeSOUN, 0x00, fmt.audio->aac_packet_type, 34, 34, (uint8_t*)fmt.raw, fmt.nb_raw )); } @@ -4634,7 +4634,7 @@ VOID TEST(KernelMP4Test, CoverMP4Codec) }; EXPECT_TRUE(srs_success == fmt.on_video(0, (char*)raw, sizeof(raw))); EXPECT_TRUE(srs_success == enc.write_sample( - SrsMp4HandlerTypeVIDE, fmt.video->frame_type, fmt.video->avc_packet_type, 40, 40, (uint8_t*)fmt.raw, fmt.nb_raw + NULL, SrsMp4HandlerTypeVIDE, fmt.video->frame_type, fmt.video->avc_packet_type, 40, 40, (uint8_t*)fmt.raw, fmt.nb_raw )); }