FlvParser.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. #include "FlvParser.h"
  2. #include <stdlib.h>
  3. #include <fstream>
  4. #include <iostream>
  5. int FlvParser::AudioTag::_aacProfile;
  6. int FlvParser::AudioTag::_sampleRateIndex;
  7. int FlvParser::AudioTag::_channelConfig;
  8. static int nH264StartCode = 0x01000000;
  9. #define CheckBuf(x) \
  10. { \
  11. if (nBufLen - nOffset < x) { \
  12. nUsedLen = nOffset; \
  13. return 0; \
  14. } \
  15. }
  16. FlvParser::FlvParser() { _pFlvHeader = nullptr; }
  17. FlvParser::~FlvParser() {
  18. for (int i = 0; i < _vpTag.size(); i++) {
  19. DestroyTag(_vpTag[i]);
  20. delete _vpTag[i];
  21. }
  22. }
  23. int FlvParser::Parse(uint8_t* pBuf, int nBufLen, int& nUsedLen) {
  24. int nOffset = 0;
  25. if (_pFlvHeader == nullptr) {
  26. CheckBuf(9);
  27. _pFlvHeader = CreateHeader(pBuf + nOffset);
  28. nOffset += _pFlvHeader->nHeaderSize;
  29. }
  30. while (1) {
  31. CheckBuf(15);
  32. int nPrevSize = SolveU32(pBuf + nOffset);
  33. nOffset += 4;
  34. Tag* tag = CreateTag(pBuf + nOffset, nBufLen - nOffset);
  35. if (tag == nullptr) {
  36. nOffset -= 4;
  37. break;
  38. }
  39. nOffset += (11 + tag->_header.nDataSize);
  40. _vpTag.push_back(tag);
  41. }
  42. nUsedLen = nOffset;
  43. return 0;
  44. }
  45. FlvParser::FlvHeader* FlvParser::CreateHeader(uint8_t* pBuf) {
  46. FlvHeader* pHeader = new FlvHeader;
  47. pHeader->nVersion = pBuf[3];
  48. pHeader->bHaveAudio = (pBuf[4] >> 2) & 0x01;
  49. pHeader->bHaveVideo = (pBuf[4] >> 0) & 0x01;
  50. pHeader->nHeaderSize = SolveU32(pBuf + 5);
  51. pHeader->pFlvHeader = new uint8_t[pHeader->nHeaderSize];
  52. memset(pHeader->pFlvHeader, 0, pHeader->nHeaderSize);
  53. memcpy(pHeader->pFlvHeader, pBuf, pHeader->nHeaderSize);
  54. return pHeader;
  55. }
  56. void FlvParser::DestroyHeader(FlvParser::FlvHeader* pHeader) {
  57. if (pHeader) {
  58. if (pHeader->pFlvHeader) {
  59. delete pHeader->pFlvHeader;
  60. }
  61. }
  62. }
  63. void FlvParser::Tag::Init(TagHeader* pHeader, uint8_t* pBuf, int nLeftLen) {
  64. memcpy(&_header, pHeader, sizeof(TagHeader));
  65. _pTagHeader = new uint8_t[11];
  66. memcpy(_pTagHeader, pBuf, 11);
  67. _pTagData = new uint8_t[pHeader->nDataSize];
  68. memcpy(_pTagData, pBuf + 11, pHeader->nDataSize);
  69. }
  70. FlvParser::VideoTag::VideoTag(TagHeader* pHeader, uint8_t* pBuf, int nLeftLen,
  71. FlvParser* pParser) {
  72. Init(pHeader, pBuf, nLeftLen);
  73. uint8_t* pd = _pTagData;
  74. _nFrameType = (pd[0] & 0xf0) >> 4;
  75. _nCodecType = (pd[0] & 0x0f) >> 0;
  76. if (_header.nTagType == 0x09 && _nCodecType == 7) {
  77. ParseH264Tag(pParser);
  78. }
  79. }
  80. FlvParser::AudioTag::AudioTag(TagHeader* pHeader, uint8_t* pBuf, int nLeftLen,
  81. FlvParser* pParser) {
  82. Init(pHeader, pBuf, nLeftLen);
  83. uint8_t* pd = _pTagData;
  84. _nSoundFormat = (pd[0] & 0xf0) >> 4;
  85. _nSoundRate = (pd[0] & 0x0c) >> 2;
  86. _nSoundSize = (pd[0] & 0x02) >> 1;
  87. _nSoundType = (pd[0] & 0x01) >> 0;
  88. if (_nSoundFormat == 10) {
  89. ParseAACTag(pParser);
  90. }
  91. }
  92. int FlvParser::AudioTag::ParseAACTag(FlvParser* pParser) {
  93. uint8_t* pd = _pTagData;
  94. int nAACPacketType = pd[1];
  95. if (nAACPacketType == 0) {
  96. ParseAudioSpecificConfig(pParser, pd);
  97. } else if (nAACPacketType == 1) {
  98. ParseAACRaw(pParser, pd);
  99. } else {
  100. }
  101. return 0;
  102. }
  103. int FlvParser::AudioTag::ParseAudioSpecificConfig(FlvParser* pParser,
  104. uint8_t* pTagData) {
  105. uint8_t* pd = pTagData;
  106. _aacProfile = (pd[2] & 0xf8) >> 3;
  107. _sampleRateIndex = ((pd[2] & 0x07) << 1 | (pd[3] >> 7));
  108. _channelConfig = (pd[3] >> 3) & 0x0f;
  109. printf("-----AAC-----\n");
  110. printf("aacProfile:%d\n", _aacProfile);
  111. printf("sampleRateIndex:%d\n", _sampleRateIndex);
  112. printf("channelConfig:%d\n", _channelConfig);
  113. _pMedia = nullptr;
  114. _nMediaLen = 0;
  115. return 0;
  116. }
  117. int FlvParser::AudioTag::ParseAACRaw(FlvParser* pParser, uint8_t* pTagData) {
  118. uint64_t bits = 0;
  119. int datasize = _header.nDataSize - 2;
  120. WriteU64(bits, 12, 0xFFF);
  121. WriteU64(bits, 1, 0);
  122. WriteU64(bits, 2, 0);
  123. WriteU64(bits, 1, 1);
  124. WriteU64(bits, 2, _aacProfile - 1);
  125. WriteU64(bits, 4, _sampleRateIndex);
  126. WriteU64(bits, 1, 0);
  127. WriteU64(bits, 3, _channelConfig);
  128. WriteU64(bits, 1, 0);
  129. WriteU64(bits, 1, 0);
  130. WriteU64(bits, 1, 0);
  131. WriteU64(bits, 1, 0);
  132. WriteU64(bits, 13, datasize + 7);
  133. WriteU64(bits, 11, 0x7FF);
  134. WriteU64(bits, 2, 0);
  135. _nMediaLen = datasize + 7;
  136. _pMedia = new uint8_t[_nMediaLen];
  137. uint8_t p64[8] = {0};
  138. for (size_t i = 0; i < 8; i++) {
  139. p64[i] = bits >> (64 - 8 * (i + 1));
  140. }
  141. memcpy(_pMedia, p64 + 1, 7);
  142. memcpy(_pMedia + 7, pTagData + 2, datasize);
  143. }
  144. FlvParser::Tag* FlvParser::CreateTag(uint8_t* pBuf, int nLeftLen) {
  145. TagHeader* header;
  146. header->nTagType = SolveU8(pBuf);
  147. header->nDataSize = SolveU24(pBuf + 1);
  148. header->nTimeSamp = SolveU24(pBuf + 4);
  149. header->nTimeSampExt = SolveU8(pBuf + 7);
  150. header->nStreamID = SolveU24(pBuf + 8);
  151. header->nTotalTS =
  152. (uint32_t)(header->nTimeSampExt << 24) + header->nTimeSamp;
  153. if ((header->nDataSize + 11) < nLeftLen) {
  154. return nullptr;
  155. }
  156. Tag* pTag;
  157. switch (header->nTagType) {
  158. case 0x08:
  159. // video
  160. pTag = new VideoTag(header, pBuf, nLeftLen, this);
  161. break;
  162. case 0x09:
  163. // audio
  164. pTag = new AudioTag(header, pBuf, nLeftLen, this);
  165. break;
  166. case 0x12:
  167. // script
  168. default:
  169. pTag = new Tag();
  170. pTag->Init(header, pBuf, nLeftLen);
  171. break;
  172. }
  173. return pTag;
  174. }
  175. void FlvParser::DestroyTag(Tag* pTag) {
  176. if (pTag->_pTagHeader) delete[] pTag->_pTagHeader;
  177. if (pTag->_pMedia) delete[] pTag->_pMedia;
  178. if (pTag->_pTagData) delete[] pTag->_pTagData;
  179. }
  180. int FlvParser::VideoTag::ParseH264Tag(FlvParser* pParser) {
  181. uint8_t* pd = _pTagData;
  182. int nAVCPacketType = pd[1];
  183. int nCompositionTime = SolveU24(pd + 2);
  184. if (nAVCPacketType == 0) {
  185. ParseH264Configuration(pParser, pd);
  186. } else if (nAVCPacketType == 1) {
  187. ParseNalu(pParser, pd);
  188. }
  189. return 0;
  190. }
  191. int FlvParser::VideoTag::ParseH264Configuration(FlvParser* pParser,
  192. uint8_t* pTagData) {
  193. uint8_t* pd = pTagData;
  194. pParser->_nNaluUnitLength = (pd[9] & 0x03) + 1;
  195. int pps_size, sps_size;
  196. sps_size = SolveU16(pd + 11);
  197. pps_size = SolveU16(pd + 11 + 2 + (1 + sps_size) + 1);
  198. _nMediaLen = 4 + sps_size + 4 + pps_size;
  199. _pMedia = new uint8_t[_nMediaLen];
  200. memset(_pMedia, 0, _nMediaLen);
  201. memcpy(_pMedia, &nH264StartCode, 4);
  202. memcpy(_pMedia + 4, pd + 11 + 2, sps_size);
  203. memcpy(_pMedia + 4 + sps_size, &nH264StartCode, 4);
  204. memcpy(_pMedia + 8 + sps_size, pd + 11 + 2 + sps_size + 1 + 2, pps_size);
  205. return 0;
  206. }
  207. int FlvParser::VideoTag::ParseNalu(FlvParser* pParser, uint8_t* pTagData) {
  208. uint8_t* pd = pTagData;
  209. int nOffset = 0;
  210. _nMediaLen = 0;
  211. _pMedia = new uint8_t[_header.nDataSize + 10];
  212. nOffset = 5;
  213. while (1) {
  214. if (nOffset >= _header.nDataSize) break;
  215. int nNaluLen = 0;
  216. switch (pParser->_nNaluUnitLength) {
  217. case 4:
  218. nNaluLen = SolveU32(pd + nOffset);
  219. break;
  220. case 3:
  221. nNaluLen = SolveU24(pd + nOffset);
  222. break;
  223. case 2:
  224. nNaluLen = SolveU16(pd + nOffset);
  225. break;
  226. default:
  227. nNaluLen = SolveU8(pd + nOffset);
  228. break;
  229. }
  230. memcpy(_pMedia + _nMediaLen, &nH264StartCode, 4);
  231. memcpy(_pMedia + _nMediaLen + 4,
  232. pd + nOffset + pParser->_nNaluUnitLength, nNaluLen);
  233. nOffset += (nNaluLen + pParser->_nNaluUnitLength);
  234. _nMediaLen += (4 + nNaluLen);
  235. }
  236. return 0;
  237. }
  238. int FlvParser::DumpH264(const std::string filepath) {
  239. std::fstream fout;
  240. fout.open(filepath.c_str(), std::ios_base::out | std::ios_base::binary);
  241. if (fout) {
  242. std::vector<Tag*>::iterator it_tag;
  243. it_tag = _vpTag.begin();
  244. for (it_tag; it_tag != _vpTag.end(); it_tag++) {
  245. if ((*it_tag)->_header.nTagType != 0x09) continue;
  246. fout.write((char*)(*it_tag)->_pMedia, (*it_tag)->_nMediaLen);
  247. }
  248. }
  249. fout.close();
  250. return 0;
  251. }
  252. int FlvParser::DumpAAC(const std::string filepath) {
  253. std::fstream fout;
  254. fout.open(filepath.c_str(), std::ios_base::out | std::ios_base::binary);
  255. if (fout) {
  256. std::vector<Tag*>::iterator it_tag;
  257. it_tag = _vpTag.begin();
  258. for (it_tag; it_tag != _vpTag.end(); it_tag++) {
  259. if ((*it_tag)->_header.nTagType != 0x08) continue;
  260. AudioTag* ad_tag = (AudioTag*)(*it_tag);
  261. if (ad_tag->_nSoundFormat != 10) continue;
  262. if (ad_tag->_nMediaLen == 0) continue;
  263. fout.write((char*)(*it_tag)->_pMedia, (*it_tag)->_nMediaLen);
  264. }
  265. }
  266. fout.close();
  267. return 0;
  268. }
  269. int FlvParser::DumpFlv(const std::string filepath) {}
  270. void FlvParser::SetStat() {
  271. for (size_t i = 0; i < _vpTag.size(); i++) {
  272. switch (_vpTag[i]->_header.nTagType) {
  273. case 0x08:
  274. _sStat.nAudioNum++;
  275. break;
  276. case 0x09:
  277. SetVideoStat(_vpTag[i]);
  278. break;
  279. case 0x12:
  280. _sStat.nMetaNum++;
  281. break;
  282. }
  283. }
  284. }
  285. void FlvParser::SetVideoStat(Tag* pTag) {
  286. _sStat.nVideoNum++;
  287. _sStat.nMaxTimeStamp = pTag->_header.nTimeSamp;
  288. if (pTag->_pTagData[0] == 0x17 && pTag->_pTagData[1] == 0x00) {
  289. _sStat.nLengthSize = (pTag->_pTagData[9] & 0x03) + 1;
  290. }
  291. }
  292. int FlvParser::MetaTag::parseMeta(FlvParser* pParser) {
  293. uint8_t* pd = _pTagData;
  294. int dataSize = _header.nDataSize;
  295. uint32_t arrayLen = 0;
  296. uint32_t offset = 13; // Type + Value_Size + Value占用13字节
  297. uint32_t nameLen = 0;
  298. double doubleValue = 0;
  299. std::string strValue = "";
  300. bool boolValue = false;
  301. uint32_t valueLen = 0;
  302. uint8_t u8Value = 0;
  303. if (pd[offset++] == 0x08) // 0x8 onMetaData
  304. {
  305. arrayLen = SolveU32(pd + offset);
  306. offset += 4; // 跳过 [ECMAArrayLength]占用的字节
  307. printf("ArrayLen = %d\n", arrayLen);
  308. } else {
  309. printf("metadata format error!!!");
  310. return -1;
  311. }
  312. for (uint32_t i = 0; i < arrayLen; i++) {
  313. doubleValue = 0;
  314. boolValue = false;
  315. strValue = "";
  316. // 读取字段长度
  317. nameLen = SolveU16(pd + offset);
  318. offset += 2; // 跳过2字节字段长度
  319. char name[nameLen + 1]; // 获取字段名称
  320. memset(name, 0, sizeof(name));
  321. memcpy(name, &pd[offset], nameLen);
  322. name[nameLen + 1] = '\0';
  323. offset += nameLen; // 跳过字段名占用的长度
  324. uint8_t amfType = pd[offset++];
  325. switch (amfType) // 判别值的类型
  326. {
  327. case 0x0: // Number type, 就是double类型, 占用8字节
  328. doubleValue = hexStr2Double(&pd[offset], 8);
  329. offset += 8; // 跳过8字节
  330. break;
  331. case 0x1: // Boolean type, 占用1字节
  332. u8Value = SolveU8(pd + offset);
  333. offset += 1; // 跳过1字节
  334. if (u8Value != 0x00)
  335. boolValue = true;
  336. else
  337. boolValue = false;
  338. break;
  339. case 0x2: // String type
  340. valueLen = SolveU16(pd + offset);
  341. offset += 2; // 跳过2字节 length
  342. strValue.append(pd + offset, pd + offset + valueLen);
  343. strValue.append("");
  344. offset += valueLen; // 跳过字段的值的长度
  345. break;
  346. default:
  347. printf("un handle amfType:%d\n", amfType);
  348. break;
  349. }
  350. if (strncmp(name, "duration", 8) == 0) {
  351. m_duration = doubleValue;
  352. } else if (strncmp(name, "width", 5) == 0) {
  353. m_width = doubleValue;
  354. } else if (strncmp(name, "height", 6) == 0) {
  355. m_height = doubleValue;
  356. } else if (strncmp(name, "videodatarate", 13) == 0) {
  357. m_videodatarate = doubleValue;
  358. } else if (strncmp(name, "framerate", 9) == 0) {
  359. m_framerate = doubleValue;
  360. } else if (strncmp(name, "videocodecid", 12) == 0) {
  361. m_videocodecid = doubleValue;
  362. } else if (strncmp(name, "audiodatarate", 13) == 0) {
  363. m_audiodatarate = doubleValue;
  364. } else if (strncmp(name, "audiosamplerate", 15) == 0) {
  365. m_audiosamplerate = doubleValue;
  366. } else if (strncmp(name, "audiosamplesize", 15) == 0) {
  367. m_audiosamplesize = doubleValue;
  368. } else if (strncmp(name, "stereo", 6) == 0) {
  369. m_stereo = boolValue;
  370. } else if (strncmp(name, "audiocodecid", 12) == 0) {
  371. m_audiocodecid = doubleValue;
  372. } else if (strncmp(name, "major_brand", 11) == 0) {
  373. m_major_brand = strValue;
  374. } else if (strncmp(name, "minor_version", 13) == 0) {
  375. m_minor_version = strValue;
  376. } else if (strncmp(name, "compatible_brands", 17) == 0) {
  377. m_compatible_brand = strValue;
  378. } else if (strncmp(name, "encoder", 7) == 0) {
  379. m_encoder = strValue;
  380. } else if (strncmp(name, "filesize", 8) == 0) {
  381. m_filesize = doubleValue;
  382. }
  383. }
  384. printMeta();
  385. return 1;
  386. }
  387. void FlvParser::MetaTag::printMeta() {
  388. printf("\nduration: %0.2lfs, filesize: %.0lfbytes\n", m_duration,
  389. m_filesize);
  390. printf("width: %0.0lf, height: %0.0lf\n", m_width, m_height);
  391. printf("videodatarate: %0.2lfkbps, framerate: %0.0lffps\n", m_videodatarate,
  392. m_framerate);
  393. printf("videocodecid: %0.0lf\n", m_videocodecid);
  394. printf("audiodatarate: %0.2lfkbps, audiosamplerate: %0.0lfKhz\n",
  395. m_audiodatarate, m_audiosamplerate);
  396. printf("audiosamplesize: %0.0lfbit, stereo: %d\n", m_audiosamplesize,
  397. m_stereo);
  398. printf("audiocodecid: %0.0lf\n", m_audiocodecid);
  399. printf("major_brand: %s, minor_version: %s\n", m_major_brand.c_str(),
  400. m_minor_version.c_str());
  401. printf("compatible_brands: %s, encoder: %s\n\n", m_compatible_brand.c_str(),
  402. m_encoder.c_str());
  403. }
  404. double FlvParser::MetaTag::hexStr2Double(const unsigned char* hex,
  405. const unsigned int length) {
  406. double ret = 0;
  407. char hexstr[length * 2];
  408. memset(hexstr, 0, length * 2);
  409. for (int i = 0; i < length; i++) {
  410. std::sprintf(hexstr + i * 2, "%02x", hex[i]);
  411. }
  412. sscanf(hexstr, "%llx", (unsigned long long*)&ret);
  413. return ret;
  414. }
  415. void FlvParser::PrintInfo() {
  416. SetStat();
  417. std::cout << "vnum:" << _sStat.nVideoNum << ",anum:" << _sStat.nAudioNum
  418. << std::endl;
  419. std::cout << "maxTimeStamp:" << _sStat.nMaxTimeStamp
  420. << ",nLengthSize:" << _sStat.nLengthSize << std::endl;
  421. }