Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add mediajson (json definitions). #205

Merged
merged 5 commits into from
Oct 10, 2024
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
142 changes: 142 additions & 0 deletions jicoco-mediajson/pom.xml
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 jicoco-mediajson/src/main/kotlin/org/jitsi/mediajson/MediaJson.kt
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()
}
}
Loading
Loading