| 1082 | } |
| 1083 | |
| 1084 | butil::Status TsWriter::Write(const RtmpAudioMessage& msg) { |
| 1085 | // ts support audio codec: aac/mp3 |
| 1086 | if (msg.codec != FLV_AUDIO_AAC && msg.codec != FLV_AUDIO_MP3) { |
| 1087 | return butil::Status(EINVAL, "Unsupported codec=%s", |
| 1088 | FlvAudioCodec2Str(msg.codec)); |
| 1089 | } |
| 1090 | const int64_t dts = static_cast<int64_t>(msg.timestamp) * 90; |
| 1091 | TsMessage tsmsg; |
| 1092 | tsmsg.write_pcr = false; |
| 1093 | tsmsg.dts = dts; |
| 1094 | tsmsg.pts = dts; |
| 1095 | tsmsg.sid = TS_PES_STREAM_ID_AUDIO_COMMON; |
| 1096 | |
| 1097 | if (msg.codec == FLV_AUDIO_AAC) { |
| 1098 | RtmpAACMessage aac_msg; |
| 1099 | butil::Status st = aac_msg.Create(msg); |
| 1100 | if (!st.ok()) { |
| 1101 | return st; |
| 1102 | } |
| 1103 | // ignore sequence header |
| 1104 | if (aac_msg.packet_type == FLV_AAC_PACKET_SEQUENCE_HEADER) { |
| 1105 | butil::Status st2 = _aac_seq_header.Create(aac_msg.data); |
| 1106 | if (!st2.ok()) { |
| 1107 | return st2; |
| 1108 | } |
| 1109 | _has_aac_seq_header = true; |
| 1110 | ++_discontinuity_counter; |
| 1111 | return butil::Status::OK(); |
| 1112 | } |
| 1113 | if (!_has_aac_seq_header) { |
| 1114 | return butil::Status(EINVAL, "Lack of AAC sequence header"); |
| 1115 | } |
| 1116 | if (aac_msg.data.size() > 0x1fff) { |
| 1117 | return butil::Status(EINVAL, "Invalid AAC data_size=%" PRIu64, |
| 1118 | (uint64_t)aac_msg.data.size()); |
| 1119 | } |
| 1120 | |
| 1121 | // the frame length is the AAC raw data plus the adts header size. |
| 1122 | const int32_t frame_length = aac_msg.data.size() + 7; |
| 1123 | |
| 1124 | // AAC-ADTS |
| 1125 | // 6.2 Audio Data Transport Stream, ADTS |
| 1126 | // in aac-iso-13818-7.pdf, page 26. |
| 1127 | // fixed 7bytes header |
| 1128 | uint8_t adts_header[7] = {0xff, 0xf9, 0x00, 0x00, 0x00, 0x0f, 0xfc}; |
| 1129 | // profile, 2bits |
| 1130 | const AACProfile aac_profile = |
| 1131 | AACObjectType2Profile(_aac_seq_header.aac_object); |
| 1132 | if (aac_profile == AAC_PROFILE_UNKNOWN) { |
| 1133 | return butil::Status(EINVAL, "Invalid aac_object=%d", |
| 1134 | (int)_aac_seq_header.aac_object); |
| 1135 | } |
| 1136 | adts_header[2] = (aac_profile << 6) & 0xc0; |
| 1137 | // sampling_frequency_index 4bits |
| 1138 | adts_header[2] |= (_aac_seq_header.aac_sample_rate << 2) & 0x3c; |
| 1139 | // channel_configuration 3bits |
| 1140 | adts_header[2] |= (_aac_seq_header.aac_channels >> 2) & 0x01; |
| 1141 | adts_header[3] = (_aac_seq_header.aac_channels << 6) & 0xc0; |