Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

147 řádky
2.9KB

  1. #include "h265-file-reader.h"
  2. #include <assert.h>
  3. #include <string.h>
  4. #include <algorithm>
  5. #define H265_NAL(v) ((v>> 1) & 0x3f)
  6. enum { NAL_IDR_W_RADL = 19, NAL_IDR_N_LP= 20, NAL_VPS = 32, NAL_SPS = 33, NAL_PPS = 34, NAL_SEI = 39};
  7. H265FileReader::H265FileReader(const char* file)
  8. :m_ptr(NULL), m_capacity(0)
  9. {
  10. FILE* fp = fopen(file, "rb");
  11. if(fp)
  12. {
  13. fseek(fp, 0, SEEK_END);
  14. m_capacity = ftell(fp);
  15. fseek(fp, 0, SEEK_SET);
  16. m_ptr = (uint8_t*)malloc(m_capacity);
  17. fread(m_ptr, 1, m_capacity, fp);
  18. fclose(fp);
  19. Init();
  20. }
  21. m_vit = m_videos.begin();
  22. }
  23. H265FileReader::~H265FileReader()
  24. {
  25. if (m_ptr)
  26. {
  27. assert(m_capacity > 0);
  28. free(m_ptr);
  29. }
  30. }
  31. bool H265FileReader::IsOpened() const
  32. {
  33. return !m_videos.empty();
  34. }
  35. int H265FileReader::GetNextFrame(int64_t &dts, const uint8_t* &ptr, size_t &bytes)
  36. {
  37. if(m_vit == m_videos.end())
  38. return -1; // file end
  39. ptr = m_vit->nalu;
  40. dts = m_vit->time;
  41. bytes = m_vit->bytes;
  42. ++m_vit;
  43. return 0;
  44. }
  45. int H265FileReader::Seek(int64_t &dts)
  46. {
  47. vframe_t frame;
  48. frame.time = dts;
  49. vframes_t::iterator it;
  50. it = std::lower_bound(m_videos.begin(), m_videos.end(), frame);
  51. if(it == m_videos.end())
  52. return -1;
  53. while(it != m_videos.begin())
  54. {
  55. if(it->idr)
  56. {
  57. m_vit = it;
  58. return 0;
  59. }
  60. --it;
  61. }
  62. return 0;
  63. }
  64. static inline const uint8_t* search_start_code(const uint8_t* ptr, const uint8_t* end)
  65. {
  66. for(const uint8_t *p = ptr; p + 3 < end; p++)
  67. {
  68. if(0x00 == p[0] && 0x00 == p[1] && (0x01 == p[2] || (0x00==p[2] && 0x01==p[3])))
  69. return p;
  70. }
  71. return end;
  72. }
  73. static inline int h265_nal_type(const unsigned char* ptr)
  74. {
  75. int i = 2;
  76. assert(0x00 == ptr[0] && 0x00 == ptr[1]);
  77. if(0x00 == ptr[2])
  78. ++i;
  79. assert(0x01 == ptr[i]);
  80. return H265_NAL(ptr[i+1]);
  81. }
  82. int H265FileReader::Init()
  83. {
  84. size_t count = 0;
  85. bool vpsspspps = true;
  86. const uint8_t* end = m_ptr + m_capacity;
  87. const uint8_t* nalu = search_start_code(m_ptr, end);
  88. const uint8_t* p = nalu;
  89. while (p < end)
  90. {
  91. const unsigned char* pn = search_start_code(p + 4, end);
  92. size_t bytes = pn - nalu;
  93. int nal_unit_type = h265_nal_type(p);
  94. assert(0 <= nal_unit_type);
  95. if(NAL_VPS == nal_unit_type || NAL_SPS == nal_unit_type || NAL_PPS == nal_unit_type)
  96. {
  97. if(vpsspspps)
  98. {
  99. size_t n = 0x01 == p[2] ? 3 : 4;
  100. std::pair<const uint8_t*, size_t> pr;
  101. pr.first = p + n;
  102. pr.second = bytes;
  103. m_sps.push_back(pr);
  104. }
  105. }
  106. {
  107. if(m_sps.size() > 0) vpsspspps = false; // don't need more vps/sps/pps
  108. vframe_t frame;
  109. frame.nalu = nalu;
  110. frame.bytes = bytes;
  111. frame.time = 40 * count++;
  112. frame.idr = (NAL_IDR_N_LP == nal_unit_type || NAL_IDR_W_RADL == nal_unit_type); // IDR-frame
  113. m_videos.push_back(frame);
  114. nalu = pn;
  115. }
  116. p = pn;
  117. }
  118. m_duration = 40 * count;
  119. return 0;
  120. }