Skip to content

Commit

Permalink
Fix single idr segment transcoding (#313)
Browse files Browse the repository at this point in the history
* Flush filters
  • Loading branch information
AlexKordic authored Mar 30, 2022
1 parent 7c772da commit ab6ae87
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
Binary file added data/singleframe.ts
Binary file not shown.
30 changes: 30 additions & 0 deletions ffmpeg/ffmpeg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1705,6 +1705,36 @@ func TestTranscoder_IgnoreUnknown(t *testing.T) {
run(cmd)
}

func TestTranscoder_FramesSingle(t *testing.T) {
wd, err := os.Getwd()
require.NoError(t, err)
fname := path.Join(wd, "..", "data", "singleframe.ts")
outNames := []string{
path.Join(wd, "..", "data", "singleframe-out-720.ts"),
path.Join(wd, "..", "data", "singleframe-out-360.ts"),
path.Join(wd, "..", "data", "singleframe-out-240.ts"),
}
// prof := P720p30fps16x9
in := &TranscodeOptionsIn{Fname: fname}
out := []TranscodeOptions{
{Oname: outNames[0], Profile: P720p30fps16x9},
{Oname: outNames[1], Profile: P360p30fps16x9},
{Oname: outNames[2], Profile: P240p30fps16x9},
}
res, err := Transcode3(in, out)
require.NoError(t, err)
for i := 0; i < len(outNames); i++ {
outInfo, err := os.Stat(outNames[i])
if os.IsNotExist(err) {
t.Error(err)
} else {
defer os.Remove(outNames[i])
}
require.NotEqual(t, outInfo.Size(), 0, "must produce output %s", outNames[i])
require.Equal(t, res.Encoded[i].Frames, 1, "must produce single frame in output %s", outNames[i])
}
}

func TestTranscoder_GetCodecInfo(t *testing.T) {
wd, err := os.Getwd()
if err != nil {
Expand Down
21 changes: 19 additions & 2 deletions ffmpeg/transcoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ int transcode(struct transcode_thread *h,
dframe = av_frame_alloc();
if (!dframe) LPMS_ERR(transcode_cleanup, "Unable to allocate frame");

#define FILTERS_NORMAL 0
#define FILTERS_SHOULD_FLUSH 1
#define FILTERS_FLUSHED 2
int filters_state = FILTERS_NORMAL;

while (1) {
// DEMUXING & DECODING
Expand All @@ -228,8 +232,15 @@ int transcode(struct transcode_thread *h,
AVFrame *last_frame = NULL;
av_frame_unref(dframe);
ret = process_in(ictx, dframe, ipkt);
if (ret == AVERROR_EOF) break;
// Bail out on streams that appear to be broken
if (ret == AVERROR_EOF) {
if(filters_state == FILTERS_NORMAL && ictx->flushing) {
// Here we need to flush the filtergraph and encoders
filters_state = FILTERS_SHOULD_FLUSH;
} else {
// Bail out on streams that appear to be broken
break;
}
}
else if (lpms_ERR_PACKET_ONLY == ret) ; // keep going for stream copy
else if (lpms_ERR_INPUT_NOKF == ret) {
LPMS_ERR(transcode_cleanup, "Could not decode; No keyframes in input");
Expand Down Expand Up @@ -346,6 +357,8 @@ int transcode(struct transcode_thread *h,
av_packet_free(&pkt);
} else if (has_frame) {
ret = process_out(ictx, octx, encoder, ost, filter, dframe);
} else if (filters_state == FILTERS_SHOULD_FLUSH) {
ret = process_out(ictx, octx, encoder, ost, filter, NULL);
}
if (AVERROR(EAGAIN) == ret || AVERROR_EOF == ret) continue;
else if (ret < 0) LPMS_ERR(transcode_cleanup, "Error encoding");
Expand All @@ -354,6 +367,10 @@ int transcode(struct transcode_thread *h,
av_packet_unref(ipkt);
}

if(filters_state == FILTERS_SHOULD_FLUSH) {
filters_state = FILTERS_FLUSHED;
}

if (ictx->transmuxing) {
for (i = 0; i < nb_outputs; i++) {
av_interleaved_write_frame(outputs[i].oc, NULL); // flush muxer
Expand Down

0 comments on commit ab6ae87

Please sign in to comment.