1 /***************************************************************************** 2 3 MPEG Video Packetizing Buffer 4 5 Copyright(C) 2004 John Cannon <spyder@matroska.org> 6 7 This program is free software ; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation ; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY ; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program ; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 21 **/ 22 23 #pragma once 24 25 #include "common/common_pch.h" 26 27 #include "common/math_fwd.h" 28 29 #include "Types.h" 30 #include "CircBuffer.h" 31 32 constexpr auto MPEG_VIDEO_PICTURE_START_CODE = 0x00; 33 constexpr auto MPEG_VIDEO_SEQUENCE_START_CODE = 0xb3; 34 constexpr auto MPEG_VIDEO_EXT_START_CODE = 0xb5; 35 constexpr auto MPEG_VIDEO_GOP_START_CODE = 0xb8; 36 constexpr auto MPEG_VIDEO_USER_START_CODE = 0xb2; 37 38 enum MPEG2BufferState_e { 39 MPEG2_BUFFER_STATE_NEED_MORE_DATA, 40 MPEG2_BUFFER_STATE_CHUNK_READY, 41 MPEG2_BUFFER_STATE_EMPTY, 42 MPEG2_BUFFER_INVALID 43 }; 44 45 constexpr auto MPEG2_I_FRAME = 1; 46 constexpr auto MPEG2_P_FRAME = 2; 47 constexpr auto MPEG2_B_FRAME = 3; 48 49 struct MPEG2SequenceHeader { 50 uint32_t width{}; 51 uint32_t height{}; 52 mtx_mp_rational_t aspectRatio; 53 mtx_mp_rational_t frameRate; 54 uint8_t profileLevelIndication{}; 55 uint8_t progressiveSequence{}; 56 57 MPEG2SequenceHeader(); 58 }; 59 60 struct MPEG2GOPHeader { 61 uint8_t closedGOP; 62 uint8_t brokenLink; 63 uint32_t timeFrames; 64 uint32_t timeSeconds; 65 uint32_t timeMinutes; 66 uint32_t timeHours; 67 68 MPEG2GOPHeader(); 69 }; 70 71 constexpr auto MPEG2_PICTURE_TYPE_FRAME = 0x03; 72 constexpr auto MPEG2_PICTURE_TYPE_TOP_FIELD = 0x01; 73 constexpr auto MPEG2_PICTURE_TYPE_BOTTOM_FIELD = 0x02; 74 75 struct MPEG2PictureHeader { 76 uint32_t temporalReference; 77 uint8_t frameType; 78 uint32_t pictureStructure; 79 uint8_t repeatFirstField; 80 uint8_t topFieldFirst; 81 uint8_t progressive; 82 83 MPEG2PictureHeader(); 84 }; 85 86 class MPEGChunk{ 87 private: 88 binary * data; 89 uint32_t size; 90 uint8_t type; 91 public: MPEGChunk(binary * n_data,uint32_t n_size)92 MPEGChunk(binary* n_data, uint32_t n_size): 93 data(n_data), size(n_size) { 94 95 assert(data); 96 assert(4 <= size); 97 98 type = data[3]; 99 } 100 ~MPEGChunk()101 ~MPEGChunk(){ 102 if(data) 103 delete [] data; 104 } 105 GetType()106 inline uint8_t GetType() const { 107 return type; 108 } 109 GetSize()110 inline uint32_t GetSize() const{ 111 return size; 112 } 113 114 binary & operator[](unsigned int i){ 115 return data[i]; 116 } 117 at(unsigned int i)118 binary & at(unsigned int i) { 119 return data[i]; 120 } 121 GetPointer()122 inline binary * GetPointer(){ 123 return data; 124 } 125 }; 126 127 void ParseSequenceHeader(MPEGChunk* chunk, MPEG2SequenceHeader & hdr); 128 bool ParsePictureHeader(MPEGChunk* chunk, MPEG2PictureHeader & hdr); 129 bool ParseGOPHeader(MPEGChunk* chunk, MPEG2GOPHeader & hdr); 130 131 class MPEGVideoBuffer{ 132 private: 133 CircBuffer * myBuffer; 134 MPEG2BufferState_e state; 135 int32_t chunkStart; 136 int32_t chunkEnd; 137 void UpdateState(); 138 int32_t FindStartCode(uint32_t startPos = 0); 139 public: MPEGVideoBuffer(uint32_t size)140 MPEGVideoBuffer(uint32_t size){ 141 myBuffer = new CircBuffer(size); 142 state = MPEG2_BUFFER_STATE_EMPTY; 143 chunkStart = -1; 144 chunkEnd = -1; 145 } 146 ~MPEGVideoBuffer()147 ~MPEGVideoBuffer(){ 148 delete myBuffer; 149 } 150 GetState()151 inline MPEG2BufferState_e GetState() const { return state; } 152 GetFreeBufferSpace()153 int32_t GetFreeBufferSpace(){ 154 return (myBuffer->buf_capacity - myBuffer->bytes_in_buf); 155 } 156 SetEndOfData()157 void SetEndOfData(){ 158 chunkEnd = myBuffer->GetLength() - 1; 159 } 160 161 void ForceFinal(); //prepares the remaining data as a chunk 162 MPEGChunk * ReadChunk(); 163 int32_t Feed(binary* data, uint32_t numBytes); 164 }; 165