@@ -2,6 +2,7 @@ package coremedia
22
33import (
44 "encoding/binary"
5+ "encoding/hex"
56 "fmt"
67
78 "github.com/danielpaulus/quicktime_video_hack/screencapture/common"
@@ -44,6 +45,10 @@ func (info CMSampleTimingInfo) String() string {
4445 info .Duration , info .PresentationTimeStamp , info .DecodeTimeStamp )
4546}
4647
48+ func (buffer CMSampleBuffer ) HasSampleData () bool {
49+ return buffer .SampleData != nil
50+ }
51+
4752//CMSampleBuffer represents the CoreMedia class used to exchange AV SampleData and contains meta information like timestamps or
4853//optional FormatDescriptors
4954type CMSampleBuffer struct {
@@ -98,75 +103,69 @@ func NewCMSampleBufferFromBytes(data []byte, mediaType uint32) (CMSampleBuffer,
98103 if length > len (data ) {
99104 return sbuffer , fmt .Errorf ("less data (%d bytes) in buffer than expected (%d bytes)" , len (data ), length )
100105 }
101-
102- _ , remainingBytes , err = common .ParseLengthAndMagic (remainingBytes , opts )
103- if err != nil {
104- return sbuffer , err
105- }
106- cmtime , err := NewCMTimeFromBytes (remainingBytes )
107- if err != nil {
108- return sbuffer , err
109- }
110- sbuffer .OutputPresentationTimestamp = cmtime
111- sbuffer .SampleTimingInfoArray , remainingBytes , err = parseStia (remainingBytes [24 :])
112- if err != nil {
113- return sbuffer , err
114- }
115-
116- length , remainingBytes , err = common .ParseLengthAndMagic (remainingBytes , sdat )
117- if err != nil {
118- return sbuffer , err
119- }
120- sbuffer .SampleData = remainingBytes [:length - 8 ]
121- length , remainingBytes , err = common .ParseLengthAndMagic (remainingBytes [length - 8 :], nsmp )
122- if err != nil {
123- return sbuffer , err
124- }
125- if length != 12 {
126- return sbuffer , fmt .Errorf ("invalid length for nsmp %d, should be 12" , length )
127- }
128- sbuffer .NumSamples = int (binary .LittleEndian .Uint32 (remainingBytes ))
129-
130- sbuffer .SampleSizes , remainingBytes , err = parseSampleSizeArray (remainingBytes [4 :])
131- if err != nil {
132- return sbuffer , err
133- }
134-
135- //audio buffers usually end after samplesize
136- if len (remainingBytes ) == 0 {
137- return sbuffer , nil
138- }
139- if binary .LittleEndian .Uint32 (remainingBytes [4 :]) == FormatDescriptorMagic {
140- sbuffer .HasFormatDescription = true
141- fdscLength := binary .LittleEndian .Uint32 (remainingBytes )
142- sbuffer .FormatDescription , err = NewFormatDescriptorFromBytes (remainingBytes [:fdscLength ])
143- if err != nil {
144- return sbuffer , err
106+ for len (remainingBytes ) > 0 {
107+ switch binary .LittleEndian .Uint32 (remainingBytes [4 :]) {
108+ case opts :
109+ cmtime , err := NewCMTimeFromBytes (remainingBytes [8 :])
110+ if err != nil {
111+ return sbuffer , err
112+ }
113+ sbuffer .OutputPresentationTimestamp = cmtime
114+ remainingBytes = remainingBytes [32 :]
115+ case stia :
116+ sbuffer .SampleTimingInfoArray , remainingBytes , err = parseStia (remainingBytes )
117+ if err != nil {
118+ return sbuffer , err
119+ }
120+ case sdat :
121+ length , remainingBytes , err = common .ParseLengthAndMagic (remainingBytes , sdat )
122+ if err != nil {
123+ return sbuffer , err
124+ }
125+ sbuffer .SampleData = remainingBytes [:length - 8 ]
126+ remainingBytes = remainingBytes [length - 8 :]
127+ case nsmp :
128+
129+ length , remainingBytes , err = common .ParseLengthAndMagic (remainingBytes , nsmp )
130+ if err != nil {
131+ return sbuffer , err
132+ }
133+ if length != 12 {
134+ return sbuffer , fmt .Errorf ("invalid length for nsmp %d, should be 12" , length )
135+ }
136+ sbuffer .NumSamples = int (binary .LittleEndian .Uint32 (remainingBytes ))
137+ remainingBytes = remainingBytes [4 :]
138+ case ssiz :
139+ sbuffer .SampleSizes , remainingBytes , err = parseSampleSizeArray (remainingBytes )
140+ if err != nil {
141+ return sbuffer , err
142+ }
143+ case FormatDescriptorMagic :
144+ sbuffer .HasFormatDescription = true
145+ fdscLength := binary .LittleEndian .Uint32 (remainingBytes )
146+ sbuffer .FormatDescription , err = NewFormatDescriptorFromBytes (remainingBytes [:fdscLength ])
147+ if err != nil {
148+ return sbuffer , err
149+ }
150+ remainingBytes = remainingBytes [fdscLength :]
151+ case satt :
152+ attachmentsLength := binary .LittleEndian .Uint32 (remainingBytes )
153+ sbuffer .Attachments , err = NewIndexDictFromBytesWithCustomMarker (remainingBytes [:attachmentsLength ], satt )
154+ if err != nil {
155+ return sbuffer , err
156+ }
157+ remainingBytes = remainingBytes [attachmentsLength :]
158+ case sary :
159+ saryLength := binary .LittleEndian .Uint32 (remainingBytes )
160+ sbuffer .Sary , err = NewIndexDictFromBytes (remainingBytes [8 :saryLength ])
161+ remainingBytes = remainingBytes [saryLength :]
162+ default :
163+ unknownMagic := string (remainingBytes [4 :8 ])
164+ return sbuffer , fmt .Errorf ("unknown magic type:%s (0x%x), cannot parse value %s" , unknownMagic , remainingBytes [4 :8 ], hex .Dump (remainingBytes ))
145165 }
146- remainingBytes = remainingBytes [fdscLength :]
147- }
148- //audio buffers usually end after samplesize
149- if len (remainingBytes ) == 0 {
150- return sbuffer , nil
151- }
152166
153- attachmentsLength := binary .LittleEndian .Uint32 (remainingBytes )
154- sbuffer .Attachments , err = NewIndexDictFromBytesWithCustomMarker (remainingBytes [:attachmentsLength ], satt )
155- if err != nil {
156- return sbuffer , err
157- }
158- remainingBytes = remainingBytes [attachmentsLength :]
159- saryLength := binary .LittleEndian .Uint32 (remainingBytes )
160- if binary .LittleEndian .Uint32 (remainingBytes [4 :]) != sary {
161- return sbuffer , fmt .Errorf ("wrong magic, expected sary got:%x" , remainingBytes [4 :8 ])
162- }
163- sbuffer .Sary , err = NewIndexDictFromBytes (remainingBytes [8 :saryLength ])
164- if err != nil {
165- return sbuffer , err
166- }
167- if len (remainingBytes [saryLength :]) != 0 {
168- return sbuffer , fmt .Errorf ("CmSampleBuf should have been read completely but still contains bytes: %x" , remainingBytes [saryLength :])
169167 }
168+
170169 return sbuffer , nil
171170}
172171
0 commit comments