Skip to content

Commit cd5f8eb

Browse files
zjzhang-cn3DRX
andauthored
set bitrate for openh264 (#566)
* Added the set bitrate function for openh264 * add examples * Format --------- Co-authored-by: Jingyang Kang <[email protected]>
1 parent 2d7bdd4 commit cd5f8eb

File tree

6 files changed

+135
-0
lines changed

6 files changed

+135
-0
lines changed

examples/openh264/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
openh264

examples/openh264/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## Instructions
2+
3+
### Install required codecs
4+
5+
In this example, we'll be using openh264 as our video codec. Therefore, we need to make sure that these codecs are installed within our system.
6+
7+
Installation steps:
8+
9+
* [openh264](https://github.com/pion/mediadevices#openh264)
10+
11+
### Download archive examplee
12+
13+
```
14+
git clone https://github.com/pion/mediadevices.git
15+
```
16+
17+
### Run openh264 example
18+
19+
Run `cd mediadevices/examples/openh264 && go build && ./openh264 recorded.h264`
20+
set bitrate ,first press `Ctrl+c` or send a SIGINT signal.
21+
To stop recording,second press `Ctrl+c` or send a SIGINT signal.
22+

examples/openh264/main.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"image"
6+
"io"
7+
"os"
8+
"os/signal"
9+
"syscall"
10+
11+
"github.com/pion/mediadevices"
12+
"github.com/pion/mediadevices/pkg/codec"
13+
"github.com/pion/mediadevices/pkg/codec/openh264"
14+
_ "github.com/pion/mediadevices/pkg/driver/camera" // This is required to register camera adapter
15+
"github.com/pion/mediadevices/pkg/frame"
16+
"github.com/pion/mediadevices/pkg/io/video"
17+
"github.com/pion/mediadevices/pkg/prop"
18+
)
19+
20+
func must(err error) {
21+
if err != nil {
22+
panic(err)
23+
}
24+
}
25+
26+
func main() {
27+
if len(os.Args) != 2 {
28+
fmt.Printf("usage: %s <path/to/file.h264>\n", os.Args[0])
29+
return
30+
}
31+
dest := os.Args[1]
32+
33+
sigs := make(chan os.Signal, 1)
34+
signal.Notify(sigs, syscall.SIGINT)
35+
36+
params, err := openh264.NewParams()
37+
must(err)
38+
params.BitRate = 1_000_000 // 1mbps
39+
40+
codecSelector := mediadevices.NewCodecSelector(
41+
mediadevices.WithVideoEncoders(&params),
42+
)
43+
44+
mediaStream, err := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{
45+
Video: func(c *mediadevices.MediaTrackConstraints) {
46+
c.FrameFormat = prop.FrameFormat(frame.FormatI420)
47+
c.Width = prop.Int(640)
48+
c.Height = prop.Int(480)
49+
},
50+
Codec: codecSelector,
51+
})
52+
must(err)
53+
54+
videoTrack := mediaStream.GetVideoTracks()[0].(*mediadevices.VideoTrack)
55+
defer videoTrack.Close()
56+
57+
videoTrack.Transform(video.TransformFunc(func(r video.Reader) video.Reader {
58+
return video.ReaderFunc(func() (img image.Image, release func(), err error) {
59+
// we send io.EOF signal to the encoder reader to stop reading. Therefore, io.Copy
60+
// will finish its execution and the program will finish
61+
select {
62+
case <-sigs:
63+
return nil, func() {}, io.EOF
64+
default:
65+
}
66+
67+
return r.Read()
68+
})
69+
}))
70+
71+
reader, err := videoTrack.NewEncodedIOReader(params.RTPCodec().MimeType)
72+
must(err)
73+
defer reader.Close()
74+
75+
out, err := os.Create(dest)
76+
must(err)
77+
fmt.Println("Recording... Press Ctrl+c to Set BitRate")
78+
go func() {
79+
_, err = io.Copy(out, reader)
80+
}()
81+
<-sigs
82+
if control, ok := reader.(codec.Controllable); ok {
83+
if ctrl, ok := control.Controller().(codec.KeyFrameController); ok {
84+
fmt.Println("Force Key")
85+
ctrl.ForceKeyFrame()
86+
}
87+
if ctrl, ok := control.Controller().(codec.BitRateController); ok {
88+
fmt.Println("SetBitRate")
89+
ctrl.SetBitRate(200_000)
90+
}
91+
}
92+
fmt.Println("Recording... Press Ctrl+c to stop")
93+
<-sigs
94+
must(err)
95+
fmt.Println("Your video has been recorded to", dest)
96+
}

pkg/codec/openh264/bridge.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,16 @@ void enc_free(Encoder *e, int *eresult) {
6969
free(e);
7070
}
7171

72+
void enc_set_bitrate(Encoder *e, int bitrate) {
73+
SEncParamExt encParamExt;
74+
e->engine->GetOption(ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &encParamExt);
75+
encParamExt.iTargetBitrate=bitrate;
76+
encParamExt.iMaxBitrate=bitrate;
77+
encParamExt.sSpatialLayers[0].iSpatialBitrate = bitrate;
78+
encParamExt.sSpatialLayers[0].iMaxSpatialBitrate = bitrate;
79+
e->engine->SetOption(ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &encParamExt);
80+
}
81+
7282
// There's a good reference from ffmpeg in using the encode_frame
7383
// Reference: https://ffmpeg.org/doxygen/2.6/libopenh264enc_8c_source.html
7484
Slice enc_encode(Encoder *e, Frame f, int *eresult) {

pkg/codec/openh264/bridge.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ typedef struct Encoder {
4444
Encoder *enc_new(const EncoderOptions params, int *eresult);
4545
void enc_free(Encoder *e, int *eresult);
4646
Slice enc_encode(Encoder *e, Frame f, int *eresult);
47+
void enc_set_bitrate(Encoder *e, int bitrate);
4748
#ifdef __cplusplus
4849
}
4950
#endif

pkg/codec/openh264/openh264.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ func (e *encoder) ForceKeyFrame() error {
9696
return nil
9797
}
9898

99+
func (e *encoder) SetBitRate(bitrate int) error {
100+
C.enc_set_bitrate(e.engine, C.int(bitrate))
101+
return nil
102+
}
103+
99104
func (e *encoder) Controller() codec.EncoderController {
100105
return e
101106
}

0 commit comments

Comments
 (0)