Skip to content

Commit 200f3bc

Browse files
committed
Updated muxing code
1 parent 36e8b19 commit 200f3bc

File tree

3 files changed

+123
-37
lines changed

3 files changed

+123
-37
lines changed

encoder.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,13 @@ func (encoder *encoder) Close() error {
146146
// Return success
147147
return nil
148148
}
149+
150+
////////////////////////////////////////////////////////////////////////////////
151+
// PRIVATE METHODS
152+
153+
func (encoder *encoder) encode(fn MuxFunc) (*ff.AVPacket, error) {
154+
packet, err := fn(encoder.stream.Id())
155+
if packet != nil {
156+
}
157+
158+
}

sys/ffmpeg61/avcodec_encoding.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,15 @@ func AVCodec_receive_packet(ctx *AVCodecContext, pkt *AVPacket) error {
5050
}
5151
return nil
5252
}
53+
54+
// Write a packet to an output media file ensuring correct interleaving.
55+
// This function will buffer the packets internally as needed to make sure the packets in the output file are
56+
// properly interleaved, usually ordered by increasing dts. Callers doing their own interleaving should
57+
// call av_write_frame() instead of this function.
58+
func AVCodec_interleaved_write_frame(ctx *AVFormatContext, pkt *AVPacket) error {
59+
if err := AVError(C.av_interleaved_write_frame((*C.AVFormatContext)(ctx), (*C.AVPacket)(pkt))); err != 0 {
60+
return err
61+
}
62+
// Return success
63+
return nil
64+
}

writer.go

Lines changed: 101 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -193,45 +193,109 @@ func (w *writer) Decoder(DecoderMapFunc) (Decoder, error) {
193193
return nil, ErrOutOfOrder.With("not an input stream")
194194
}
195195

196-
func (w *writer) Mux(context.Context, MuxFunc) error {
197-
return ErrNotImplemented
198-
199-
/*
200-
while (1) {
201-
AVStream *in_stream, *out_stream;
202-
203-
ret = av_read_frame(ifmt_ctx, pkt);
204-
if (ret < 0)
205-
break;
206-
207-
in_stream = ifmt_ctx->streams[pkt->stream_index];
208-
if (pkt->stream_index >= stream_mapping_size ||
209-
stream_mapping[pkt->stream_index] < 0) {
210-
av_packet_unref(pkt);
211-
continue;
212-
}
213-
214-
pkt->stream_index = stream_mapping[pkt->stream_index];
215-
out_stream = ofmt_ctx->streams[pkt->stream_index];
216-
log_packet(ifmt_ctx, pkt, "in");
217-
218-
// copy packet
219-
av_packet_rescale_ts(pkt, in_stream->time_base, out_stream->time_base);
220-
pkt->pos = -1;
221-
log_packet(ofmt_ctx, pkt, "out");
222-
223-
ret = av_interleaved_write_frame(ofmt_ctx, pkt);
224-
// pkt is now blank (av_interleaved_write_frame() takes ownership of
225-
// its contents and resets pkt), so that no unreferencing is necessary.
226-
// This would be different if one used av_write_frame().
227-
if (ret < 0) {
228-
fprintf(stderr, "Error muxing packet\n");
229-
break;
230-
}
231-
}
232-
*/
196+
func (w *writer) Mux(ctx context.Context, fn MuxFunc) error {
197+
// Check fn
198+
if fn == nil {
199+
return ErrBadParameter.With("nil mux function")
200+
}
201+
202+
// Create a new map of encoders
203+
encoders := make(map[int]*encoder, len(w.encoder))
204+
for k, v := range w.encoder {
205+
encoders[k] = v
206+
}
207+
208+
FOR_LOOP:
209+
for {
210+
select {
211+
case <-ctx.Done():
212+
break FOR_LOOP
213+
default:
214+
// Loop until no more encoders are available to send packets
215+
if len(encoders) == 0 {
216+
break FOR_LOOP
217+
}
218+
219+
// Find the first encoder which should return a packet
220+
next_time := 0
221+
next_stream := 0
222+
for stream := range encoders {
223+
if next_time == 0 || encoder.nextTime() < next_time {
224+
next_time = encoder.nextTime()
225+
next_stream = stream
226+
}
227+
}
228+
229+
// Get a packet from the encoder
230+
packet, err := encoders[next_stream].encode(fn)
231+
if errors.Is(err, io.EOF) {
232+
break FOR_LOOP
233+
} else if err != nil {
234+
return err
235+
} else if packet == nil {
236+
// Remove the encoder from the map
237+
delete(encoders, next_stream)
238+
continue FOR_LOOP
239+
}
240+
241+
// Send the packet to the muxer
242+
//av_packet_rescale_ts(pkt, in_stream->time_base, out_stream->time_base);
243+
// Packet's stream_index field must be set to the index of the corresponding stream in s->streams.
244+
// The timestamps (pts, dts) must be set to correct values in the stream's timebase
245+
// (unless the output format is flagged with the AVFMT_NOTIMESTAMPS flag, then they can be set
246+
// to AV_NOPTS_VALUE). The dts for subsequent packets in one stream must be strictly increasing
247+
// (unless the output format is flagged with the AVFMT_TS_NONSTRICT, then they merely have to
248+
// be nondecreasing). duration should also be set if known.
249+
if err := ff.AVCodec_interleaved_write_frame(w.output, packet); err != nil {
250+
return err
251+
}
252+
}
253+
}
254+
255+
// Flush
256+
if err := ff.AVCodec_interleaved_write_frame(w.output, nil); err != nil {
257+
return err
258+
}
259+
260+
// Return the context error, which will be nil if the loop ended normally
261+
return ctx.Err()
233262
}
234263

264+
/*
265+
while (1) {
266+
AVStream *in_stream, *out_stream;
267+
268+
ret = av_read_frame(ifmt_ctx, pkt);
269+
if (ret < 0)
270+
break;
271+
272+
in_stream = ifmt_ctx->streams[pkt->stream_index];
273+
if (pkt->stream_index >= stream_mapping_size ||
274+
stream_mapping[pkt->stream_index] < 0) {
275+
av_packet_unref(pkt);
276+
continue;
277+
}
278+
279+
pkt->stream_index = stream_mapping[pkt->stream_index];
280+
out_stream = ofmt_ctx->streams[pkt->stream_index];
281+
log_packet(ifmt_ctx, pkt, "in");
282+
283+
// copy packet
284+
av_packet_rescale_ts(pkt, in_stream->time_base, out_stream->time_base);
285+
pkt->pos = -1;
286+
log_packet(ofmt_ctx, pkt, "out");
287+
288+
ret = av_interleaved_write_frame(ofmt_ctx, pkt);
289+
// pkt is now blank (av_interleaved_write_frame() takes ownership of
290+
// its contents and resets pkt), so that no unreferencing is necessary.
291+
// This would be different if one used av_write_frame().
292+
if (ret < 0) {
293+
fprintf(stderr, "Error muxing packet\n");
294+
break;
295+
}
296+
}
297+
*/
298+
235299
// Return OUTPUT and combination of DEVICE and STREAM
236300
func (w *writer) Type() MediaType {
237301
return OUTPUT

0 commit comments

Comments
 (0)