All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jitsi.mediajson.MediaJson.kt Maven / Gradle / Ivy

The newest version!
/*
 * 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): List = 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() {
    override fun serialize(value: Int, gen: JsonGenerator, p: SerializerProvider) {
        gen.writeString(value.toString())
    }
}
class String2IntDeserializer : JsonDeserializer() {
    override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Int {
        return p.readValueAs(Int::class.java).toInt()
    }
}
class Long2StringSerializer : JsonSerializer() {
    override fun serialize(value: Long, gen: JsonGenerator, p: SerializerProvider) {
        gen.writeString(value.toString())
    }
}
class String2LongDeserializer : JsonDeserializer() {
    override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Long {
        return p.readValueAs(Long::class.java).toLong()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy