Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: OpenIPC Telegram channels
url: https://openipc.org/our-channels
about: Questions and discussion
101 changes: 101 additions & 0 deletions .github/ISSUE_TEMPLATE/device_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: Device report
description: Report how OpenIPC Decoder works on your phone, tablet, TV, set-top box or car device
title: "[Device]: "
labels: ["device-report"]
body:
- type: markdown
attributes:
value: |
Thanks for testing! Reports are collected into the **Verified devices** table in the README.
The app version and build hash are shown in the menu next to **Exit**, for example `v1.28, a9ac8df`.

- type: dropdown
id: device_type
attributes:
label: Device type
options:
- Phone
- Tablet
- TV
- Set-top box
- Car device / mirror
- Other
validations:
required: true

- type: input
id: model
attributes:
label: Manufacturer and model
placeholder: "Samsung Galaxy A51 (SM-A515F)"
validations:
required: true

- type: input
id: android
attributes:
label: Android version / firmware
description: Android version, plus the vendor firmware if it is not stock (ColorOS, SlimBOXtv, ...)
placeholder: "Android 13 / One UI 5.1"
validations:
required: true

- type: input
id: soc
attributes:
label: SoC and kernel version
description: Settings → About → Kernel version. SoC if known (Amlogic S905X3, Allwinner H313, ...)
placeholder: "Exynos 9611, kernel 4.14.113"

- type: input
id: app_version
attributes:
label: App version
description: Shown in the menu next to Exit
placeholder: "v1.28, a9ac8df"
validations:
required: true

- type: dropdown
id: result
attributes:
label: Overall result
options:
- Works
- Works with issues
- Does not work
validations:
required: true

- type: checkboxes
id: works
attributes:
label: What works
options:
- label: H.264 video
- label: H.265 video
- label: Audio
- label: Quad mode
- label: Remote control / D-pad
- label: WebUI
- label: Screenshot (long press)

- type: textarea
id: stream
attributes:
label: Camera and stream
description: Camera firmware (OpenIPC or other), resolution, FPS, bitrate, audio codec
placeholder: "OpenIPC on gk7205v300, H.265 1920x1080@25, 2 Mbps, AAC 16 kHz"

- type: textarea
id: notes
attributes:
label: Problems and notes
description: What did not work or looked wrong (cropped picture, no sound, delay, crash, ...)

- type: textarea
id: logs
attributes:
label: Log (optional)
description: "With USB/network debugging enabled: `adb logcat -d -s OpenIPCDecoder`"
render: text
253 changes: 162 additions & 91 deletions README.md

Large diffs are not rendered by default.

218 changes: 218 additions & 0 deletions README.ru.md

Large diffs are not rendered by default.

218 changes: 218 additions & 0 deletions README.zh-CN.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) OpenIPC https://openipc.org MIT License
* Copyright (c) OpenIPC https://openipc.org Prosperity Public License 3.0.0
*
* build.gradle — Android application module build configuration
*
Expand Down
2 changes: 1 addition & 1 deletion android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) OpenIPC https://openipc.org MIT License
# Copyright (c) OpenIPC https://openipc.org Prosperity Public License 3.0.0
#
# proguard-rules.pro — R8/ProGuard keep rules for the Decoder application
#
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/java/com/openipc/decoder/App.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) OpenIPC https://openipc.org MIT License
* Copyright (c) OpenIPC https://openipc.org Prosperity Public License 3.0.0
*
* App.java — Application subclass for global uncaught exception handling
*
Expand Down
118 changes: 118 additions & 0 deletions android/app/src/main/java/com/openipc/decoder/AudioConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright (c) OpenIPC https://openipc.org Prosperity Public License 3.0.0
*
* AudioConfig.java — audio track parameters parsed from the SDP
*
*/

package com.openipc.decoder;

class AudioConfig {
static final String NONE = "NONE"; // no audio track or unsupported codec
static final String PCM = "PCM"; // L16
static final String PCMU = "PCMU"; // G.711 mu-law
static final String PCMA = "PCMA"; // G.711 A-law
static final String AAC = "AAC";

String codec = NONE;
int pt = -1;
int sampleRate = 8000;
int channels = 1;
boolean bigEndian;

// AAC: AudioSpecificConfig from fmtp "config=", null when absent
byte[] aacConfig;
// AAC RFC 3640 (mpeg4-generic) AU-header layout; sizeLength == 0 means no AU headers
int sizeLength;
int indexLength;
int indexDeltaLength;

/** Fill defaults for static RTP payload types (RFC 3551), which may come without rtpmap. */
void applyStaticPayloadType() {
switch (pt) {
case 0: codec = PCMU; sampleRate = 8000; channels = 1; break;
case 8: codec = PCMA; sampleRate = 8000; channels = 1; break;
case 10: codec = PCM; sampleRate = 44100; channels = 2; bigEndian = true; break;
case 11: codec = PCM; sampleRate = 44100; channels = 1; bigEndian = true; break;
default: break;
}
}

/** Apply "a=rtpmap:<pt> <name>/<rate>[/<channels>]". */
void applyRtpmap(String encoding) {
String[] parts = encoding.trim().split("/");
String name = parts[0].toUpperCase(java.util.Locale.ROOT);

bigEndian = false;
if (name.equals("MPEG4-GENERIC") || name.equals("AAC") || name.equals("MP4A")) {
codec = AAC;
} else if (name.equals("PCMU")) {
codec = PCMU;
} else if (name.equals("PCMA")) {
codec = PCMA;
} else if (name.equals("L16")) {
codec = PCM;
bigEndian = true;
} else {
// MP4A-LATM, OPUS, G726, ... are not supported
codec = NONE;
}

if (parts.length > 1) {
try {
int rate = Integer.parseInt(parts[1].trim());
if (rate > 0 && rate <= 192000) sampleRate = rate;
} catch (NumberFormatException ignored) {}
}
channels = 1;
if (parts.length > 2) {
try {
int ch = Integer.parseInt(parts[2].trim());
if (ch == 1 || ch == 2) channels = ch;
} catch (NumberFormatException ignored) {}
}
}

/** Apply "a=fmtp:<pt> key=value; key=value". */
void applyFmtp(String params) {
for (String param : params.split(";")) {
int eq = param.indexOf('=');
if (eq <= 0) continue;
String key = param.substring(0, eq).trim().toLowerCase(java.util.Locale.ROOT);
String value = param.substring(eq + 1).trim();
try {
switch (key) {
case "config": aacConfig = parseHex(value); break;
case "sizelength": sizeLength = Integer.parseInt(value); break;
case "indexlength": indexLength = Integer.parseInt(value); break;
case "indexdeltalength": indexDeltaLength = Integer.parseInt(value); break;
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
Resolved
default: break;
}
} catch (NumberFormatException ignored) {}
}
}

/**
* Validate after all SDP attributes are applied (rtpmap and fmtp may come in any order).
* AAC with an impossible AU-header layout is disabled rather than misparsed.
*/
void finish() {
if (AAC.equals(codec) && (sizeLength < 0 || sizeLength > 16
|| indexLength < 0 || indexLength > 16
|| indexDeltaLength < 0 || indexDeltaLength > 16)) {
codec = NONE;
}
}

private static byte[] parseHex(String hex) {
if (hex.isEmpty() || hex.length() % 2 != 0) return null;
byte[] out = new byte[hex.length() / 2];
for (int i = 0; i < out.length; i++) {
int hi = Character.digit(hex.charAt(2 * i), 16);
int lo = Character.digit(hex.charAt(2 * i + 1), 16);
if (hi < 0 || lo < 0) return null;
out[i] = (byte) ((hi << 4) | lo);
}
return out;
}
}
Loading
Loading