Skip to content

Commit

Permalink
* Add FrameRecorder.videoSideData/audioSideData properties and `FF…
Browse files Browse the repository at this point in the history
…mpegFrameRecorder.setDisplayRotation()` for convenience (issue #1976)
  • Loading branch information
saudet committed May 14, 2023
1 parent 2d8263c commit b1c95f1
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

* Add `FrameRecorder.videoSideData/audioSideData` properties and `FFmpegFrameRecorder.setDisplayRotation()` for convenience ([issue #1976](https://github.com/bytedeco/javacv/issues/1976))
* Fix `FFmpegFrameGrabber.grab()` not returning audio frames buffered by the codec ([issue #1971](https://github.com/bytedeco/javacv/issues/1971))
* Upgrade dependencies for OpenBLAS 0.3.23, OpenCV 4.7.0, FFmpeg 6.0 ([issue #1693](https://github.com/bytedeco/javacv/issues/1693)), librealsense2 2.53.1, Leptonica 1.83.0, Tesseract 5.3.1

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2017 Samuel Audet
* Copyright (C) 2016-2023 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
Expand Down Expand Up @@ -318,6 +318,7 @@ public void testFFmpegFrameGrabberSeeking() throws IOException {
recorder.setSampleFormat(AV_SAMPLE_FMT_FLTP);
recorder.setAudioCodec(AV_CODEC_ID_AAC);
recorder.setAudioQuality(0);
recorder.setDisplayRotation((seektestnum - 2) * 90.0);
recorder.start();
if (seektestnum!=2) {
Frame frame = new Frame(640, 480, Frame.DEPTH_UBYTE, 3);
Expand Down Expand Up @@ -361,6 +362,7 @@ public void testFFmpegFrameGrabberSeeking() throws IOException {
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(tempFile);
grabber.setVideoOption("threads", "1"); // more precise without threads
grabber.start();
assertEquals((seektestnum - 2) * 90.0, grabber.getDisplayRotation(), 0);
int length = (int) ( grabber.getLengthInTime() - 1000000L);


Expand Down
48 changes: 47 additions & 1 deletion src/main/java/org/bytedeco/javacv/FFmpegFrameRecorder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2022 Samuel Audet
* Copyright (C) 2009-2023 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
Expand Down Expand Up @@ -206,6 +206,10 @@ public void release() throws Exception {
public synchronized void releaseUnsafe() throws Exception {
started = false;

if (display_matrix != null) {
display_matrix.releaseReference();
}

if (plane_ptr != null && plane_ptr2 != null) {
plane_ptr.releaseReference();
plane_ptr2.releaseReference();
Expand Down Expand Up @@ -388,6 +392,7 @@ static class SeekCallback extends Seek_Pointer_long_int {
private AVPacket video_pkt, audio_pkt;
private int[] got_video_packet, got_audio_packet;
private AVFormatContext ifmt_ctx;
private IntPointer display_matrix;

private volatile boolean started = false;

Expand All @@ -398,6 +403,15 @@ public void setCloseOutputStream(boolean closeOutputStream) {
this.closeOutputStream = closeOutputStream;
}

/** Sets the rotation in degrees to the side data of the video stream. */
public void setDisplayRotation(double angle) {
if (display_matrix == null) {
display_matrix = new IntPointer(9).retainReference();
}
av_display_rotation_set(display_matrix, -angle);
setVideoSideData("Display Matrix", display_matrix.asByteBuffer());
}

@Override public int getFrameNumber() {
return picture == null ? super.getFrameNumber() : (int)picture.pts();
}
Expand Down Expand Up @@ -821,6 +835,22 @@ public synchronized void startUnsafe() throws Exception {
av_dict_set(metadata, new BytePointer(e.getKey(), charset), new BytePointer(e.getValue(), charset), 0);
}
video_st.metadata(metadata);

for (Entry<String, Buffer> e : videoSideData.entrySet()) {
int type = -1;
for (int i = 0; i < AV_PKT_DATA_NB; i++) {
BytePointer s = av_packet_side_data_name(i);
if (s != null && !s.isNull() && e.getKey().equals(s.getString())) {
type = i;
break;
}
}
Pointer p = new Pointer(e.getValue());
BytePointer b = av_stream_new_side_data(video_st, type, p.capacity());
if (b != null && !b.isNull()) {
b.capacity(p.capacity()).put(p);
}
}
}

if (audio_st != null && inpAudioStream == null) {
Expand Down Expand Up @@ -892,6 +922,22 @@ public synchronized void startUnsafe() throws Exception {
av_dict_set(metadata, new BytePointer(e.getKey(), charset), new BytePointer(e.getValue(), charset), 0);
}
audio_st.metadata(metadata);

for (Entry<String, Buffer> e : audioSideData.entrySet()) {
int type = -1;
for (int i = 0; i < AV_PKT_DATA_NB; i++) {
BytePointer s = av_packet_side_data_name(i);
if (s != null && !s.isNull() && e.getKey().equals(s.getString())) {
type = i;
break;
}
}
Pointer p = new Pointer(e.getValue());
BytePointer b = av_stream_new_side_data(audio_st, type, p.capacity());
if (b != null && !b.isNull()) {
b.capacity(p.capacity()).put(p);
}
}
}

AVDictionary options = new AVDictionary(null);
Expand Down
33 changes: 32 additions & 1 deletion src/main/java/org/bytedeco/javacv/FrameRecorder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2018 Samuel Audet
* Copyright (C) 2009-2023 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
Expand All @@ -26,6 +26,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;
Expand Down Expand Up @@ -119,6 +120,8 @@ public static FrameRecorder create(String className, String filename, int width,
protected Map<String, String> metadata = new HashMap<String, String>();
protected Map<String, String> videoMetadata = new HashMap<String, String>();
protected Map<String, String> audioMetadata = new HashMap<String, String>();
protected Map<String, Buffer> videoSideData = new HashMap<String, Buffer>();
protected Map<String, Buffer> audioSideData = new HashMap<String, Buffer>();
protected int frameNumber = 0;
protected long timestamp = 0;
protected int maxBFrames = -1;
Expand Down Expand Up @@ -356,6 +359,34 @@ public void setAudioMetadata(String key, String value) {
audioMetadata.put(key, value);
}

public Map<String, Buffer> getVideoSideData() {
return videoSideData;
}
public void setVideoSideData(Map<String, Buffer> 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<String, Buffer> getAudioSideData() {
return audioSideData;
}
public void setAudioSideData(Map<String, Buffer> 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;
}
Expand Down

0 comments on commit b1c95f1

Please sign in to comment.