mirror of
https://github.com/jech/galene.git
synced 2024-11-10 02:35:58 +01:00
Add support for recording h.264 video.
We store h.264 in Matroska, since we already have the library. We currently store the video width and height as 0.
This commit is contained in:
parent
7d29ef5a64
commit
0623e92760
1 changed files with 60 additions and 13 deletions
|
@ -13,6 +13,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/at-wat/ebml-go/mkvcore"
|
||||||
"github.com/at-wat/ebml-go/webm"
|
"github.com/at-wat/ebml-go/webm"
|
||||||
"github.com/pion/rtp"
|
"github.com/pion/rtp"
|
||||||
"github.com/pion/rtp/codecs"
|
"github.com/pion/rtp/codecs"
|
||||||
|
@ -187,7 +188,7 @@ func (conn *diskConn) warn(message string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// called locked
|
// called locked
|
||||||
func (conn *diskConn) reopen() error {
|
func (conn *diskConn) reopen(extension string) error {
|
||||||
for _, t := range conn.tracks {
|
for _, t := range conn.tracks {
|
||||||
if t.writer != nil {
|
if t.writer != nil {
|
||||||
t.writeBuffered(true)
|
t.writeBuffered(true)
|
||||||
|
@ -197,7 +198,7 @@ func (conn *diskConn) reopen() error {
|
||||||
}
|
}
|
||||||
conn.file = nil
|
conn.file = nil
|
||||||
|
|
||||||
file, err := openDiskFile(conn.directory, conn.username)
|
file, err := openDiskFile(conn.directory, conn.username, extension)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -227,7 +228,7 @@ func (conn *diskConn) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func openDiskFile(directory, username string) (*os.File, error) {
|
func openDiskFile(directory, username, extension string) (*os.File, error) {
|
||||||
filenameFormat := "2006-01-02T15:04:05.000"
|
filenameFormat := "2006-01-02T15:04:05.000"
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
filenameFormat = "2006-01-02T15-04-05-000"
|
filenameFormat = "2006-01-02T15-04-05-000"
|
||||||
|
@ -240,9 +241,11 @@ func openDiskFile(directory, username string) (*os.File, error) {
|
||||||
for counter := 0; counter < 100; counter++ {
|
for counter := 0; counter < 100; counter++ {
|
||||||
var fn string
|
var fn string
|
||||||
if counter == 0 {
|
if counter == 0 {
|
||||||
fn = fmt.Sprintf("%v.webm", filename)
|
fn = fmt.Sprintf("%v.%v", filename, extension)
|
||||||
} else {
|
} else {
|
||||||
fn = fmt.Sprintf("%v-%02d.webm", filename, counter)
|
fn = fmt.Sprintf("%v-%02d.%v",
|
||||||
|
filename, counter, extension,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn = filepath.Join(directory, fn)
|
fn = filepath.Join(directory, fn)
|
||||||
|
@ -278,7 +281,7 @@ type diskTrack struct {
|
||||||
remote conn.UpTrack
|
remote conn.UpTrack
|
||||||
conn *diskConn
|
conn *diskConn
|
||||||
|
|
||||||
writer webm.BlockWriteCloser
|
writer mkvcore.BlockWriteCloser
|
||||||
builder *samplebuilder.SampleBuilder
|
builder *samplebuilder.SampleBuilder
|
||||||
lastSeqno maybeUint32
|
lastSeqno maybeUint32
|
||||||
origin maybeUint32
|
origin maybeUint32
|
||||||
|
@ -300,7 +303,8 @@ func newDiskConn(client *Client, directory string, up conn.Up, remoteTracks []co
|
||||||
client.group.WallOps("Multiple audio tracks, recording just one")
|
client.group.WallOps("Multiple audio tracks, recording just one")
|
||||||
}
|
}
|
||||||
} else if strings.EqualFold(codec, "video/vp8") ||
|
} else if strings.EqualFold(codec, "video/vp8") ||
|
||||||
strings.EqualFold(codec, "video/vp9") {
|
strings.EqualFold(codec, "video/vp9") ||
|
||||||
|
strings.EqualFold(codec, "video/h264") {
|
||||||
if video == nil || video.Label() == "l" {
|
if video == nil || video.Label() == "l" {
|
||||||
video = remote
|
video = remote
|
||||||
} else if remote.Label() != "l" {
|
} else if remote.Label() != "l" {
|
||||||
|
@ -375,6 +379,17 @@ func newDiskConn(client *Client, directory string, up conn.Up, remoteTracks []co
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
conn.hasVideo = true
|
conn.hasVideo = true
|
||||||
|
} else if strings.EqualFold(codec.MimeType, "video/h264") {
|
||||||
|
builder = samplebuilder.New(
|
||||||
|
128, &codecs.H264Packet{}, codec.ClockRate,
|
||||||
|
samplebuilder.WithPartitionHeadChecker(
|
||||||
|
&codecs.H264PartitionHeadChecker{},
|
||||||
|
),
|
||||||
|
samplebuilder.WithPartitionTailChecker(
|
||||||
|
markerPartitionTailChecker,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
conn.hasVideo = true
|
||||||
} else {
|
} else {
|
||||||
// this shouldn't happen
|
// this shouldn't happen
|
||||||
return nil, errors.New(
|
return nil, errors.New(
|
||||||
|
@ -565,7 +580,8 @@ func (conn *diskConn) initWriter(width, height uint32) error {
|
||||||
if conn.file != nil && width == conn.width && height == conn.height {
|
if conn.file != nil && width == conn.width && height == conn.height {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var entries []webm.TrackEntry
|
isWebm := true
|
||||||
|
var desc []mkvcore.TrackDescription
|
||||||
for i, t := range conn.tracks {
|
for i, t := range conn.tracks {
|
||||||
var entry webm.TrackEntry
|
var entry webm.TrackEntry
|
||||||
codec := t.remote.Codec()
|
codec := t.remote.Codec()
|
||||||
|
@ -602,25 +618,56 @@ func (conn *diskConn) initWriter(width, height uint32) error {
|
||||||
PixelHeight: uint64(height),
|
PixelHeight: uint64(height),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
} else if strings.EqualFold(codec.MimeType, "video/h264") {
|
||||||
|
entry = webm.TrackEntry{
|
||||||
|
Name: "Video",
|
||||||
|
TrackNumber: uint64(i + 1),
|
||||||
|
CodecID: "V_MPEG4/ISO/AVC",
|
||||||
|
TrackType: 1,
|
||||||
|
Video: &webm.Video{
|
||||||
|
PixelWidth: uint64(width),
|
||||||
|
PixelHeight: uint64(height),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
isWebm = false
|
||||||
} else {
|
} else {
|
||||||
return errors.New("unknown track type")
|
return errors.New("unknown track type")
|
||||||
}
|
}
|
||||||
entries = append(entries, entry)
|
desc = append(desc,
|
||||||
|
mkvcore.TrackDescription{
|
||||||
|
TrackNumber: uint64(i + 1),
|
||||||
|
TrackEntry: entry,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := conn.reopen()
|
extension := "webm"
|
||||||
|
header := webm.DefaultEBMLHeader
|
||||||
|
if !isWebm {
|
||||||
|
extension = "mkv"
|
||||||
|
h := *header
|
||||||
|
h.DocType = "matroska"
|
||||||
|
header = &h
|
||||||
|
}
|
||||||
|
|
||||||
|
err := conn.reopen(extension)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
writers, err := webm.NewSimpleBlockWriter(conn.file, entries)
|
ws, err := mkvcore.NewSimpleBlockWriter(
|
||||||
|
conn.file, desc,
|
||||||
|
mkvcore.WithEBMLHeader(header),
|
||||||
|
mkvcore.WithSegmentInfo(webm.DefaultSegmentInfo),
|
||||||
|
mkvcore.WithBlockInterceptor(webm.DefaultBlockInterceptor),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.file.Close()
|
conn.file.Close()
|
||||||
conn.file = nil
|
conn.file = nil
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(writers) != len(conn.tracks) {
|
if len(ws) != len(conn.tracks) {
|
||||||
conn.file.Close()
|
conn.file.Close()
|
||||||
conn.file = nil
|
conn.file = nil
|
||||||
return errors.New("unexpected number of writers")
|
return errors.New("unexpected number of writers")
|
||||||
|
@ -630,7 +677,7 @@ func (conn *diskConn) initWriter(width, height uint32) error {
|
||||||
conn.height = height
|
conn.height = height
|
||||||
|
|
||||||
for i, t := range conn.tracks {
|
for i, t := range conn.tracks {
|
||||||
t.writer = writers[i]
|
t.writer = ws[i]
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue