正在显示
5 个修改的文件
包含
162 行增加
和
15 行删除
| @@ -123,7 +123,6 @@ Please select your language: | @@ -123,7 +123,6 @@ Please select your language: | ||
| 123 | * [SRS 2.0 English][v2_EN_Home] | 123 | * [SRS 2.0 English][v2_EN_Home] |
| 124 | * [SRS 2.0 Chinese][v2_CN_Home] | 124 | * [SRS 2.0 Chinese][v2_CN_Home] |
| 125 | 125 | ||
| 126 | -<<<<<<< HEAD | ||
| 127 | ### SRS 3.0 wiki | 126 | ### SRS 3.0 wiki |
| 128 | 127 | ||
| 129 | Please select your language: | 128 | Please select your language: |
| @@ -182,6 +181,8 @@ Please select your language: | @@ -182,6 +181,8 @@ Please select your language: | ||
| 182 | - [ ] Support MPEG-DASH, the future streaming protocol, read [#299][bug #299]. | 181 | - [ ] Support MPEG-DASH, the future streaming protocol, read [#299][bug #299]. |
| 183 | - [ ] Support HLS+, please read [#466][bug #466] and [#468][bug #468]. | 182 | - [ ] Support HLS+, please read [#466][bug #466] and [#468][bug #468]. |
| 184 | 183 | ||
| 184 | +### Change Logs | ||
| 185 | + | ||
| 185 | ### V3 changes | 186 | ### V3 changes |
| 186 | 187 | ||
| 187 | * v3.0, 2017-01-19, for [#742][bug #742] refine source, meta and origin hub. 3.0.16 | 188 | * v3.0, 2017-01-19, for [#742][bug #742] refine source, meta and origin hub. 3.0.16 |
| @@ -250,6 +250,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -250,6 +250,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 250 | #define ERROR_MP4_BOX_ILLEGAL_BRAND 3074 | 250 | #define ERROR_MP4_BOX_ILLEGAL_BRAND 3074 |
| 251 | #define ERROR_MP4_NOT_NON_SEEKABLE 3075 | 251 | #define ERROR_MP4_NOT_NON_SEEKABLE 3075 |
| 252 | #define ERROR_MP4_ESDS_SL_Config 3076 | 252 | #define ERROR_MP4_ESDS_SL_Config 3076 |
| 253 | +#define ERROR_MP4_ILLEGAL_MOOV 3077 | ||
| 253 | 254 | ||
| 254 | /////////////////////////////////////////////////////// | 255 | /////////////////////////////////////////////////////// |
| 255 | // HTTP/StreamCaster/KAFKA protocol error. | 256 | // HTTP/StreamCaster/KAFKA protocol error. |
| @@ -141,15 +141,17 @@ extern ISrsThreadContext* _srs_context; | @@ -141,15 +141,17 @@ extern ISrsThreadContext* _srs_context; | ||
| 141 | #define srs_trace(msg, ...) _srs_log->trace(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) | 141 | #define srs_trace(msg, ...) _srs_log->trace(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 142 | #define srs_warn(msg, ...) _srs_log->warn(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) | 142 | #define srs_warn(msg, ...) _srs_log->warn(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 143 | #define srs_error(msg, ...) _srs_log->error(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) | 143 | #define srs_error(msg, ...) _srs_log->error(NULL, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 144 | +#endif | ||
| 144 | // use __FUNCTION__ to print c method | 145 | // use __FUNCTION__ to print c method |
| 145 | -#elif 0 | 146 | +#if 0 |
| 146 | #define srs_verbose(msg, ...) _srs_log->verbose(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | 147 | #define srs_verbose(msg, ...) _srs_log->verbose(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 147 | #define srs_info(msg, ...) _srs_log->info(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | 148 | #define srs_info(msg, ...) _srs_log->info(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 148 | #define srs_trace(msg, ...) _srs_log->trace(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | 149 | #define srs_trace(msg, ...) _srs_log->trace(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 149 | #define srs_warn(msg, ...) _srs_log->warn(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | 150 | #define srs_warn(msg, ...) _srs_log->warn(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 150 | #define srs_error(msg, ...) _srs_log->error(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | 151 | #define srs_error(msg, ...) _srs_log->error(__FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 152 | +#endif | ||
| 151 | // use __PRETTY_FUNCTION__ to print c++ class:method | 153 | // use __PRETTY_FUNCTION__ to print c++ class:method |
| 152 | -#else | 154 | +#if 0 |
| 153 | #define srs_verbose(msg, ...) _srs_log->verbose(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | 155 | #define srs_verbose(msg, ...) _srs_log->verbose(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 154 | #define srs_info(msg, ...) _srs_log->info(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | 156 | #define srs_info(msg, ...) _srs_log->info(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| 155 | #define srs_trace(msg, ...) _srs_log->trace(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) | 157 | #define srs_trace(msg, ...) _srs_log->trace(__PRETTY_FUNCTION__, _srs_context->get_id(), msg, ##__VA_ARGS__) |
| @@ -121,6 +121,19 @@ bool SrsMp4Box::is_mdat() | @@ -121,6 +121,19 @@ bool SrsMp4Box::is_mdat() | ||
| 121 | return type == SrsMp4BoxTypeMDAT; | 121 | return type == SrsMp4BoxTypeMDAT; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | +SrsMp4Box* SrsMp4Box::get(SrsMp4BoxType bt) | ||
| 125 | +{ | ||
| 126 | + vector<SrsMp4Box*>::iterator it; | ||
| 127 | + for (it = boxes.begin(); it != boxes.end(); ++it) { | ||
| 128 | + SrsMp4Box* box = *it; | ||
| 129 | + if (box->type == bt) { | ||
| 130 | + return box; | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + return NULL; | ||
| 135 | +} | ||
| 136 | + | ||
| 124 | int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox) | 137 | int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox) |
| 125 | { | 138 | { |
| 126 | *ppbox = NULL; | 139 | *ppbox = NULL; |
| @@ -625,6 +638,40 @@ SrsMp4MovieBox::~SrsMp4MovieBox() | @@ -625,6 +638,40 @@ SrsMp4MovieBox::~SrsMp4MovieBox() | ||
| 625 | { | 638 | { |
| 626 | } | 639 | } |
| 627 | 640 | ||
| 641 | +SrsMp4MovieHeaderBox* SrsMp4MovieBox::mvhd() | ||
| 642 | +{ | ||
| 643 | + SrsMp4Box* box = get(SrsMp4BoxTypeMVHD); | ||
| 644 | + return dynamic_cast<SrsMp4MovieHeaderBox*>(box); | ||
| 645 | +} | ||
| 646 | + | ||
| 647 | +SrsMp4TrackBox* SrsMp4MovieBox::video() | ||
| 648 | +{ | ||
| 649 | + for (int i = 0; i < boxes.size(); i++) { | ||
| 650 | + SrsMp4Box* box = boxes.at(i); | ||
| 651 | + if (box->type == SrsMp4BoxTypeTRAK) { | ||
| 652 | + SrsMp4TrackBox* trak = dynamic_cast<SrsMp4TrackBox*>(box); | ||
| 653 | + if ((trak->track_type() & SrsMp4TrackTypeVideo) == SrsMp4TrackTypeVideo) { | ||
| 654 | + return trak; | ||
| 655 | + } | ||
| 656 | + } | ||
| 657 | + } | ||
| 658 | + return NULL; | ||
| 659 | +} | ||
| 660 | + | ||
| 661 | +SrsMp4TrackBox* SrsMp4MovieBox::audio() | ||
| 662 | +{ | ||
| 663 | + for (int i = 0; i < boxes.size(); i++) { | ||
| 664 | + SrsMp4Box* box = boxes.at(i); | ||
| 665 | + if (box->type == SrsMp4BoxTypeTRAK) { | ||
| 666 | + SrsMp4TrackBox* trak = dynamic_cast<SrsMp4TrackBox*>(box); | ||
| 667 | + if ((trak->track_type() & SrsMp4TrackTypeAudio) == SrsMp4TrackTypeAudio) { | ||
| 668 | + return trak; | ||
| 669 | + } | ||
| 670 | + } | ||
| 671 | + } | ||
| 672 | + return NULL; | ||
| 673 | +} | ||
| 674 | + | ||
| 628 | int SrsMp4MovieBox::nb_header() | 675 | int SrsMp4MovieBox::nb_header() |
| 629 | { | 676 | { |
| 630 | return SrsMp4Box::nb_header(); | 677 | return SrsMp4Box::nb_header(); |
| @@ -659,6 +706,11 @@ SrsMp4MovieHeaderBox::~SrsMp4MovieHeaderBox() | @@ -659,6 +706,11 @@ SrsMp4MovieHeaderBox::~SrsMp4MovieHeaderBox() | ||
| 659 | { | 706 | { |
| 660 | } | 707 | } |
| 661 | 708 | ||
| 709 | +uint64_t SrsMp4MovieHeaderBox::duration() | ||
| 710 | +{ | ||
| 711 | + return duration_in_tbn * 1000 / timescale; | ||
| 712 | +} | ||
| 713 | + | ||
| 662 | int SrsMp4MovieHeaderBox::nb_header() | 714 | int SrsMp4MovieHeaderBox::nb_header() |
| 663 | { | 715 | { |
| 664 | int size = SrsMp4FullBox::nb_header(); | 716 | int size = SrsMp4FullBox::nb_header(); |
| @@ -686,12 +738,12 @@ int SrsMp4MovieHeaderBox::encode_header(SrsBuffer* buf) | @@ -686,12 +738,12 @@ int SrsMp4MovieHeaderBox::encode_header(SrsBuffer* buf) | ||
| 686 | buf->write_8bytes(creation_time); | 738 | buf->write_8bytes(creation_time); |
| 687 | buf->write_8bytes(modification_time); | 739 | buf->write_8bytes(modification_time); |
| 688 | buf->write_4bytes(timescale); | 740 | buf->write_4bytes(timescale); |
| 689 | - buf->write_8bytes(duration); | 741 | + buf->write_8bytes(duration_in_tbn); |
| 690 | } else { | 742 | } else { |
| 691 | buf->write_4bytes((uint32_t)creation_time); | 743 | buf->write_4bytes((uint32_t)creation_time); |
| 692 | buf->write_4bytes((uint32_t)modification_time); | 744 | buf->write_4bytes((uint32_t)modification_time); |
| 693 | buf->write_4bytes(timescale); | 745 | buf->write_4bytes(timescale); |
| 694 | - buf->write_4bytes((uint32_t)duration); | 746 | + buf->write_4bytes((uint32_t)duration_in_tbn); |
| 695 | } | 747 | } |
| 696 | 748 | ||
| 697 | buf->write_4bytes(rate); | 749 | buf->write_4bytes(rate); |
| @@ -721,12 +773,12 @@ int SrsMp4MovieHeaderBox::decode_header(SrsBuffer* buf) | @@ -721,12 +773,12 @@ int SrsMp4MovieHeaderBox::decode_header(SrsBuffer* buf) | ||
| 721 | creation_time = buf->read_8bytes(); | 773 | creation_time = buf->read_8bytes(); |
| 722 | modification_time = buf->read_8bytes(); | 774 | modification_time = buf->read_8bytes(); |
| 723 | timescale = buf->read_4bytes(); | 775 | timescale = buf->read_4bytes(); |
| 724 | - duration = buf->read_8bytes(); | 776 | + duration_in_tbn = buf->read_8bytes(); |
| 725 | } else { | 777 | } else { |
| 726 | creation_time = buf->read_4bytes(); | 778 | creation_time = buf->read_4bytes(); |
| 727 | modification_time = buf->read_4bytes(); | 779 | modification_time = buf->read_4bytes(); |
| 728 | timescale = buf->read_4bytes(); | 780 | timescale = buf->read_4bytes(); |
| 729 | - duration = buf->read_4bytes(); | 781 | + duration_in_tbn = buf->read_4bytes(); |
| 730 | } | 782 | } |
| 731 | 783 | ||
| 732 | rate = buf->read_4bytes(); | 784 | rate = buf->read_4bytes(); |
| @@ -769,6 +821,18 @@ SrsMp4TrackHeaderBox::~SrsMp4TrackHeaderBox() | @@ -769,6 +821,18 @@ SrsMp4TrackHeaderBox::~SrsMp4TrackHeaderBox() | ||
| 769 | { | 821 | { |
| 770 | } | 822 | } |
| 771 | 823 | ||
| 824 | +SrsMp4TrackType SrsMp4TrackBox::track_type() | ||
| 825 | +{ | ||
| 826 | + SrsMp4Box* box = get(SrsMp4BoxTypeMDIA); | ||
| 827 | + if (!box) { | ||
| 828 | + return SrsMp4TrackTypeForbidden; | ||
| 829 | + } | ||
| 830 | + | ||
| 831 | + // TODO: Maybe should discovery all mdia boxes. | ||
| 832 | + SrsMp4MediaBox* mdia = dynamic_cast<SrsMp4MediaBox*>(box); | ||
| 833 | + return mdia->track_type(); | ||
| 834 | +} | ||
| 835 | + | ||
| 772 | int SrsMp4TrackHeaderBox::nb_header() | 836 | int SrsMp4TrackHeaderBox::nb_header() |
| 773 | { | 837 | { |
| 774 | int size = SrsMp4FullBox::nb_header(); | 838 | int size = SrsMp4FullBox::nb_header(); |
| @@ -962,6 +1026,23 @@ SrsMp4MediaBox::~SrsMp4MediaBox() | @@ -962,6 +1026,23 @@ SrsMp4MediaBox::~SrsMp4MediaBox() | ||
| 962 | { | 1026 | { |
| 963 | } | 1027 | } |
| 964 | 1028 | ||
| 1029 | +SrsMp4TrackType SrsMp4MediaBox::track_type() | ||
| 1030 | +{ | ||
| 1031 | + SrsMp4Box* box = get(SrsMp4BoxTypeHDLR); | ||
| 1032 | + if (!box) { | ||
| 1033 | + return SrsMp4TrackTypeForbidden; | ||
| 1034 | + } | ||
| 1035 | + | ||
| 1036 | + SrsMp4HandlerReferenceBox* hdlr = dynamic_cast<SrsMp4HandlerReferenceBox*>(box); | ||
| 1037 | + if (hdlr->handler_type == SrsMp4HandlerTypeSOUN) { | ||
| 1038 | + return SrsMp4TrackTypeAudio; | ||
| 1039 | + } else if (hdlr->handler_type == SrsMp4HandlerTypeVIDE) { | ||
| 1040 | + return SrsMp4TrackTypeVideo; | ||
| 1041 | + } else { | ||
| 1042 | + return SrsMp4TrackTypeForbidden; | ||
| 1043 | + } | ||
| 1044 | +} | ||
| 1045 | + | ||
| 965 | SrsMp4MediaHeaderBox::SrsMp4MediaHeaderBox() | 1046 | SrsMp4MediaHeaderBox::SrsMp4MediaHeaderBox() |
| 966 | { | 1047 | { |
| 967 | type = SrsMp4BoxTypeMDHD; | 1048 | type = SrsMp4BoxTypeMDHD; |
| @@ -1084,12 +1165,12 @@ SrsMp4HandlerReferenceBox::~SrsMp4HandlerReferenceBox() | @@ -1084,12 +1165,12 @@ SrsMp4HandlerReferenceBox::~SrsMp4HandlerReferenceBox() | ||
| 1084 | 1165 | ||
| 1085 | bool SrsMp4HandlerReferenceBox::is_video() | 1166 | bool SrsMp4HandlerReferenceBox::is_video() |
| 1086 | { | 1167 | { |
| 1087 | - return handler_type == SrsMp4BoxTypeVIDE; | 1168 | + return handler_type == SrsMp4HandlerTypeVIDE; |
| 1088 | } | 1169 | } |
| 1089 | 1170 | ||
| 1090 | bool SrsMp4HandlerReferenceBox::is_audio() | 1171 | bool SrsMp4HandlerReferenceBox::is_audio() |
| 1091 | { | 1172 | { |
| 1092 | - return handler_type == SrsMp4BoxTypeSOUN; | 1173 | + return handler_type == SrsMp4HandlerTypeSOUN; |
| 1093 | } | 1174 | } |
| 1094 | 1175 | ||
| 1095 | int SrsMp4HandlerReferenceBox::nb_header() | 1176 | int SrsMp4HandlerReferenceBox::nb_header() |
| @@ -1124,7 +1205,7 @@ int SrsMp4HandlerReferenceBox::decode_header(SrsBuffer* buf) | @@ -1124,7 +1205,7 @@ int SrsMp4HandlerReferenceBox::decode_header(SrsBuffer* buf) | ||
| 1124 | } | 1205 | } |
| 1125 | 1206 | ||
| 1126 | buf->skip(4); | 1207 | buf->skip(4); |
| 1127 | - handler_type = buf->read_4bytes(); | 1208 | + handler_type = (SrsMp4HandlerType)buf->read_4bytes(); |
| 1128 | buf->skip(12); | 1209 | buf->skip(12); |
| 1129 | 1210 | ||
| 1130 | if ((ret = srs_mp4_string_read(buf, name, left_space(buf))) != ERROR_SUCCESS) { | 1211 | if ((ret = srs_mp4_string_read(buf, name, left_space(buf))) != ERROR_SUCCESS) { |
| @@ -2766,6 +2847,24 @@ int SrsMp4Decoder::initialize(ISrsReader* r) | @@ -2766,6 +2847,24 @@ int SrsMp4Decoder::initialize(ISrsReader* r) | ||
| 2766 | int SrsMp4Decoder::parse_moov(SrsMp4MovieBox* moov) | 2847 | int SrsMp4Decoder::parse_moov(SrsMp4MovieBox* moov) |
| 2767 | { | 2848 | { |
| 2768 | int ret = ERROR_SUCCESS; | 2849 | int ret = ERROR_SUCCESS; |
| 2850 | + | ||
| 2851 | + SrsMp4MovieHeaderBox* mvhd = moov->mvhd(); | ||
| 2852 | + if (!mvhd) { | ||
| 2853 | + ret = ERROR_MP4_ILLEGAL_MOOV; | ||
| 2854 | + srs_error("MP4 missing mvhd. ret=%d", ret); | ||
| 2855 | + return ret; | ||
| 2856 | + } | ||
| 2857 | + | ||
| 2858 | + SrsMp4TrackBox* vide = moov->video(); | ||
| 2859 | + SrsMp4TrackBox* soun = moov->audio(); | ||
| 2860 | + if (!vide && !soun) { | ||
| 2861 | + ret = ERROR_MP4_ILLEGAL_MOOV; | ||
| 2862 | + srs_error("MP4 missing audio and video track. ret=%d", ret); | ||
| 2863 | + return ret; | ||
| 2864 | + } | ||
| 2865 | + | ||
| 2866 | + srs_trace("MP4 moov dur=%dms, vide=%d, soun=%d", mvhd->duration(), vide != NULL, soun != NULL); | ||
| 2867 | + | ||
| 2769 | return ret; | 2868 | return ret; |
| 2770 | } | 2869 | } |
| 2771 | 2870 |
| @@ -81,9 +81,18 @@ enum SrsMp4BoxType | @@ -81,9 +81,18 @@ enum SrsMp4BoxType | ||
| 81 | SrsMp4BoxTypeMP4A = 0x6d703461, // 'mp4a' | 81 | SrsMp4BoxTypeMP4A = 0x6d703461, // 'mp4a' |
| 82 | SrsMp4BoxTypeESDS = 0x65736473, // 'esds' | 82 | SrsMp4BoxTypeESDS = 0x65736473, // 'esds' |
| 83 | SrsMp4BoxTypeUDTA = 0x75647461, // 'udta' | 83 | SrsMp4BoxTypeUDTA = 0x75647461, // 'udta' |
| 84 | +}; | ||
| 85 | + | ||
| 86 | +/** | ||
| 87 | + * 8.4.3.3 Semantics | ||
| 88 | + * ISO_IEC_14496-12-base-format-2012.pdf, page 37 | ||
| 89 | + */ | ||
| 90 | +enum SrsMp4HandlerType | ||
| 91 | +{ | ||
| 92 | + SrsMp4HandlerTypeForbidden = 0x00, | ||
| 84 | 93 | ||
| 85 | - SrsMp4BoxTypeVIDE = 0x76696465, // 'vide' | ||
| 86 | - SrsMp4BoxTypeSOUN = 0x736f756e, // 'soun' | 94 | + SrsMp4HandlerTypeVIDE = 0x76696465, // 'vide' |
| 95 | + SrsMp4HandlerTypeSOUN = 0x736f756e, // 'soun' | ||
| 87 | }; | 96 | }; |
| 88 | 97 | ||
| 89 | /** | 98 | /** |
| @@ -121,7 +130,7 @@ public: | @@ -121,7 +130,7 @@ public: | ||
| 121 | SrsMp4BoxType type; | 130 | SrsMp4BoxType type; |
| 122 | // For box 'uuid'. | 131 | // For box 'uuid'. |
| 123 | uint8_t* usertype; | 132 | uint8_t* usertype; |
| 124 | -private: | 133 | +protected: |
| 125 | std::vector<SrsMp4Box*> boxes; | 134 | std::vector<SrsMp4Box*> boxes; |
| 126 | private: | 135 | private: |
| 127 | // The position at buffer to start demux the box. | 136 | // The position at buffer to start demux the box. |
| @@ -138,6 +147,9 @@ public: | @@ -138,6 +147,9 @@ public: | ||
| 138 | virtual bool is_ftyp(); | 147 | virtual bool is_ftyp(); |
| 139 | virtual bool is_moov(); | 148 | virtual bool is_moov(); |
| 140 | virtual bool is_mdat(); | 149 | virtual bool is_mdat(); |
| 150 | + // Get the contained box of specific type. | ||
| 151 | + // @return The first matched box. | ||
| 152 | + virtual SrsMp4Box* get(SrsMp4BoxType bt); | ||
| 141 | /** | 153 | /** |
| 142 | * Discovery the box from buffer. | 154 | * Discovery the box from buffer. |
| 143 | * @param ppbox Output the discoveried box, which user must free it. | 155 | * @param ppbox Output the discoveried box, which user must free it. |
| @@ -252,6 +264,9 @@ protected: | @@ -252,6 +264,9 @@ protected: | ||
| 252 | virtual int decode_header(SrsBuffer* buf); | 264 | virtual int decode_header(SrsBuffer* buf); |
| 253 | }; | 265 | }; |
| 254 | 266 | ||
| 267 | +class SrsMp4TrackBox; | ||
| 268 | +class SrsMp4MovieHeaderBox; | ||
| 269 | + | ||
| 255 | /** | 270 | /** |
| 256 | * 8.2.1 Movie Box (moov) | 271 | * 8.2.1 Movie Box (moov) |
| 257 | * ISO_IEC_14496-12-base-format-2012.pdf, page 30 | 272 | * ISO_IEC_14496-12-base-format-2012.pdf, page 30 |
| @@ -263,6 +278,13 @@ class SrsMp4MovieBox : public SrsMp4Box | @@ -263,6 +278,13 @@ class SrsMp4MovieBox : public SrsMp4Box | ||
| 263 | public: | 278 | public: |
| 264 | SrsMp4MovieBox(); | 279 | SrsMp4MovieBox(); |
| 265 | virtual ~SrsMp4MovieBox(); | 280 | virtual ~SrsMp4MovieBox(); |
| 281 | +public: | ||
| 282 | + // Get the header of moov. | ||
| 283 | + virtual SrsMp4MovieHeaderBox* mvhd(); | ||
| 284 | + // Get the first video track. | ||
| 285 | + virtual SrsMp4TrackBox* video(); | ||
| 286 | + // Get the first audio track. | ||
| 287 | + virtual SrsMp4TrackBox* audio(); | ||
| 266 | protected: | 288 | protected: |
| 267 | virtual int nb_header(); | 289 | virtual int nb_header(); |
| 268 | virtual int encode_header(SrsBuffer* buf); | 290 | virtual int encode_header(SrsBuffer* buf); |
| @@ -282,6 +304,7 @@ public: | @@ -282,6 +304,7 @@ public: | ||
| 282 | // an integer that declares the most recent time the presentation was modified (in | 304 | // an integer that declares the most recent time the presentation was modified (in |
| 283 | // seconds since midnight, Jan. 1, 1904, in UTC time) | 305 | // seconds since midnight, Jan. 1, 1904, in UTC time) |
| 284 | uint64_t modification_time; | 306 | uint64_t modification_time; |
| 307 | +private: | ||
| 285 | // an integer that specifies the time-scale for the entire presentation; this is the number of | 308 | // an integer that specifies the time-scale for the entire presentation; this is the number of |
| 286 | // time units that pass in one second. For example, a time coordinate system that measures time in | 309 | // time units that pass in one second. For example, a time coordinate system that measures time in |
| 287 | // sixtieths of a second has a time scale of 60. | 310 | // sixtieths of a second has a time scale of 60. |
| @@ -289,7 +312,7 @@ public: | @@ -289,7 +312,7 @@ public: | ||
| 289 | // an integer that declares length of the presentation (in the indicated timescale). This property | 312 | // an integer that declares length of the presentation (in the indicated timescale). This property |
| 290 | // is derived from the presentation’s tracks: the value of this field corresponds to the duration of the | 313 | // is derived from the presentation’s tracks: the value of this field corresponds to the duration of the |
| 291 | // longest track in the presentation. If the duration cannot be determined then duration is set to all 1s. | 314 | // longest track in the presentation. If the duration cannot be determined then duration is set to all 1s. |
| 292 | - uint64_t duration; | 315 | + uint64_t duration_in_tbn; |
| 293 | public: | 316 | public: |
| 294 | // a fixed point 16.16 number that indicates the preferred rate to play the presentation; 1.0 | 317 | // a fixed point 16.16 number that indicates the preferred rate to play the presentation; 1.0 |
| 295 | // (0x00010000) is normal forward playback | 318 | // (0x00010000) is normal forward playback |
| @@ -309,12 +332,23 @@ public: | @@ -309,12 +332,23 @@ public: | ||
| 309 | public: | 332 | public: |
| 310 | SrsMp4MovieHeaderBox(); | 333 | SrsMp4MovieHeaderBox(); |
| 311 | virtual ~SrsMp4MovieHeaderBox(); | 334 | virtual ~SrsMp4MovieHeaderBox(); |
| 335 | +public: | ||
| 336 | + // Get the duration in ms. | ||
| 337 | + virtual uint64_t duration(); | ||
| 312 | protected: | 338 | protected: |
| 313 | virtual int nb_header(); | 339 | virtual int nb_header(); |
| 314 | virtual int encode_header(SrsBuffer* buf); | 340 | virtual int encode_header(SrsBuffer* buf); |
| 315 | virtual int decode_header(SrsBuffer* buf); | 341 | virtual int decode_header(SrsBuffer* buf); |
| 316 | }; | 342 | }; |
| 317 | 343 | ||
| 344 | +// The type of track, maybe combine of types. | ||
| 345 | +enum SrsMp4TrackType | ||
| 346 | +{ | ||
| 347 | + SrsMp4TrackTypeForbidden = 0x00, | ||
| 348 | + SrsMp4TrackTypeAudio = 0x01, | ||
| 349 | + SrsMp4TrackTypeVideo = 0x02, | ||
| 350 | +}; | ||
| 351 | + | ||
| 318 | /** | 352 | /** |
| 319 | * 8.3.1 Track Box (trak) | 353 | * 8.3.1 Track Box (trak) |
| 320 | * ISO_IEC_14496-12-base-format-2012.pdf, page 32 | 354 | * ISO_IEC_14496-12-base-format-2012.pdf, page 32 |
| @@ -327,6 +361,11 @@ class SrsMp4TrackBox : public SrsMp4Box | @@ -327,6 +361,11 @@ class SrsMp4TrackBox : public SrsMp4Box | ||
| 327 | public: | 361 | public: |
| 328 | SrsMp4TrackBox(); | 362 | SrsMp4TrackBox(); |
| 329 | virtual ~SrsMp4TrackBox(); | 363 | virtual ~SrsMp4TrackBox(); |
| 364 | +public: | ||
| 365 | + // Get the type of track, maybe combine of track type, | ||
| 366 | + // for example, it maybe Audio|Video when contains both. | ||
| 367 | + // Generally, only single type, no combination. | ||
| 368 | + virtual SrsMp4TrackType track_type(); | ||
| 330 | }; | 369 | }; |
| 331 | 370 | ||
| 332 | /** | 371 | /** |
| @@ -458,6 +497,11 @@ class SrsMp4MediaBox : public SrsMp4Box | @@ -458,6 +497,11 @@ class SrsMp4MediaBox : public SrsMp4Box | ||
| 458 | public: | 497 | public: |
| 459 | SrsMp4MediaBox(); | 498 | SrsMp4MediaBox(); |
| 460 | virtual ~SrsMp4MediaBox(); | 499 | virtual ~SrsMp4MediaBox(); |
| 500 | +public: | ||
| 501 | + // Get the type of track, maybe combine of track type, | ||
| 502 | + // for example, it maybe Audio|Video when contains both. | ||
| 503 | + // Generally, only single type, no combination. | ||
| 504 | + virtual SrsMp4TrackType track_type(); | ||
| 461 | }; | 505 | }; |
| 462 | 506 | ||
| 463 | /** | 507 | /** |
| @@ -521,7 +565,7 @@ public: | @@ -521,7 +565,7 @@ public: | ||
| 521 | // an integer containing one of the following values, or a value from a derived specification: | 565 | // an integer containing one of the following values, or a value from a derived specification: |
| 522 | // ‘vide’, Video track | 566 | // ‘vide’, Video track |
| 523 | // ‘soun’, Audio track | 567 | // ‘soun’, Audio track |
| 524 | - uint32_t handler_type; | 568 | + SrsMp4HandlerType handler_type; |
| 525 | uint32_t reserved[3]; | 569 | uint32_t reserved[3]; |
| 526 | // a null-terminated string in UTF-8 characters which gives a human-readable name for the track | 570 | // a null-terminated string in UTF-8 characters which gives a human-readable name for the track |
| 527 | // type (for debugging and inspection purposes). | 571 | // type (for debugging and inspection purposes). |
-
请 注册 或 登录 后发表评论