Skip to content

Commit

Permalink
Set video codec based on rtp type
Browse files Browse the repository at this point in the history
  • Loading branch information
skilurius committed Aug 26, 2024
1 parent 5fd2e2d commit 2e9ad7e
Show file tree
Hide file tree
Showing 13 changed files with 45 additions and 197 deletions.
2 changes: 0 additions & 2 deletions app/src/main/java/com/geehe/fpvue/SettingsChanged.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@

public interface SettingsChanged {
void onChannelSettingChanged(final int channel);

void onCodecSettingChanged(final String codec);
}
86 changes: 10 additions & 76 deletions app/src/main/java/com/geehe/fpvue/VideoActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,12 @@ public void run() {
int lastVideoW = 0, lastVideoH = 0;
WfbLinkManager wfbLinkManager;
BroadcastReceiver batteryReceiver;
VideoPlayer videoPlayerH264;
VideoPlayer videoPlayerH265;
VideoPlayer videoPlayer;
private ActivityVideoBinding binding;
private OSDManager osdManager;
private String activeCodec;
private ParcelFileDescriptor dvrFd = null;
private Timer dvrIconTimer = null;

public static String getCodec(Context context) {
return context.getSharedPreferences("general",
Context.MODE_PRIVATE).getString("codec", "h265");
}

public static int getChannel(Context context) {
return context.getSharedPreferences("general",
Context.MODE_PRIVATE).getInt("wifi-channel", 161);
Expand Down Expand Up @@ -141,13 +134,9 @@ protected void onCreate(Bundle savedInstanceState) {

// Setup video players
setContentView(binding.getRoot());
videoPlayerH264 = new VideoPlayer(this);
videoPlayerH264.setIVideoParamsChanged(this);
binding.svH264.getHolder().addCallback(videoPlayerH264.configure1());

videoPlayerH265 = new VideoPlayer(this);
videoPlayerH265.setIVideoParamsChanged(this);
binding.svH265.getHolder().addCallback(videoPlayerH265.configure1());
videoPlayer = new VideoPlayer(this);
videoPlayer.setIVideoParamsChanged(this);
binding.mainVideo.getHolder().addCallback(videoPlayer.configure1());

osdManager = new OSDManager(this, binding);
osdManager.setUp();
Expand Down Expand Up @@ -181,28 +170,12 @@ protected void onCreate(Bundle savedInstanceState) {
});
}

// Codecs
String codecPref = getCodec(this);
SubMenu codecMenu = popup.getMenu().addSubMenu("Codec");
codecMenu.setHeaderTitle("Current: " + codecPref);

String[] codecs = getResources().getStringArray(R.array.codecs);
for (String codecStr : codecs) {
if (codecPref.equals(codecStr)) {
continue;
}
codecMenu.add(codecStr).setOnMenuItemClickListener(item -> {
onCodecSettingChanged(codecStr);
return true;
});
}

// OSD
SubMenu osd = popup.getMenu().addSubMenu("OSD");
MenuItem lock = osd.add(osdManager.isOSDLocked() ? "Unlock OSD" : "Lock OSD");
MenuItem lock = osd.add(osdManager.getTitle());
lock.setOnMenuItemClickListener(item -> {
osdManager.lockOSD(!osdManager.isOSDLocked());
lock.setTitle(osdManager.isOSDLocked() ? "Unlock OSD" : "Lock OSD");
lock.setTitle(osdManager.getTitle());
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
item.setActionView(new View(this));
return false;
Expand Down Expand Up @@ -249,7 +222,6 @@ protected void onCreate(Bundle savedInstanceState) {
}
return true;
});

MenuItem fmp4 = recording.add("fMP4");
fmp4.setCheckable(true);
fmp4.setChecked(getDvrMP4());
Expand Down Expand Up @@ -333,7 +305,7 @@ private void startDvr(Uri dvrUri) {
}
try {
dvrFd = getContentResolver().openFileDescriptor(dvrUri, "rw");
currentPlayer().startDvr(dvrFd.getFd(), getDvrMP4());
videoPlayer.startDvr(dvrFd.getFd(), getDvrMP4());
} catch (IOException e) {
Log.e(TAG, "Failed to open dvr file ", e);
dvrFd = null;
Expand All @@ -353,7 +325,7 @@ private void stopDvr() {
return;
}
binding.imgRecIndicator.setVisibility(View.INVISIBLE);
currentPlayer().stopDvr();
videoPlayer.stopDvr();
dvrIconTimer.cancel();
dvrIconTimer.purge();
dvrIconTimer = null;
Expand Down Expand Up @@ -484,7 +456,7 @@ protected void onStop() {
handler.removeCallbacks(runnable);
unregisterReceivers();
wfbLinkManager.stopAdapters();
stopVideoPlayer();
videoPlayer.stop();
super.onStop();
}

Expand All @@ -493,7 +465,7 @@ protected void onResume() {
registerReceivers();

// On resume is called when the app is reopened, a device might have been plugged since the last time it started.
startVideoPlayer();
videoPlayer.start();

wfbLinkManager.setChannel(getChannel(this));
wfbLinkManager.refreshAdapters();
Expand All @@ -503,31 +475,6 @@ protected void onResume() {
super.onResume();
}

protected VideoPlayer currentPlayer() {
return getCodec(this).equals("h265") ? videoPlayerH265 : videoPlayerH264;
}

public synchronized void startVideoPlayer() {
String codec = getCodec(this);
if (codec.equals("h265")) {
videoPlayerH264.stop();
videoPlayerH265.start(codec);
binding.svH264.setVisibility(View.INVISIBLE);
binding.svH265.setVisibility(View.VISIBLE);
} else {
videoPlayerH265.stop();
videoPlayerH264.start(codec);
binding.svH265.setVisibility(View.INVISIBLE);
binding.svH264.setVisibility(View.VISIBLE);
}
activeCodec = codec;
}

public synchronized void stopVideoPlayer() {
videoPlayerH264.stop();
videoPlayerH265.stop();
}

@Override
public void onChannelSettingChanged(int channel) {
int currentChannel = getChannel(this);
Expand All @@ -542,19 +489,6 @@ public void onChannelSettingChanged(int channel) {
wfbLinkManager.startAdapters(channel);
}

@Override
public void onCodecSettingChanged(String codec) {
if (codec.equals(activeCodec)) {
return;
}
SharedPreferences prefs = getSharedPreferences("general", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("codec", codec);
editor.apply();
stopVideoPlayer();
startVideoPlayer();
}

@Override
public void onVideoRatioChanged(final int videoW, final int videoH) {
lastVideoW = videoW;
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/java/com/geehe/fpvue/osd/MovableLayout.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public class MovableLayout extends LinearLayout {
private SharedPreferences preferences;
private boolean isMovable = false;
private float defaultX, defaultY;

private String prefName;

public MovableLayout(Context context) {
Expand All @@ -34,7 +33,6 @@ public MovableLayout(Context context, AttributeSet attrs, int defStyleAttr) {

private void init(Context context) {
preferences = context.getSharedPreferences("movable_layout_prefs", Context.MODE_PRIVATE);

WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
Point displaySize = new Point();
Expand All @@ -46,7 +44,9 @@ private void init(Context context) {

@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isMovable) return false;
if (!isMovable) {
return false;
}

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/geehe/fpvue/osd/OSDManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ public Boolean isOSDLocked() {
return osdLocked;
}

public String getTitle() {
return isOSDLocked() ? "Unlock OSD" : "Lock OSD";
}

public void onOSDItemCheckChanged(OSDElement element, boolean isChecked) {
// Show or hide the ImageView corresponding to the checkbox position
element.layout.setVisibility(isChecked ? View.VISIBLE : View.GONE);
Expand Down
12 changes: 1 addition & 11 deletions app/src/main/res/layout/activity_video.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,7 @@
tools:context="com.geehe.fpvue.VideoActivity">

<SurfaceView
android:id="@+id/sv_h265"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="16:9"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<SurfaceView
android:id="@+id/sv_h264"
android:id="@+id/mainVideo"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
Expand Down
4 changes: 0 additions & 4 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
<resources>
<string name="app_name">PixelPilot</string>
<string-array name="codecs">
<item>h265</item>
<item>h264</item>
</string-array>
<string-array name="channels">
<item>1</item>
<item>2</item>
Expand Down
44 changes: 10 additions & 34 deletions app/videonative/src/main/cpp/VideoPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,28 +85,9 @@ void VideoPlayer::processQueue() {
}

//Not yet parsed bit stream (e.g. raw h264 or rtp data)
void VideoPlayer::onNewVideoData(const uint8_t *data, const std::size_t data_length,
const VIDEO_DATA_TYPE videoDataType) {
void VideoPlayer::onNewVideoData(const uint8_t *data, const std::size_t data_length) {
//MLOGD << "onNewVideoData " << data_length;
switch (videoDataType) {
case VIDEO_DATA_TYPE::RTP_H264:
// MLOGD << "onNewVideoData RTP_H264 " << data_length;
mParser.parse_rtp_h264_stream(data, data_length);
break;
case VIDEO_DATA_TYPE::RAW_H264:
// mParser.parse_raw_h264_stream(data,data_length);
// mParser.parseJetsonRawSlicedH264(data,data_length);
break;
case VIDEO_DATA_TYPE::RTP_H265:
//MLOGD << "onNewVideoData RTP_H265 " << data_length;
//rtpToNalu(data,data_length);
mParser.parse_rtp_h265_stream(data, data_length);
break;
case VIDEO_DATA_TYPE::RAW_H265:
// MLOGD << "onNewVideoData RTP_H265 " << data_length;
//mParser.parse_raw_h265_stream(data,data_length);
break;
}
mParser.parse_rtp_stream(data, data_length);
}

void VideoPlayer::onNewNALU(const NALU &nalu) {
Expand All @@ -129,20 +110,15 @@ void VideoPlayer::setVideoSurface(JNIEnv *env, jobject surface) {
}


void VideoPlayer::start(JNIEnv *env, jobject androidContext, jstring codec) {
void VideoPlayer::start(JNIEnv *env, jobject androidContext) {
AAssetManager *assetManager = NDKHelper::getAssetManagerFromContext2(env, androidContext);
//mParser.setLimitFPS(-1); //Default: Real time !
const int VS_PORT = 5600;
const char *codec_ = env->GetStringUTFChars(codec, nullptr);
const int VS_PROTOCOL = strcmp(codec_, "h265") == 0 ? RTP_H265 : RTP_H264;
env->ReleaseStringUTFChars(codec, codec_);
const auto videoDataType = static_cast<VIDEO_DATA_TYPE>(VS_PROTOCOL);
mUDPReceiver.release();
mUDPReceiver = std::make_unique<UDPReceiver>(javaVm, VS_PORT, "UdpReceiver", -16,
[this, videoDataType](const uint8_t *data,
size_t data_length) {
onNewVideoData(data, data_length,
videoDataType);
[this](const uint8_t *data,
size_t data_length) {
onNewVideoData(data, data_length);
}, WANTED_UDP_RCVBUF_SIZE);
mUDPReceiver->startReceiving();
}
Expand Down Expand Up @@ -216,8 +192,8 @@ JNI_METHOD(void, nativeFinalize)
}

JNI_METHOD(void, nativeStart)
(JNIEnv *env, jclass jclass1, jlong videoPlayerN, jobject androidContext, jstring codec) {
native(videoPlayerN)->start(env, androidContext, codec);
(JNIEnv *env, jclass jclass1, jlong videoPlayerN, jobject androidContext) {
native(videoPlayerN)->start(env, androidContext);
}

JNI_METHOD(void, nativeStop)
Expand All @@ -226,7 +202,7 @@ JNI_METHOD(void, nativeStop)
}

JNI_METHOD(void, nativeSetVideoSurface)
(JNIEnv *env, jclass jclass1, jlong videoPlayerN, jobject surface, jint codec) {
(JNIEnv *env, jclass jclass1, jlong videoPlayerN, jobject surface) {
native(videoPlayerN)->setVideoSurface(env, surface);
}

Expand Down Expand Up @@ -328,4 +304,4 @@ JNIEXPORT jboolean JNICALL
Java_com_geehe_videonative_VideoPlayer_nativeIsRecording(JNIEnv *env, jclass clazz,
jlong native_instance) {
return native(native_instance)->isRecording();
}
}
9 changes: 2 additions & 7 deletions app/videonative/src/main/cpp/VideoPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,7 @@ class VideoPlayer {
public:
VideoPlayer(JNIEnv *env, jobject context);

enum VIDEO_DATA_TYPE {
RTP_H264, RAW_H264, RTP_H265, RAW_H265
};

void onNewVideoData(const uint8_t *data, const std::size_t data_length,
const VIDEO_DATA_TYPE videoDataType);
void onNewVideoData(const uint8_t *data, const std::size_t data_length);

/*
* Set the surface the decoder can be configured with. When @param surface==nullptr
Expand All @@ -37,7 +32,7 @@ class VideoPlayer {
/*
* Start the receiver and ground recorder if enabled
*/
void start(JNIEnv *env, jobject androidContext, jstring codec);
void start(JNIEnv *env, jobject androidContext);

/**
* Stop the receiver and ground recorder if enabled
Expand Down
27 changes: 8 additions & 19 deletions app/videonative/src/main/cpp/parser/H26XParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,14 @@ void H26XParser::reset() {
nParsedKonfigurationFrames = 0;
}

void H26XParser::parse_raw_h264_stream(const uint8_t *data, const size_t data_length) {
//mParseRAW.parseData(data,data_length);
}

void H26XParser::parse_raw_h265_stream(const uint8_t *data, const size_t data_length) {
//mParseRAW.parseData(data,data_length,true);
}

void H26XParser::parse_rtp_h264_stream(const uint8_t *rtp_data, const size_t data_length) {
mDecodeRTP.parseRTPH264toNALU(rtp_data, data_length);
}

void H26XParser::parse_rtp_h265_stream(const uint8_t *rtp_data, const size_t data_length) {
IS_H265 = true;
mDecodeRTP.parseRTPH265toNALU(rtp_data, data_length);
void H26XParser::parse_rtp_stream(const uint8_t *rtp_data, const size_t data_length) {
const RTP::RTPPacket rtpPacket(rtp_data, data_length);
if (rtpPacket.header.payload == RTP_PAYLOAD_TYPE_H264) {
mDecodeRTP.parseRTPH264toNALU(rtp_data, data_length);
} else if (rtpPacket.header.payload == RTP_PAYLOAD_TYPE_H265) {
IS_H265 = true;
mDecodeRTP.parseRTPH265toNALU(rtp_data, data_length);
}
}

void H26XParser::onNewNaluDataExtracted(const std::chrono::steady_clock::time_point creation_time,
Expand All @@ -53,7 +46,3 @@ void H26XParser::newNaluExtracted(const NALU &nalu) {
nParsedKonfigurationFrames++;
}
}




8 changes: 1 addition & 7 deletions app/videonative/src/main/cpp/parser/H26XParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,7 @@ class H26XParser {
public:
H26XParser(NALU_DATA_CALLBACK onNewNALU);

void parse_raw_h264_stream(const uint8_t *data, const size_t data_length);

void parse_raw_h265_stream(const uint8_t *data, const size_t data_length);

void parse_rtp_h264_stream(const uint8_t *rtp_data, const size_t data_len);

void parse_rtp_h265_stream(const uint8_t *rtp_data, const size_t data_len);
void parse_rtp_stream(const uint8_t *rtp_data, const size_t data_len);

void reset();

Expand Down
Loading

0 comments on commit 2e9ad7e

Please sign in to comment.