Skip to content

Commit 44508c3

Browse files
committed
Changes
1 parent 066b7a5 commit 44508c3

File tree

5 files changed

+159
-11
lines changed

5 files changed

+159
-11
lines changed

interfaces.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ type Manager interface {
2929
// specified, then the format will be used to create the file or else
3030
// the format is guessed from the path. If no parameters are provided,
3131
// then the default parameters for the format are used.
32-
Create(string, Format, ...Parameters) (Media, error)
32+
Create(string, Format, []Metadata, ...Parameters) (Media, error)
3333

3434
// Create a media stream for writing. The format will be used to
3535
// determine the formar type and one or more CodecParameters used to
3636
// create the streams. If no parameters are provided, then the
3737
// default parameters for the format are used. It is the responsibility
3838
// of the caller to also close the writer when done.
39-
Write(io.Writer, Format, ...Parameters) (Media, error)
39+
Write(io.Writer, Format, []Metadata, ...Parameters) (Media, error)
4040

4141
// Return supported input formats which match any filter, which can be
4242
// a name, extension (with preceeding period) or mimetype. The MediaType
@@ -48,7 +48,7 @@ type Manager interface {
4848
// can be NONE (for any) or combinations of DEVICE and STREAM.
4949
OutputFormats(MediaType, ...string) []Format
5050

51-
// Return supported devices for a given format name
51+
// Return supported devices for a given format.
5252
// Not all devices may be supported on all platforms or listed
5353
// if the device does not support enumeration.
5454
Devices(Format) []Device
@@ -87,7 +87,6 @@ type Manager interface {
8787
}
8888

8989
// Device represents a device for input or output of media streams.
90-
// TODO
9190
type Device interface {
9291
// Device name, format depends on the device
9392
Name() string

manager.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,14 @@ func (manager *manager) Read(r io.Reader, format Format, opts ...string) (Media,
267267
return newReader(r, format, opts...)
268268
}
269269

270-
// Create a media file for writing, from a path.
271-
func (manager *manager) Create(string, Format, ...Parameters) (Media, error) {
272-
return nil, ErrNotImplemented
270+
// Create a media file for writing, from a url, path, or device.
271+
func (manager *manager) Create(url string, format Format, metadata []Metadata, params ...Parameters) (Media, error) {
272+
return createMedia(url, format, metadata, params...)
273273
}
274274

275275
// Create a media stream for writing.
276-
func (manager *manager) Write(io.Writer, Format, ...Parameters) (Media, error) {
277-
return nil, ErrNotImplemented
276+
func (manager *manager) Write(w io.Writer, format Format, metadata []Metadata, params ...Parameters) (Media, error) {
277+
return createWriter(w, format, metadata, params...)
278278
}
279279

280280
// Return version information for the media manager as a set of metadata

mediatype.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ const (
2222
OUTPUT // Muxer
2323
FILE // File or byte stream
2424
DEVICE // Device rather than stream
25+
CODEC // Codec
2526

2627
// Set minimum and maximum values
2728
MIN = UNKNOWN
28-
MAX = DEVICE
29+
MAX = CODEC
2930

3031
// Convenience values
3132
ANY = NONE
@@ -71,6 +72,8 @@ func (v MediaType) FlagString() string {
7172
return "FILE"
7273
case DEVICE:
7374
return "DEVICE"
75+
case CODEC:
76+
return "CODEC"
7477
}
7578
return ""
7679
}

stream.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,39 @@ type stream struct {
1212
*ff.AVStream
1313
}
1414

15+
type writerstream struct {
16+
*ff.AVStream
17+
}
18+
1519
var _ Stream = (*stream)(nil)
20+
var _ Stream = (*writerstream)(nil)
1621

1722
////////////////////////////////////////////////////////////////////////////////
1823
// LIFECYCLE
1924

20-
// Open media from a url, file path or device
25+
// Stream wrapper for decoding
2126
func newStream(ctx *ff.AVStream) *stream {
2227
return &stream{ctx}
2328
}
2429

30+
// Stream wrapper for encoding
31+
func newWriterStream(ctx *ff.AVFormatContext, param Parameters) (*writerstream, error) {
32+
// Parameters - Codec
33+
var codec_id ff.AVCodecID
34+
if param.Type().Is(CODEC) {
35+
codec_id = param.Codec().ID()
36+
} else if param.Type().Is(VIDEO) {
37+
codec_id = ctx.Input().VideoCodec()
38+
} else if param.Type().Is(AUDIO) {
39+
codec_id = ctx.Input().AudioCodec()
40+
} else {
41+
return nil, ErrBadParameter.With("invalid stream parameters")
42+
43+
}
44+
45+
return nil, ErrNotImplemented
46+
}
47+
2548
////////////////////////////////////////////////////////////////////////////////
2649
// PUBLIC METHODS
2750

writer.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package media
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"io"
7+
8+
// Packages
9+
ff "github.com/mutablelogic/go-media/sys/ffmpeg61"
10+
11+
// Namespace imports
12+
. "github.com/djthorpe/go-errors"
13+
)
14+
15+
////////////////////////////////////////////////////////////////////////////////
16+
// TYPES
17+
18+
type writer struct {
19+
t MediaType
20+
output *ff.AVFormatContext
21+
avio *ff.AVIOContextEx
22+
}
23+
24+
type writer_callback struct {
25+
w io.Writer
26+
}
27+
28+
var _ Media = (*writer)(nil)
29+
30+
////////////////////////////////////////////////////////////////////////////////
31+
// LIFECYCLE
32+
33+
// Create media from a url or device
34+
func createMedia(url string, format Format, metadata []Metadata, params ...Parameters) (*writer, error) {
35+
writer := new(writer)
36+
writer.t = OUTPUT
37+
38+
// Guess the output format
39+
var ofmt *ff.AVOutputFormat
40+
if format == nil && url != "" {
41+
ofmt = ff.AVFormat_guess_format("", url, "")
42+
} else if format != nil {
43+
ofmt = format.(*outputformat).ctx
44+
}
45+
if ofmt == nil {
46+
return nil, ErrBadParameter.With("unable to guess the output format")
47+
}
48+
49+
// Allocate the output media context
50+
ctx, err := ff.AVFormat_create_file(url, ofmt)
51+
if err != nil {
52+
return nil, err
53+
} else {
54+
writer.output = ctx
55+
}
56+
57+
// Add streams
58+
for _, param := range params {
59+
stream, err := newWriterStream(ctx, param)
60+
if err != nil {
61+
return nil, errors.Join(err, writer.Close())
62+
} else {
63+
fmt.Println("TODO: STREAM", stream)
64+
}
65+
}
66+
67+
// Open the output file, if needed
68+
if !ctx.Flags().Is(ff.AVFMT_NOFILE) {
69+
w, err := ff.AVFormat_avio_open(url, ff.AVIO_FLAG_WRITE)
70+
if err != nil {
71+
return nil, errors.Join(err, writer.Close())
72+
} else {
73+
ctx.SetPb(w)
74+
writer.avio = w
75+
}
76+
}
77+
78+
// TODO: Metadata
79+
80+
// TODO: Write the header
81+
82+
// Return success
83+
return writer, nil
84+
}
85+
86+
// Create media from io.Writer
87+
// TODO
88+
func createWriter(w io.Writer, format Format, metadata []Metadata, params ...Parameters) (*writer, error) {
89+
return nil, ErrNotImplemented
90+
}
91+
92+
func (w *writer) Close() error {
93+
var result error
94+
95+
// TODO: Write the trailer
96+
97+
// Free resources
98+
if w.avio != nil {
99+
result = errors.Join(result, ff.AVFormat_avio_close(w.avio))
100+
}
101+
result = errors.Join(result, ff.AVFormat_close_writer(w.output))
102+
103+
// Return any errors
104+
return result
105+
}
106+
107+
////////////////////////////////////////////////////////////////////////////////
108+
// PUBLIC METHODS
109+
110+
func (w *writer) Decoder(DecoderMapFunc) (Decoder, error) {
111+
return nil, ErrNotImplemented
112+
}
113+
114+
// Return OUTPUT and combination of DEVICE and STREAM
115+
func (w *writer) Type() MediaType {
116+
return OUTPUT
117+
}
118+
119+
// Return the metadata for the media.
120+
func (w *writer) Metadata() []Metadata {
121+
// Not yet implemented
122+
return nil
123+
}

0 commit comments

Comments
 (0)