Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
.env
**/*.log
**/*.h264
**/*.h264log
**/*.mp4
**/*.fmp4
**/*.ogg
**/*.raw
**/*.exe
2 changes: 1 addition & 1 deletion examples/record-video/videorecoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func main() {
if person.BVideoOn {
// Start listening to their video feed
// {"evt":12303,"body":{"subInfoList":[{"id":16778240,"size":2,"bOn":false}]},"seq":18}
session.VideoSubscribeRequest(person.ID, 4)
session.VideoSubscribeRequest(person.ID, 4) // HQ: 4, MED: 3
} else {
// Stop listening to their video feed
// {"evt":12305,"body":{"subIDList":[{"id":16778240}]},"seq":17}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/RealKeyboardWarrior/zoomer
go 1.14

require (
github.com/RealKeyboardWarrior/joy4 v1.0.31 // indirect
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.4.2
github.com/joho/godotenv v1.4.0
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
github.com/RealKeyboardWarrior/joy4 v1.0.29 h1:rLocLhfPdP2sdgXYf/5WlCgXcJYKDQZzUv06FSudWoE=
github.com/RealKeyboardWarrior/joy4 v1.0.29/go.mod h1:nEH4UPkq2g3twTHS4l5YmmYanYzi53N31S+87pEqmdk=
github.com/RealKeyboardWarrior/joy4 v1.0.30 h1:CNlyC9uUmyGmwIfmw49t2lr8/k1wTCpbJ6tXM0ghvPo=
github.com/RealKeyboardWarrior/joy4 v1.0.30/go.mod h1:kMdgn+vjjtfOOMTs/i1s8DHqGw5jKrMJqbGsAdZTOII=
github.com/RealKeyboardWarrior/joy4 v1.0.31 h1:IggOsIKN5XkjOARfDk/ERabVnz3mPEtZ0cyzi2JFges=
github.com/RealKeyboardWarrior/joy4 v1.0.31/go.mod h1:kMdgn+vjjtfOOMTs/i1s8DHqGw5jKrMJqbGsAdZTOII=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
Expand Down
4 changes: 2 additions & 2 deletions zoom/codecs/h264/video_depacketizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ func (depacketizer *VideoDepacketizer) Unmarshal(packet []byte) ([]byte, error)
}

// 4. Decrypt the ciphertext
log.Printf("body iv=%v body=%v tag=%v", hex.EncodeToString(decodedPayload.IV), hex.EncodeToString(decodedPayload.Ciphertext), hex.EncodeToString(decodedPayload.Tag))
log.Printf("crypto: body iv=%v body=%v tag=%v", hex.EncodeToString(decodedPayload.IV), hex.EncodeToString(decodedPayload.Ciphertext), hex.EncodeToString(decodedPayload.Tag))
ciphertextWithTag := append(decodedPayload.Ciphertext, decodedPayload.Tag...)
plaintext, err := depacketizer.decryptor.Decrypt(decodedPayload.IV, ciphertextWithTag)
if err != nil {
return nil, err
}
log.Printf("rtp: decrypted=%v", hex.EncodeToString(plaintext))
log.Printf("crypto: decrypted=%v", hex.EncodeToString(plaintext))

return plaintext, nil
} else {
Expand Down
4 changes: 2 additions & 2 deletions zoom/codecs/opus/audio_depacketizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ func (depacketizer *AudioDepacketizer) Unmarshal(packet []byte) ([]byte, error)
}

// 2. Decrypt the ciphertext
log.Printf("body iv=%v body=%v tag=%v", hex.EncodeToString(decodedPayload.IV), hex.EncodeToString(decodedPayload.Ciphertext), hex.EncodeToString(decodedPayload.Tag))
log.Printf("crypto: body iv=%v body=%v tag=%v", hex.EncodeToString(decodedPayload.IV), hex.EncodeToString(decodedPayload.Ciphertext), hex.EncodeToString(decodedPayload.Tag))
ciphertextWithTag := append(decodedPayload.Ciphertext, decodedPayload.Tag...)
plaintext, err := depacketizer.decryptor.Decrypt(decodedPayload.IV, ciphertextWithTag)
if err != nil {
return nil, err
}
log.Printf("rtp: decrypted=%v", hex.EncodeToString(plaintext))
log.Printf("crypto: decrypted=%v", hex.EncodeToString(plaintext))

return plaintext, nil
}
Expand Down
17 changes: 17 additions & 0 deletions zoom/formats/h264raw/muxer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package h264raw

import (
"io"
"os"
"time"
)

func Recorder() (io.WriteCloser, error) {
f, err := os.Create(time.Now().Format("2006-01-02-15-04-05") + ".h264")
if err != nil {
return nil, err
}
return f, nil
// defer f.Close()
// n2, err := f.Write(d2)
}
123 changes: 123 additions & 0 deletions zoom/formats/mp4/muxer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package mp4

import (
"encoding/hex"
"fmt"
"log"
"time"

"github.com/RealKeyboardWarrior/joy4/av"
"github.com/RealKeyboardWarrior/joy4/av/avutil"
"github.com/RealKeyboardWarrior/joy4/codec/h264parser"
"github.com/RealKeyboardWarrior/joy4/format"
)

func init() {
format.RegisterAll()
}

type Mp4Recorder struct {
muxer av.MuxCloser
initialized bool
prevDuration time.Duration
}

func NewRecorder() (*Mp4Recorder, error) {
muxer, err := avutil.Create(time.Now().Format("2006-01-02-15-04-05") + ".fmp4")
if err != nil {
return nil, err
}

log.Printf("Mp4Recorder: starting")
return &Mp4Recorder{
muxer: muxer,
initialized: false,
prevDuration: time.Duration(0),
}, nil
}

func (recorder *Mp4Recorder) tryInitialize(nalus []byte) error {
codec, err := h264parser.PktToCodecData(av.Packet{
IsKeyFrame: true,
Data: nalus,
})
if err != nil {
return err
}
if codec == nil {
return fmt.Errorf("failed to initialize muxer because no codec data was extracted from nalus")
}

codecs := []av.CodecData{codec}
if err = recorder.muxer.WriteHeader(codecs); err != nil {
return err
}

recorder.initialized = true
return nil
}

func IsKeyFrame(naluz []byte) bool {
nalus, _ := h264parser.SplitNALUs(naluz)
log.Printf("Mp4Recorder: processing %v nalus", len(nalus))
for _, nalu := range nalus {
if len(nalu) > 0 {
naltype := nalu[0] & 0x1f
if naltype == 5 {
return true
}
}
}
return false
}

func (recorder *Mp4Recorder) WritePacket(nalus []byte, duration time.Duration) error {
if !recorder.initialized {
if err := recorder.tryInitialize(nalus); err != nil {
log.Printf("Mp4Recorder: failed to initialize with packet")
return nil
} else {
log.Printf("Mp4Recorder: initialized")
}
}

log.Printf("Mp4Recorder: writing packet")
isKeyFrame := IsKeyFrame(nalus)
avccBytes, err := h264parser.AnnexBToAVCC(nalus)
if err != nil {
return err
}

if avccBytes == nil {
log.Printf("skipping writing packet, conversion to AVCC yielded no VCL units in %v", hex.EncodeToString(nalus))
return nil
}

recorder.prevDuration = recorder.prevDuration + duration
err = recorder.muxer.WritePacket(av.Packet{
IsKeyFrame: isKeyFrame,
Idx: int8(0),
CompositionTime: time.Duration(0),
Time: recorder.prevDuration,
Data: avccBytes,
})
if err != nil {
return err
}

return nil
}

func (recorder *Mp4Recorder) Close() error {
if !recorder.initialized {
log.Printf("warn: Mp4Recorder was never initialized")
return nil
}

log.Printf("Mp4Recorder: closing")
if err := recorder.muxer.WriteTrailer(); err != nil {
return err
}

return recorder.muxer.Close()
}
2 changes: 1 addition & 1 deletion zoom/rtp/ext/rtp_metadata_screenshare.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func DecodeScreenShareMetadata(rtpPacket *rtp.Packet) (*RtpMetadata, error) {
log.Printf("rtp extensions [RtpId id=%v] [meta=%v] [%v]", id, svcMeta, resolutionMeta)

if rtpPacket.PayloadType == 110 {
log.Printf("rtp [PT type=10] payload=%v", hex.EncodeToString(rtpPacket.Payload))
log.Printf("rtp [PT type=%v] payload=%v", rtpPacket.PayloadType, hex.EncodeToString(rtpPacket.Payload))
return nil, nil
} else if rtpPacket.PayloadType == 99 {
// Expected payload format
Expand Down
2 changes: 1 addition & 1 deletion zoom/rtp/ext/rtp_metadata_video.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func DecodeVideoMetadata(rtpPacket *rtp.Packet) (*RtpMetadata, error) {
}
}
if rtpPacket.PayloadType == 110 {
log.Printf("rtp [PT type=10] payload=%v", hex.EncodeToString(rtpPacket.Payload))
log.Printf("rtp [PT type=%v] payload=%v", rtpPacket.PayloadType, hex.EncodeToString(rtpPacket.Payload))
return nil, nil
} else if rtpPacket.PayloadType == 98 {
// Expected payload format
Expand Down
27 changes: 22 additions & 5 deletions zoom/rtp/rtp_decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,18 @@ func (parser *ZoomRtpDecoder) getSampleBuilderFor(ssrc uint32) (*samplebuilder.S
}

// TODO: think about reasonable max late
maxLate := uint16(400)
// TODO: add audio support
maxLate := uint16(400) // Amount of RTP packets that can be in the queue
var sampleRate uint32
var depacketizer rtp.Depacketizer
switch parser.streamType {
case STREAM_TYPE_SCREENSHARE, STREAM_TYPE_VIDEO:
depacketizer = h264.NewVideoDepacketizer(decryptor)
sampleRate = uint32(90000)
case STREAM_TYPE_AUDIO:
depacketizer = opus.NewAudioDepacketizer(decryptor)
sampleRate = uint32(16000)
}

// TODO: fix sample rate
sampleRate := uint32(1)
parser.sampleBuilders[ssrc] = samplebuilder.New(maxLate, depacketizer, sampleRate)
}
return parser.sampleBuilders[ssrc], nil
Expand All @@ -100,6 +100,7 @@ func (parser *ZoomRtpDecoder) Decode(rawPkt []byte) (*media.Sample, error) {
return nil, err
}

log.Printf("rtp: active decoder %v", parser.streamType)
log.Printf("rtp header [M = %v] [PT type=%v] [SN seq=%v] [TS timestamp=%v] [P padding=%v size=%v] [ssrc=%v csrc=%v]", rtpPacket.Marker, rtpPacket.PayloadType, rtpPacket.SequenceNumber, rtpPacket.Timestamp, rtpPacket.Padding, rtpPacket.PaddingSize, rtpPacket.SSRC, rtpPacket.CSRC)
log.Printf("rtp payload [PYLD size=%v data=%v]", len(rtpPacket.Payload), hex.EncodeToString(rtpPacket.Payload))

Expand Down Expand Up @@ -143,13 +144,29 @@ func (parser *ZoomRtpDecoder) Decode(rawPkt []byte) (*media.Sample, error) {
// 4. Push the RTP packet to the sampleBuilder, this re-orders the packets based
// on the RTP Sequence, they may arrive out of order aggregates them and calls
// the correct depacketizer (VideoDepacketizer / AudioDepacketizer).
sampleBuilder.Push(rtpPacket)
switch parser.streamType {
case STREAM_TYPE_VIDEO:
if rtpPacket.PayloadType == 98 {
sampleBuilder.Push(rtpPacket)
} else {
log.Printf("ZoomRtpDecoder: skipping writing RTP packet to SampleBuilder because wrong PT")
return nil, nil
}
case STREAM_TYPE_SCREENSHARE:
fallthrough
case STREAM_TYPE_AUDIO:
sampleBuilder.Push(rtpPacket)
}

// 5. Pop a sample, may return nil if no packets are ready yet.
sample := sampleBuilder.Pop()
// WARNING: SAMPLE THAT WAS POPPED MAY NOT BE ASSOCIATED WITH THE RTP PACKET!
// THIS IS BECAUSE THE SAMPLE BUILDER ALWAYS LAGS BEHIND ONE PACKET AND MAY
// AGGREGATE PACKETS IN THE CASE OF VIDEO STREAMS.

if sample != nil && sample.PrevDroppedPackets > 0 {
log.Printf("ZoomRtpDecoder: dropped %v packets", sample.PrevDroppedPackets)
}

return sample, nil
}
43 changes: 43 additions & 0 deletions zoom/rtp/rtp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package rtp

import (
"encoding/hex"
"log"
"testing"

"github.com/pion/rtp"
)

func TestRtpPacketPayloadType110(t *testing.T) {

rawPkts := []string{
"00b2260501039e90d9b2659bed2e2c01000402bede0004124000003560be396c396c50007000001c865adb6e92bd7f53c1335880949ab1717da719828bcc344b97f830fd42650d07ee2479c8da9e3bf5e46c7fb411b1d496d8abedab7bbabc874d2fb749b0226000245ee3f7591617ac251bf85ed9d4120693a686461b84a7c0665f7ff65baf90802fb44cab5ee022bcd7986f2f52d1f5777d7e6333c58ae900db76ce489628d832c95e6b8846d4da92673dfef61177e07903efea2a980c26957e1d1a0f062dc581a42631c521438af44a0a0b0bd92c7ed8cabf42d6a217aa85280893e14097877b013f2a158929167679c2fd3f57b685860260ab08a32006bce7eb31b2035b59cc7b4fb9e803320fd0bfb261ddb8819c7ddd338129fb695a73be02bb9a544633e14ca0b9d873af5ead211d59274db6dccddde0a09168a20606e7cfa146f3d1c030d6b0ca46c1bd9cd887484106cc9025d5a0ba21bd6ea951c70724c7a09c058234f5863e81e93550c420d76998c9b5c28b80e8f082f0b6da4c5fc3df3686efb0961efd40677861c09a1f8999d830c4a0fe3f121b7d660899e87c3de1138733066ccda5442f9193623779a3214e6b94beb2e986eaa04d32994ed45a4747df58ccdda4df4426786fdabedaa3f1ed7a7a34941d98e9619a467afd04393207d8d13d002b0b00d9d5f71085cf5ba7d991370ea220158369fe29f2a195b1518f0c0c0fdb406d69b42d6bfae172d78696b3a848b7dd4e8e6a512f759c6db8adb977aead0e563bb2724e95ef07aa6a56e2a6e802017c8c11fe06e40de8b7f4e34f8e9026798f053c74880c5c9c29a3b1201d2455d4abe5b11054f3a3d4b2892f16bbb0f1da1f189cec74d79a8efb5018b2bbca806481e9d887353bbba063829997e8d5929d0f21c60be784dcdbafa9de81bec67ea4fa199f68cdc060c50bce3e74cf290d0258ed485df7d3c6d4f2b95c99a4f047c9ecbffd0204c4f58ad4c68d1e77826bb77c64a8b6de99f03b035b1c60c8960f9b65837b574374e93f7c18ec30f4da0fe451b31c5afc52dbde18b940dc45e253b860a45a3d45393116c3407880c6b308cedf0ba3740c253ac0e681f671d1c174248a794705b2cba2ad645db974815ded40891dac18e93884ec1db20d7ea072cb6aca9c02ed89cbcf2dda9afd239e40edd60e9d0748d87a19171f98c6055c20ccc49d3a49e2fbe558ba132cb8cee88189c045dfb6dd0c204a1866dc0dcd48fafb695dc14115b15e929bc0a42dfc2e4f379630cf3e6613b0e4932176314b925e5dbeb684597a6ea84190ab6de556b1",
"00b22d0501011a90d9b2079bed4b5a01000402bede0004124000003560963976396c50007000001c8666e6c75b98a3f69020981a797963df9c4802c88b923f1cf6abc0291b8341182cb142a3aebef0c997d46277d9ae4614a5789a941b55b71655823bd017d732f63ccb3507e078fdae0014feaa2f5123a96cf8d2cbf0513a0deeac84ca2c2ba67a73c39da0b6ae1d61647e4fb1df4f9da0c07dd31e392579dcf8ad8d3f080a2d9987e651204f543bbbfd2aa3bf9d758300c07dfb6ff387a6be0f4049946645d23731e4a8af6630fe959d77281059433f3bdc7519cf6ce9638b5a103961f356998ed3f1f1141e84efcdc75a54ccfc508afa6d93ef09739b398701e7318e3bbd84cf2fe8c32680bb7f02489afa1577a8f0209aca3de63ea22f6ecfbc1005722feb5a93dd092fd889f5ce72803616acc0c2e96b4ac5cb245f66cd251500af46f98297376a2ab56406a415cb42f0de38bf6cbdb561f49a8412c4ab2772c38baea14f3bc423f0d5f92889f14126c3df178e42916ced46a906688bee303cce89144b86c6c0066c3f8d692c13c90a7537b010dc7c77f3f26afc6248ae854c0e16e24c47ef4d426733f482c9b3eb2e40a2250ebcfa5947c0a5378a7654f05c90bf35525f2aaef9a85a86ce844a03f9e7801f406a9a0d85f71a35e50d94d7c75ba70072409b325a89e8d98e80",
"00b244030101aa9045b2409bee536001000402bede00041240000035e25e39d039c650007000001c4e83a0a32dff3e73b204e8e27bfc3b5c3665978e942d9ba684ecc79aa491608f2ef004198c2a140355975e2769f718ccffd66535e72c92daa89a3d5891389da0bfb3671f157bb4a4ba0bde599128fb371b06eca7dc651e36ac8303f0c57bed79fa69ad3e378cc4067c8ff77f3af1a3787fa1edfaad82f7bd7a59b90e33dcee8526ae2c5311f1299dde6b044c6597a82f6209df3f8ed8bb9370fbcd2ea46c785f1b9e204b2025e579227f4c5a5a72282c6cfafbc5fecd194b52e2bd6f05e213c951abdaa7dbb15430e5adc9aed8f6aee01d467ec54a2e36075c79511601f422997dfc19ecde7ef26eef3736aa6b10e8088311628363675888672aa1d0e97ba49cf68e7bf06ebf673eb96a9c3ce5f624aeabd99ed608fb0357238335a4e5d74aeb79e8fa0228c4fdee6ddd56dd4eb7ab9c9da05f4ddfaaca3f0d531ab3e557b12b6ad8522474b0c747f0b9e367dbeadad2b2e32aaa1838e1facf5c0df6bb7e2f9f7a510829dd13a2",
"00b25d0401012c9031b2969befb2f001000402bede0004124000003525b23a3e3a3450007000001ca250bc03eaf6b9c8954ae93c9fc397dbe020e22abcda2a2a8c6f48fe7927f009ddbc3abcdb91688ff3caee922cb2813a0f74c913f2493e5577998f19b92ef6ee68b86c82bd8c797b7bc13dc0bc854962a73310243adbdd4257c7fbda836d5a07e86e3798fc78661b6fdebcac9a59da308153db43d914da5e89a938b1c17375bc42d9776a4f17f545b766538ff9629d28488fcac340ca388a5f52b7206a9ac7fba842d4b7887108bc043c027c3d6f7dfee46406b07dda6bceb9d76a430e6733eaaad8de4848de0b712f89f70cced5f67da41f98853724ae7bb1ba142cc755b0e3e513c45add04d834fa45ff359e3d19fae800a2772ee6a229db9adfb8d80843257ff71ec712e538f9fd8cbf6d36c62dee1e221f451692883f09686bdbf3fc4177edc616e9200508618cc45377278639015874d2e5617ec3d1d8f00aaedd978e1247e687a5eaefdacad59302ac67f485e2f5ffff61696355073597206975f04d5d71ff4676d095a2a9bf50b3e39b69d91897d9160c06032b55d807d3065c963e28e85cbb5e403bd8c486ab851f7685155eeefec68ca7",
"00b276030101bc9045b25a9bf100ec01000402bede00041240000035e25e3aac3aa250007000001c4e63e7b7db84cb55b1cd17b695a2fb060f96f34ab0d0d8f3016f5ce133fa70cc16c63b5eadfae39d254aa037cd1c50eecfbe29ffc38cb9ae327a06a13c65751ced2f2b033f292782f2e1f7b6f72c3b5ca74f64cef085ddf484af07d0770c3815cfeef7ea8b1471193abab365ffcfe02255206b62feb8d35a6a8a43233843e808210d000475aedb18dc24797dee7c46aab22be2e74acab4f4e5ddd6a96850cf0d16adb847dfbb7800cfbf3f24b86e829eb2c7e7b14c4cbe492a5a1d6b20718615fe296fdc2afec0c3fb5ed8267c3265cd735d83aa20ba7a6d38383f7e3a00f44483db795cc55b87a3204d27d458fa54f2086cb26f244ff2ba5753cb7aa34f75655a4286cda5b60eea449ace3001c03ffedded40998fdcdbd0424ee4b6c276eb75fe11365575b43cb03bdc41cdbbd2d9720f80115310676ef2589b7aa3126ce63736b9e4bfdde80df06f0beaa22a1959b1e409f11bf80fa5ad2cb1c291b0ab138a614fe8d1aa7fc41aa25f458864e7318e08f4639c537f6ac225f0a70ebfa465e8e32dfb80b07d80cbd7295a15a1b7f6a12aae73f0ac",
"00b2900301018f9045b2949bf2721001000402bede00041240000035e25e3b243b1a50007000001c4e13e858957903fd1b5e5a9786cfdf998266cdbc1a13dc2902fae6cac4493a6e977868212ccdb1c2813a3179340618e00fb0c53f16fe8f4f04fdd6afde8d21a133795f00d6620fce7a341f932f91efdbc053f230d41d92807ee16295eda21e195bc3e64093f3ed91d9bdfb3c11bb3ab2d4a6c3f34ce2fec7313e9c79056feaaec67fdc39ab117f02fffcee1c17e7c1b5809efcd24d946b8b988b651e03fb8652f4cf9e8e71fde36bbd1f2819c280baad56f9e62746643524a74034c66fab8ba6397a750f418f69175ad582eeb8752bebde5fa9532c554061ae6df2e5799bc6b71323ca98fd842300753615b3d1c79fba090d2efbd504a00dd15f876e63b2f1769566ba0ba313dc6d209d17db3e88467e08aa1d6108ff54376616b178b3753f504e5efe79673d09bd850c5abaa641346c3207a6b4a45971cf054120a61e6bc8bf82b1722afb993679065608399f206927cc011ea5eba0d35fe9c24e86282712cb",
"00b2a8040101ad9031b28a9bf3bfb201000402bede0004124000003525b23b923b8850007000001ca250996d38094f7950594786c781c4b1242e3bec806384df6860c5c45b241bb04c799dbd68122515c14da485364a40c033d6635e9eb6f056eebbf92ccb2ac0beaa85e190d5a274499bd7023a83e5443852afe0ac9bef8a002f9ea0ede87b00439b98e0fb52917d3e50a44788bfa8abdc28a71898481cb3296a4803bf913b79840f765b154f0bd407ab0d78d8cce0c2156a737eb2b8682f84e080d0caf742d33ecdb349c55e566bdf116049ffaa487d8903ff76ed7098c32610d075a4091ff2647a81fd0c2787033254de171e682f0007ba592eb594295807a30a7f9429d4f81af9a7c1a9e8a8618b35cd7b236a3636958770303240e943b788470f9cd8ec51c798f3cbae45be9ee1e20ffa78247a498107f0774d4e2d79f3e04e4e247e5274f4fadaec8e1a90304fd4bca5a2f66fcef87d524edf2d5d5325f874006873357d1965fd89f5ac327e0ef1f915aa84cd953895e8b88021b4cb28f37a669ba3c445f831c823b59e56bbd32527f1fbff27e581c3dbd6a49ce390815681",
// Different logs:
"0043890501018e90d94321d9d1928601000402bede0004124ff0003560bc1d171d1750007000001c86626016058f369134035bb21d6a14e06557061af34a3809a4ef1c2717a369537bc7681f584642320f6be686a705b03fa76e00aa52f7dd4869b378c5f0fde56b473ded015ce52d280f93c51c7b980e97063dc95acf89f1290468c102ce319ec27ab19b5cfc3f2ec0dbb036bf8b2a1c2049a11a4724c6d5d7387c54419320a34eebe0654632755efb163808a21608b7c817516170e3fdef7b21a605fbba0f4b48f948ebc03c09bae4a469fdbebb87c35aa5a267daa29d1c37bfce83a3dd2911d8e4f6b87ac97d2cf84eea9328b4e7363772b557036363c71c0b82ffdb42eedc9efb9ea76660b65cebcd61afb1cb30c8ad41d0b0e516febd885b09bcf15f03496ec21ec9a7ac2c4f760e9ed22e2f95d334e11aa39fc0d5822f41ccf5602660cb062dc527e66bba05a13eda669737951297ddd4bd9d1e4a32d4fe5d6ff1efaa9288e8a1ae66f88b61d81dc985e946e3c9ae6d4442c6f82801699f7933ea9f8c6c815ab78e7984ff94333d0f3fc4c60bd1d3d069c32ee3514f74284afcaf935b57c20839875d2cdb8b3ce41e3c526db18c8c4122c4cfcffea5ffd792b31cff0060bb3cfa61afc411be184b6644032bbaa9acc65319",
}

//depakcetizer := h264.NewNaluPacketizer()

for _, rawPktHex := range rawPkts {
rawPkt, _ := hex.DecodeString(rawPktHex[14:])
rtpPacket := rtp.Packet{}
err := rtpPacket.Unmarshal(rawPkt)
if err != nil {
t.Error(err)
}
log.Printf("%v", rtpPacket)

// frame, err := depakcetizer.Unmarshal(rtpPacket.Payload)
// if err != nil {
// t.Error(err)
// }
// log.Printf("frame = %v", hex.EncodeToString(frame))
}

}
4 changes: 2 additions & 2 deletions zoom/streampkt/pkt_audio.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ func (pkt *ZoomAudioPkt) Unmarshal(data []byte) error {
pkt.lenRtp = rtpPktSize
pkt.Rtp = rtpPkt

if len(data) > int(45+rtpPktSize) {
pkt.AdditionalData = data[45+rtpPktSize:]
if len(data) > int(23+rtpPktSize) {
pkt.AdditionalData = data[23+rtpPktSize:]
}
return nil
}
Expand Down
Loading