-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add mediajson (json definitions). (#205)
* feat: Add mediajson (json definitions). * feat: Expose seq/chunk/timestamp as numbers in the API. * ref: Move inte a jicoco-mediajson package. * ref: Move the prometheus jetty servlet into its own package.
- Loading branch information
Showing
9 changed files
with
730 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
~ Copyright @ 2022 - present 8x8, Inc. | ||
~ | ||
~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
~ you may not use this file except in compliance with the License. | ||
~ You may obtain a copy of the License at | ||
~ | ||
~ http://www.apache.org/licenses/LICENSE-2.0 | ||
~ | ||
~ Unless required by applicable law or agreed to in writing, software | ||
~ distributed under the License is distributed on an "AS IS" BASIS, | ||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
~ See the License for the specific language governing permissions and | ||
~ limitations under the License. | ||
--> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>org.jitsi</groupId> | ||
<artifactId>jicoco-parent</artifactId> | ||
<version>1.1-SNAPSHOT</version> | ||
</parent> | ||
<artifactId>jicoco-mediajson</artifactId> | ||
<version>1.1-SNAPSHOT</version> | ||
<name>jicoco-mediajson</name> | ||
<description>Jitsi Common Components (Media JSON)</description> | ||
<dependencies> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.module</groupId> | ||
<artifactId>jackson-module-kotlin</artifactId> | ||
<version>${jackson.version}</version> | ||
</dependency> | ||
<!-- testing --> | ||
<dependency> | ||
<groupId>io.kotest</groupId> | ||
<artifactId>kotest-runner-junit5-jvm</artifactId> | ||
<version>${kotest.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.kotest</groupId> | ||
<artifactId>kotest-assertions-core-jvm</artifactId> | ||
<version>${kotest.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.googlecode.json-simple</groupId> | ||
<artifactId>json-simple</artifactId> | ||
<version>${json.simple.version}</version> | ||
<!-- json-simple 1.1.1 incorrectly listed junit as a compile dependency rather than a test dependency. | ||
This has been fixed in its github repo but a new release hasn't been pushed to maven. --> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
</dependencies> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.jetbrains.kotlin</groupId> | ||
<artifactId>kotlin-maven-plugin</artifactId> | ||
<version>${kotlin.version}</version> | ||
<executions> | ||
<execution> | ||
<id>compile</id> | ||
<phase>compile</phase> | ||
<goals> | ||
<goal>compile</goal> | ||
</goals> | ||
<configuration> | ||
<args> | ||
<arg>-opt-in=kotlin.ExperimentalStdlibApi</arg> | ||
</args> | ||
<sourceDirs> | ||
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir> | ||
</sourceDirs> | ||
</configuration> | ||
</execution> | ||
<execution> | ||
<id>test-compile</id> | ||
<phase>test-compile</phase> | ||
<goals> | ||
<goal>test-compile</goal> | ||
</goals> | ||
<configuration> | ||
<args> | ||
<arg>-opt-in=kotlin.ExperimentalStdlibApi</arg> | ||
</args> | ||
<sourceDirs> | ||
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir> | ||
</sourceDirs> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
<configuration> | ||
<jvmTarget>11</jvmTarget> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>3.10.1</version> | ||
<executions> | ||
<!-- Replacing default-compile as it is treated specially by maven --> | ||
<execution> | ||
<id>default-compile</id> | ||
<phase>none</phase> | ||
</execution> | ||
<!-- Replacing default-testCompile as it is treated specially by maven --> | ||
<execution> | ||
<id>default-testCompile</id> | ||
<phase>none</phase> | ||
</execution> | ||
<execution> | ||
<id>java-compile</id> | ||
<phase>compile</phase> | ||
<goals> | ||
<goal>compile</goal> | ||
</goals> | ||
</execution> | ||
<execution> | ||
<id>java-test-compile</id> | ||
<phase>test-compile</phase> | ||
<goals> | ||
<goal>testCompile</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
<configuration> | ||
<release>11</release> | ||
<compilerArgs> | ||
<arg>-Xlint:all</arg> | ||
</compilerArgs> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
106 changes: 106 additions & 0 deletions
106
jicoco-mediajson/src/main/kotlin/org/jitsi/mediajson/MediaJson.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* Copyright @ 2024 - present 8x8, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.jitsi.mediajson | ||
|
||
import com.fasterxml.jackson.annotation.JsonSubTypes | ||
import com.fasterxml.jackson.annotation.JsonTypeInfo | ||
import com.fasterxml.jackson.core.JsonGenerator | ||
import com.fasterxml.jackson.core.JsonParser | ||
import com.fasterxml.jackson.databind.DeserializationContext | ||
import com.fasterxml.jackson.databind.DeserializationFeature | ||
import com.fasterxml.jackson.databind.JsonDeserializer | ||
import com.fasterxml.jackson.databind.JsonSerializer | ||
import com.fasterxml.jackson.databind.SerializerProvider | ||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize | ||
import com.fasterxml.jackson.databind.annotation.JsonSerialize | ||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper | ||
|
||
private val objectMapper = jacksonObjectMapper().apply { | ||
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) | ||
} | ||
|
||
/** | ||
* This is based on the format used by VoxImplant here, hence the encoding of certain numeric fields as strings: | ||
* https://voximplant.com/docs/guides/voxengine/websocket | ||
*/ | ||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "event") | ||
@JsonSubTypes( | ||
JsonSubTypes.Type(value = MediaEvent::class, name = "media"), | ||
JsonSubTypes.Type(value = StartEvent::class, name = "start"), | ||
) | ||
sealed class Event(val event: String) { | ||
fun toJson(): String = objectMapper.writeValueAsString(this) | ||
companion object { | ||
fun parse(s: String): Event = objectMapper.readValue(s, Event::class.java) | ||
fun parse(s: List<String>): List<Event> = s.map { objectMapper.readValue(it, Event::class.java) } | ||
} | ||
} | ||
|
||
data class MediaEvent( | ||
@JsonSerialize(using = Int2StringSerializer::class) | ||
@JsonDeserialize(using = String2IntDeserializer::class) | ||
val sequenceNumber: Int, | ||
val media: Media | ||
) : Event("media") | ||
|
||
data class StartEvent( | ||
@JsonSerialize(using = Int2StringSerializer::class) | ||
@JsonDeserialize(using = String2IntDeserializer::class) | ||
val sequenceNumber: Int, | ||
val start: Start | ||
) : Event("start") | ||
|
||
data class MediaFormat( | ||
val encoding: String, | ||
val sampleRate: Int, | ||
val channels: Int | ||
) | ||
data class Start( | ||
val tag: String, | ||
val mediaFormat: MediaFormat | ||
) | ||
|
||
data class Media( | ||
val tag: String, | ||
@JsonSerialize(using = Int2StringSerializer::class) | ||
@JsonDeserialize(using = String2IntDeserializer::class) | ||
val chunk: Int, | ||
@JsonSerialize(using = Long2StringSerializer::class) | ||
@JsonDeserialize(using = String2LongDeserializer::class) | ||
val timestamp: Long, | ||
val payload: String | ||
) | ||
|
||
class Int2StringSerializer : JsonSerializer<Int>() { | ||
override fun serialize(value: Int, gen: JsonGenerator, p: SerializerProvider) { | ||
gen.writeString(value.toString()) | ||
} | ||
} | ||
class String2IntDeserializer : JsonDeserializer<Int>() { | ||
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Int { | ||
return p.readValueAs(Int::class.java).toInt() | ||
} | ||
} | ||
class Long2StringSerializer : JsonSerializer<Long>() { | ||
override fun serialize(value: Long, gen: JsonGenerator, p: SerializerProvider) { | ||
gen.writeString(value.toString()) | ||
} | ||
} | ||
class String2LongDeserializer : JsonDeserializer<Long>() { | ||
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Long { | ||
return p.readValueAs(Long::class.java).toLong() | ||
} | ||
} |
Oops, something went wrong.