diff --git a/CHANGELOG.md b/CHANGELOG.md
index c98d36e8..5e5815f5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,5 @@
+ * Add `FrameGrabber.videoSideData/audioSideData` properties and `FFmpegFrameGrabber.getDisplayRotation()` for convenience ([issue #1361](https://github.com/bytedeco/javacv/issues/1361))
* Add to `FFmpegFrameGrabber` and `FFmpegFrameRecorder` constructors taking a `URL` for convenience and clarity
* Fix incorrect call to `opencv_calib3d.stereoRectify()` in `ProjectiveDevice` ([issue #1802](https://github.com/bytedeco/javacv/issues/1802))
* Retry after 10 ms when `av_read_frame()` returns `EAGAIN` in `FFmpegFrameGrabber.grabFrame()` ([issue #1784](https://github.com/bytedeco/javacv/issues/1784))
@@ -6,7 +7,7 @@
* Update `FFmpegStreamingTimeout` sample to use `timeout` instead of `stimeout` for RTSP ([pull #1758](https://github.com/bytedeco/javacv/pull/1758))
* Restore static calls to `FFmpegFrameGrabber.tryLoad()` and `FFmpegFrameRecorder.tryLoad()` ([issue #1756](https://github.com/bytedeco/javacv/issues/1756))
* Enable by default on `RealSense2FrameGrabber.start()` all color, depth, and IR streams as `videoStream` ([pull #1750](https://github.com/bytedeco/javacv/pull/1750))
- * Upgrade dependencies for OpenBLAS 0.3.20, OpenCV 4.6.0, FFmpeg 5.0.1, Leptonica 1.82.0 ([pull #1791](https://github.com/bytedeco/javacv/pull/1791)), Tesseract 5.1.0
+ * Upgrade dependencies for OpenBLAS 0.3.20, OpenCV 4.6.0, FFmpeg 5.0.1, Leptonica 1.82.0 ([pull #1791](https://github.com/bytedeco/javacv/pull/1791)), Tesseract 5.2.0
### February 11, 2022 version 1.5.7
* Fix accuracy and latency issues with `FFmpegFrameGrabber.setVideoFrameNumber()` ([pull #1734](https://github.com/bytedeco/javacv/pull/1734))
diff --git a/platform/pom.xml b/platform/pom.xml
index c9a48cf5..1055ded9 100644
--- a/platform/pom.xml
+++ b/platform/pom.xml
@@ -93,7 +93,7 @@
org.bytedeco
tesseract-platform
- 5.1.0-${javacpp.version}
+ 5.2.0-${javacpp.version}
diff --git a/pom.xml b/pom.xml
index f9c53c6d..d1aa2aba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -135,7 +135,7 @@
org.bytedeco
tesseract
- 5.1.0-${javacpp.version}
+ 5.2.0-${javacpp.version}
diff --git a/src/main/java/org/bytedeco/javacv/FFmpegFrameGrabber.java b/src/main/java/org/bytedeco/javacv/FFmpegFrameGrabber.java
index c67b851a..e154cb41 100644
--- a/src/main/java/org/bytedeco/javacv/FFmpegFrameGrabber.java
+++ b/src/main/java/org/bytedeco/javacv/FFmpegFrameGrabber.java
@@ -607,6 +607,48 @@ public double getVideoFrameRate() {
return entry == null || entry.value() == null ? null : entry.value().getString(charset);
}
+ @Override public Map getVideoSideData() {
+ if (video_st == null) {
+ return super.getVideoSideData();
+ }
+ videoSideData = new HashMap();
+ for (int i = 0; i < video_st.nb_side_data(); i++) {
+ AVPacketSideData sd = video_st.side_data().position(i);
+ String key = av_packet_side_data_name(sd.type()).getString();
+ Buffer value = sd.data().capacity(sd.size()).asBuffer();
+ videoSideData.put(key, value);
+ }
+ return videoSideData;
+ }
+
+ @Override public Buffer getVideoSideData(String key) {
+ return getVideoSideData().get(key);
+ }
+
+ /** Returns the rotation in degrees from the side data of the video stream, or 0 if unknown. */
+ public double getDisplayRotation() {
+ ByteBuffer b = (ByteBuffer)getVideoSideData("Display Matrix");
+ return b != null ? av_display_rotation_get(new IntPointer(new BytePointer(b))) : 0;
+ }
+
+ @Override public Map getAudioSideData() {
+ if (audio_st == null) {
+ return super.getAudioSideData();
+ }
+ audioSideData = new HashMap();
+ for (int i = 0; i < audio_st.nb_side_data(); i++) {
+ AVPacketSideData sd = audio_st.side_data().position(i);
+ String key = av_packet_side_data_name(sd.type()).getString();
+ Buffer value = sd.data().capacity(sd.size()).asBuffer();
+ audioSideData.put(key, value);
+ }
+ return audioSideData;
+ }
+
+ @Override public Buffer getAudioSideData(String key) {
+ return getAudioSideData().get(key);
+ }
+
/** default override of super.setFrameNumber implies setting
* of a frame close to a video frame having that number */
@Override public void setFrameNumber(int frameNumber) throws Exception {
diff --git a/src/main/java/org/bytedeco/javacv/FrameGrabber.java b/src/main/java/org/bytedeco/javacv/FrameGrabber.java
index 6a58cd0e..f531536f 100644
--- a/src/main/java/org/bytedeco/javacv/FrameGrabber.java
+++ b/src/main/java/org/bytedeco/javacv/FrameGrabber.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2019 Samuel Audet
+ * Copyright (C) 2009-2022 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import java.nio.Buffer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
@@ -200,6 +201,8 @@ public static enum SampleMode {
protected Map metadata = new HashMap();
protected Map videoMetadata = new HashMap();
protected Map audioMetadata = new HashMap();
+ protected Map videoSideData = new HashMap();
+ protected Map audioSideData = new HashMap();
protected int frameNumber = 0;
protected long timestamp = 0;
protected int maxDelay = -1;
@@ -485,6 +488,34 @@ public void setAudioMetadata(String key, String value) {
audioMetadata.put(key, value);
}
+ public Map getVideoSideData() {
+ return videoSideData;
+ }
+ public void setVideoSideData(Map videoSideData) {
+ this.videoSideData = videoSideData;
+ }
+
+ public Buffer getVideoSideData(String key) {
+ return videoSideData.get(key);
+ }
+ public void setVideoSideData(String key, Buffer value) {
+ videoSideData.put(key, value);
+ }
+
+ public Map getAudioSideData() {
+ return audioSideData;
+ }
+ public void setAudioSideData(Map audioSideData) {
+ this.audioSideData = audioSideData;
+ }
+
+ public Buffer getAudioSideData(String key) {
+ return audioSideData.get(key);
+ }
+ public void setAudioSideData(String key, Buffer value) {
+ audioSideData.put(key, value);
+ }
+
public int getFrameNumber() {
return frameNumber;
}