Skip to content

Commit 4a46189

Browse files
committed
FLV: Support HEVC(12) and OPUS(13)
1 parent c8e50af commit 4a46189

File tree

3 files changed

+34
-25
lines changed

3 files changed

+34
-25
lines changed

flv/flv.go

+22-13
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ func (v *AudioSamplingRate) From(a aac.SampleRateIndex) {
349349

350350
// The audio codec id, FLV named it the SoundFormat.
351351
// Refer to @doc video_file_format_spec_v10.pdf, @page 76, @section E.4.2 Audio Tags
352+
// It's 4bits, that is 0-16.
352353
type AudioCodec uint8
353354

354355
const (
@@ -365,7 +366,8 @@ const (
365366
AudioCodecAAC // 10 = AAC
366367
AudioCodecSpeex // 11 = Speex
367368
AudioCodecUndefined12
368-
AudioCodecUndefined13
369+
// For FLV, it's undefined, we define it as Opus for WebRTC.
370+
AudioCodecOpus // 13 = Opus
369371
AudioCodecMP3In8kHz // 14 = MP3 8 kHz
370372
AudioCodecDeviceSpecific // 15 = Device-specific sound
371373
AudioCodecForbidden
@@ -395,6 +397,8 @@ func (v AudioCodec) String() string {
395397
return "AAC"
396398
case AudioCodecSpeex:
397399
return "Speex"
400+
case AudioCodecOpus:
401+
return "Opus"
398402
case AudioCodecMP3In8kHz:
399403
return "MP3(8kHz)"
400404
case AudioCodecDeviceSpecific:
@@ -432,15 +436,14 @@ func NewAudioPackager() (AudioPackager, error) {
432436
}
433437

434438
func (v *audioPackager) Encode(frame *AudioFrame) (tag []byte, err error) {
439+
audioTagHeader := []byte{
440+
byte(frame.SoundFormat)<<4 | byte(frame.SoundRate)<<2 | byte(frame.SoundSize)<<1 | byte(frame.SoundType),
441+
}
442+
435443
if frame.SoundFormat == AudioCodecAAC {
436-
return append([]byte{
437-
byte(frame.SoundFormat)<<4 | byte(frame.SoundRate)<<2 | byte(frame.SoundSize)<<1 | byte(frame.SoundType),
438-
byte(frame.Trait),
439-
}, frame.Raw...), nil
444+
return append(append(audioTagHeader, byte(frame.Trait)), frame.Raw...), nil
440445
} else {
441-
return append([]byte{
442-
byte(frame.SoundFormat)<<4 | byte(frame.SoundRate)<<2 | byte(frame.SoundSize)<<1 | byte(frame.SoundType),
443-
}, frame.Raw...), nil
446+
return append(audioTagHeader, frame.Raw...), nil
444447
}
445448
}
446449

@@ -501,6 +504,7 @@ func (v VideoFrameType) String() string {
501504

502505
// The video codec id.
503506
// Refer to @doc video_file_format_spec_v10.pdf, @page 78, @section E.4.3 Video Tags
507+
// It's 4bits, that is 0-16.
504508
type VideoCodec uint8
505509

506510
const (
@@ -511,6 +515,8 @@ const (
511515
VideoCodecOn2VP6Alpha // 5 = On2 VP6 with alpha channel
512516
VideoCodecScreen2 // 6 = Screen video version 2
513517
VideoCodecAVC // 7 = AVC
518+
// See page 79 at @doc https://github.com/CDN-Union/H265/blob/master/Document/video_file_format_spec_v10_1_ksyun_20170615.doc
519+
VideoCodecHEVC VideoCodec = 12 // 12 = HEVC
514520
)
515521

516522
func (v VideoCodec) String() string {
@@ -527,19 +533,22 @@ func (v VideoCodec) String() string {
527533
return "Screen2"
528534
case VideoCodecAVC:
529535
return "AVC"
536+
case VideoCodecHEVC:
537+
return "HEVC"
530538
default:
531539
return "Forbidden"
532540
}
533541
}
534542

535543
// The video AVC frame trait, whethere sequence header or not.
536544
// Refer to @doc video_file_format_spec_v10.pdf, @page 78, @section E.4.3 Video Tags
545+
// If AVC or HEVC, it's 8bits.
537546
type VideoFrameTrait uint8
538547

539548
const (
540-
VideoFrameTraitSequenceHeader VideoFrameTrait = iota // 0 = AVC sequence header
541-
VideoFrameTraitNALU // 1 = AVC NALU
542-
VideoFrameTraitSequenceEOF // 2 = AVC end of sequence (lower level NALU sequence ender is
549+
VideoFrameTraitSequenceHeader VideoFrameTrait = iota // 0 = AVC/HEVC sequence header
550+
VideoFrameTraitNALU // 1 = AVC/HEVC NALU
551+
VideoFrameTraitSequenceEOF // 2 = AVC/HEVC end of sequence (lower level NALU sequence ender is
543552
VideoFrameTraitForbidden
544553
)
545554

@@ -596,7 +605,7 @@ func (v *videoPackager) Decode(tag []byte) (frame *VideoFrame, err error) {
596605
frame.FrameType = VideoFrameType(byte(p[0]>>4) & 0x0f)
597606
frame.CodecID = VideoCodec(byte(p[0]) & 0x0f)
598607

599-
if frame.CodecID == VideoCodecAVC {
608+
if frame.CodecID == VideoCodecAVC || frame.CodecID == VideoCodecHEVC {
600609
frame.Trait = VideoFrameTrait(p[1])
601610
frame.CTS = int32(uint32(p[2])<<16 | uint32(p[3])<<8 | uint32(p[4]))
602611
frame.Raw = tag[5:]
@@ -608,7 +617,7 @@ func (v *videoPackager) Decode(tag []byte) (frame *VideoFrame, err error) {
608617
}
609618

610619
func (v videoPackager) Encode(frame *VideoFrame) (tag []byte, err error) {
611-
if frame.CodecID == VideoCodecAVC {
620+
if frame.CodecID == VideoCodecAVC || frame.CodecID == VideoCodecHEVC {
612621
return append([]byte{
613622
byte(frame.FrameType)<<4 | byte(frame.CodecID), byte(frame.Trait),
614623
byte(frame.CTS >> 16), byte(frame.CTS >> 8), byte(frame.CTS),

https/crypto/ocsp/ocsp_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ func TestOCSPDecode(t *testing.T) {
4343
}
4444

4545
if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) {
46-
t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate)
46+
t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, expected.ThisUpdate)
4747
}
4848

4949
if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) {
50-
t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, expected.NextUpdate)
50+
t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, expected.NextUpdate)
5151
}
5252

5353
if resp.Status != expected.Status {

kxps/kxps_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -60,55 +60,55 @@ func TestKxps_Rps10s(t *testing.T) {
6060
kxps := newKxps(nil, s)
6161

6262
if err := kxps.doSample(time.Unix(0, 0)); err != nil {
63-
t.Errorf("sample failed, err is", err)
63+
t.Errorf("sample failed, err is %+v", err)
6464
} else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 {
6565
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
6666
}
6767

6868
s.s = 10
6969
if err := kxps.doSample(time.Unix(10, 0)); err != nil {
70-
t.Errorf("sample failed, err is", err)
70+
t.Errorf("sample failed, err is %+v", err)
7171
} else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 {
7272
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
7373
}
7474

7575
s.s = 20
7676
if err := kxps.doSample(time.Unix(20, 0)); err != nil {
77-
t.Errorf("sample failed, err is", err)
77+
t.Errorf("sample failed, err is %+v", err)
7878
} else if kxps.Xps10s() != 10.0/10.0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 {
7979
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
8080
} else if err := kxps.doSample(time.Unix(30, 0)); err != nil {
81-
t.Errorf("sample failed, err is", err)
81+
t.Errorf("sample failed, err is %+v", err)
8282
} else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 {
8383
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
8484
}
8585

8686
s.s = 30
8787
if err := kxps.doSample(time.Unix(40, 0)); err != nil {
88-
t.Errorf("sample failed, err is", err)
88+
t.Errorf("sample failed, err is %+v", err)
8989
} else if kxps.Xps10s() != 10.0/10.0 || kxps.Xps30s() != 20.0/30.0 || kxps.Xps300s() != 0 {
9090
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
9191
} else if err := kxps.doSample(time.Unix(50, 0)); err != nil {
92-
t.Errorf("sample failed, err is", err)
92+
t.Errorf("sample failed, err is %+v", err)
9393
} else if kxps.Xps10s() != 0 || kxps.Xps30s() != 20.0/30.0 || kxps.Xps300s() != 0 {
9494
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
9595
}
9696

9797
s.s = 40
9898
if err := kxps.doSample(time.Unix(310, 0)); err != nil {
99-
t.Errorf("sample failed, err is", err)
99+
t.Errorf("sample failed, err is %+v", err)
100100
} else if kxps.Xps10s() != 10.0/10.0 || kxps.Xps30s() != 10.0/30.0 || kxps.Xps300s() != 30.0/300.0 {
101101
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
102102
} else if err := kxps.doSample(time.Unix(320, 0)); err != nil {
103-
t.Errorf("sample failed, err is", err)
103+
t.Errorf("sample failed, err is %+v", err)
104104
} else if kxps.Xps10s() != 0 || kxps.Xps30s() != 10.0/30.0 || kxps.Xps300s() != 30.0/300.0 {
105105
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
106106
} else if err := kxps.doSample(time.Unix(340, 0)); err != nil {
107-
t.Errorf("sample failed, err is", err)
107+
t.Errorf("sample failed, err is %+v", err)
108108
} else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 30.0/300.0 {
109109
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
110110
} else if err := kxps.doSample(time.Unix(610, 0)); err != nil {
111-
t.Errorf("sample failed, err is", err)
111+
t.Errorf("sample failed, err is %+v", err)
112112
} else if kxps.Xps10s() != 0 || kxps.Xps30s() != 0 || kxps.Xps300s() != 0 {
113113
t.Errorf("sample invalid, 10s=%v, 30s=%v, 300s=%v", kxps.Xps10s(), kxps.Xps30s(), kxps.Xps300s())
114114
}

0 commit comments

Comments
 (0)