Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api2-decode-encode-video.cpp example and correct stream tear-down sequence #113

Closed
mmomtchev opened this issue Nov 21, 2023 · 3 comments · Fixed by #116
Closed

api2-decode-encode-video.cpp example and correct stream tear-down sequence #113

mmomtchev opened this issue Nov 21, 2023 · 3 comments · Fixed by #116

Comments

@mmomtchev
Copy link
Contributor

I am using avcpp to create Node.js bindings for ffmpeg as a PoC for nobind

It is a very good C++ wrapper and it would be a pity to leave it to fall into disrepair.

It seems that the example/api2-samples/api2-decode-encode-video.cpp does not work with ffmpeg 5.0/6.0.

It does not set the PTS/DTS when writing and ffmpeg complains and (sometimes) eventually chokes.

I added some rudimentary PTS/DTS calculations - they should probably go into the example - and now the problem is the flushing of the last frame.

Looking from the code:

This expects that an EOF is signaled by decode returning a falsy frame. However it does not do that - at the last packet, readPacket returns a falsy packet, but when pusing it through the codec, it returns one more valid frame. When trying to read again, readPacket returns another falsy packet and this time decode throws an EOF error - which probably means that it shouldn't have been called at this point.

Do you know what is the correct sequence to tear down the stream?

@mmomtchev
Copy link
Contributor Author

This is what I do to manually count the frames w/ resynchronization on the input stream when it is possible:
master...mmomtchev:avcpp:example-pts-dts

@mmomtchev
Copy link
Contributor Author

There are two separate issues that prevent the clean teardown

First one:

if (inFrame && inFrame.timeBase() != Rational()) {

There are two possible sources for the timebase here - either from the current frame - which works for all frames except the last one where the encoder is called with an empty frame - either from m_stream when m_stream.isValid(). However the encoder is not constructed with the stream - only the decoder is. The encoder must use its own timebase field here - and all three options must be mutually exclusive - currently a valid stream will replace the timebase of the frame.

Second one:

if (ret < 0 && ret != AVERROR(EAGAIN))

This should be:
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
just like in the function above and below it

@h4tr3d
Copy link
Owner

h4tr3d commented Nov 23, 2023

Thanks for reporting and fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants