-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
issues # 1689 and # 1697 #1734
issues # 1689 and # 1697 #1734
Conversation
@@ -1393,7 +1408,7 @@ public synchronized Frame grabFrame(boolean doAudio, boolean doVideo, boolean do | |||
AVRational time_base = video_st.time_base(); | |||
timestamp = 1000000L * pts * time_base.num() / time_base.den(); | |||
// best guess, AVCodecContext.frame_number = number of decoded frames... | |||
frameNumber = (int)Math.round(timestamp * getFrameRate() / 1000000L); | |||
frameNumber = (int)Math.floor(timestamp * getFrameRate() / 1000000L); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is floor() better than round()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While fixing #1697 I decided that in all cases when we round some floating results we should simulate result of integer division, so we should round towards zero, like floor does
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean that when we use round(), we might be getting the next frame by mistake, but when we use floor() this doesn't happen, and in the worst case we might be getting the previous frame instead, which is better?
@@ -77,10 +77,15 @@ | |||
|
|||
/** Constants defining data type in the frame*/ | |||
public static enum Type { | |||
UNKNOWN, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make UNKNOWN = -1, making sure VIDEO = 0, and let's also follow the order of FFmpeg, unless there's a good reason not to: AVMEDIA_TYPE_UNKNOWN = -1, AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_DATA, AVMEDIA_TYPE_SUBTITLE, AVMEDIA_TYPE_ATTACHMENT
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All right. I swapped data and subtitle by accident.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I forgot, but we can't set the ordinal() for enum, so for backward compatibility, we shouldn't put UNKNOWN first. Do we even need an UNKNOWN though? It might be problematic for forward compatibility. We could just initialize the field to null like all the rest of the fields. What do you think?
Actually, UNKNOWN is not necessary, I added it just by analogy with original ffmpeg definition. We can use null instead.3 янв. 2022 г. 18:00 пользователь Samuel Audet ***@***.***> написал:
@saudet commented on this pull request.
In src/main/java/org/bytedeco/javacv/Frame.java:
@@ -77,10 +77,15 @@
/** Constants defining data type in the frame*/
public static enum Type {
+ UNKNOWN,
And I forgot, but we can't set the ordinal() for enum, so for backward compatibility, we shouldn't put UNKNOWN first. Do we even need an UNKNOWN though? It might be problematic for forward compatibility. We could just initialize the field to null like all the rest of the fields. What do you think?
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
Yes, that's right. round may give us next or previous integer, while floor is always predictable.3 янв. 2022 г. 17:56 пользователь Samuel Audet ***@***.***> написал:
@saudet commented on this pull request.
In src/main/java/org/bytedeco/javacv/FFmpegFrameGrabber.java:
@@ -1393,7 +1408,7 @@ public synchronized Frame grabFrame(boolean doAudio, boolean doVideo, boolean do
AVRational time_base = video_st.time_base();
timestamp = 1000000L * pts * time_base.num() / time_base.den();
// best guess, AVCodecContext.frame_number = number of decoded frames...
- frameNumber = (int)Math.round(timestamp * getFrameRate() / 1000000L);
+ frameNumber = (int)Math.floor(timestamp * getFrameRate() / 1000000L);
Do you mean that when we use round(), we might be getting the next frame by mistake, but when we use floor() this doesn't happen, and in the worst case we might be getting the previous frame instead, which is better?
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
Ok, sounds good! Please update this branch accordingly. Thanks! |
Updated the branch. In addition, I realized that my changes in |
We can set stream_index to -1 any time we want, we just need to make sure to call av_packet_unref() before doing that, such as here: https://github.com/bytedeco/javacv/blob/master/src/main/java/org/bytedeco/javacv/FFmpegFrameGrabber.java#L714-L717 |
But we just have set
to return a frame with some data. Now if we call |
Ah, yes, ok I see what you mean. So, readPacket is false on the first pass, but it gets set to true on the second pass here: if (!readPacket) {
readPacket = true;
continue;
} But you've removed that... why? |
Well, because the logic including this part was initially incorrect.
So, now
the fist task could be solved by setting stream index to -1 for that packet (as I suggested initially). But then it will not be unref. So we should retain its stream index as initial (this way the second task will be solved automatically if we set readPacket to true somhow - but how?). A possible way could be to check if frame.opaque is equal to the previous packet, and then to read new packet if it is true. But the frame.opaque may be changed in a user code (somewhere between two succeeding |
In general, this data processing problem occurs due to the fact that data is handled differently than audio or video. In the case of audio or video, we use the send_packet / receive_frame functions, which themselves suggest whether additional packets need to be read. In the case of data, we do not have such capabilities - we just have to return this data as frame.data and ensure that the new package is read on the next |
Right, the reason to use that block is precisely so that doData behaves like doVideo and doAudio. I suppose it doesn't work when doData is false, yeah. So maybe something like this? } else {
if (!readPacket) {
readPacket = true;
continue;
}
if (doData ...
}
} |
Yes, that should work correctly as well as the last suggested code in the framenumber branch. The only difference I can see is that processing data packets with
will always require additional run of the external while(!done) loop to set readPacket=true, while in the case of
it is set true from the very beginning for any not video/audio packets. That can be slightly more efficient (but only in case of the data packets processing, which is not so often situation though). So now we have to determine which solution is the best. |
Actually, something like looks more clean: } else if (readPacket && doData && whatever) {
// ...
} else if (!readPacket) {
readPacket = true;
} That way, we don't have a |
Ok. I agree. But why should we check readPacket in the last else?6 янв. 2022 г. 5:58 пользователь Samuel Audet ***@***.***> написал:
Actually, something like looks more clean:
} else if (readPacket && doData && whatever) {
// ...
} else if (!readPacket) {
readPacket = true;
}
That way, we don't have a continue out of no where, which makes it clear that readPacket is always going to be set and that we're eventually going to either process/return something, or reach the end of the file/stream.
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
We don't need to, we can just force it to true, sure. |
No description provided.