Skip to content

Commit

Permalink
feat: extract correct media from rtp stream
Browse files Browse the repository at this point in the history
  • Loading branch information
towi committed Nov 14, 2024
1 parent 8a19f09 commit 6717b68
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.sipgate.li.simulator.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

class LiMediaExtractor {

private static final int HEADER_SIZE = 12;
private static final Map<Integer, String> PAYLOAD_TYPE_MAP = new HashMap<>();

static {
PAYLOAD_TYPE_MAP.put(0, "PCMU");
PAYLOAD_TYPE_MAP.put(3, "GSM");
PAYLOAD_TYPE_MAP.put(4, "G723");
PAYLOAD_TYPE_MAP.put(5, "DVI4");
PAYLOAD_TYPE_MAP.put(6, "DVI4");
PAYLOAD_TYPE_MAP.put(7, "LPC");
PAYLOAD_TYPE_MAP.put(8, "PCMA");
PAYLOAD_TYPE_MAP.put(9, "G.722");
PAYLOAD_TYPE_MAP.put(10, "L16");
PAYLOAD_TYPE_MAP.put(11, "L16");
PAYLOAD_TYPE_MAP.put(12, "QCELP");
PAYLOAD_TYPE_MAP.put(13, "CN");
PAYLOAD_TYPE_MAP.put(14, "MPA");
PAYLOAD_TYPE_MAP.put(15, "G.728");
PAYLOAD_TYPE_MAP.put(16, "DVI4");
PAYLOAD_TYPE_MAP.put(17, "DVI4");
PAYLOAD_TYPE_MAP.put(18, "G.729");
PAYLOAD_TYPE_MAP.put(25, "CelB");
PAYLOAD_TYPE_MAP.put(26, "JPEG");
PAYLOAD_TYPE_MAP.put(28, "nv");
PAYLOAD_TYPE_MAP.put(31, "H.261");
PAYLOAD_TYPE_MAP.put(32, "MPV");
PAYLOAD_TYPE_MAP.put(33, "MP2T");
PAYLOAD_TYPE_MAP.put(34, "H.263");
}

private final Set<String> payloadTypeNames = new HashSet<>();

public Set<String> getPayloadTypeNames() {
return payloadTypeNames;
}

void extractMediaFromRtp(final OutputStream output, final byte[] bytes) {
try {
final var payloadTypeCode = bytes[1] & 0x7F;
payloadTypeNames.add(PAYLOAD_TYPE_MAP.get(payloadTypeCode));
final var buf = new byte[bytes.length - HEADER_SIZE];
System.arraycopy(bytes, HEADER_SIZE, buf, 0, bytes.length - HEADER_SIZE);
output.write(buf);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import com.sipgate.li.lib.x2x3.protocol.PduObject;
import com.sipgate.li.lib.x2x3.protocol.PduType;
import com.sipgate.li.simulator.x2x3.X2X3Memory;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
Expand All @@ -16,7 +14,6 @@
import java.util.List;
import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
Expand All @@ -27,6 +24,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

@RestController
@RequestMapping("/x2x3")
Expand Down Expand Up @@ -104,8 +102,9 @@ public ResponseEntity<List<String>> getAllX3() throws IOException {

// ================================

@GetMapping(value = "/all/rtp/{xid}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public @ResponseBody byte[] getAllRtp(@PathVariable final UUID xid) throws IOException {
@GetMapping(value = "/all/rtp/{xid}")
public ResponseEntity<byte[]> getAllRtp(@PathVariable final UUID xid) throws IOException {
final var liMediaExtractor = new LiMediaExtractor();
try (final var buf = new ByteArrayOutputStream()) {
x2X3Memory
.getStorage()
Expand All @@ -114,17 +113,30 @@ public ResponseEntity<List<String>> getAllX3() throws IOException {
.filter(pdu -> pdu.xid().equals(xid))
.sorted(Comparator.comparingInt(pdu -> pdu.findSequenceNumber().orElse(-1)))
.map(PduObject::payload)
.forEach(payload -> writeToBuf(payload, buf));
return buf.toByteArray();
.forEach(payload -> liMediaExtractor.extractMediaFromRtp(buf, payload));
LOGGER.info("Extracted types: {}", liMediaExtractor.getPayloadTypeNames());
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM) // TODO: set the content type from getPayloadTypeNames()?
.body(buf.toByteArray());
}
}

private static void writeToBuf(final byte[] payload, final ByteArrayOutputStream buf) {
try {
buf.write(payload);
} catch (final IOException e) {
throw new RuntimeException(e);
}
@GetMapping(value = "/all/stream/{xid}")
public ResponseEntity<StreamingResponseBody> getAllStream(@PathVariable final UUID xid) {
final var liMediaExtractor = new LiMediaExtractor();
// might not work yet like streaming, but it's a start
// - sorting is skipped here, of course.
final StreamingResponseBody responseBody = buf ->
x2X3Memory
.getStorage()
.stream()
.filter(pdu -> PduType.X3_PDU.equals(pdu.pduType()))
.filter(pdu -> pdu.xid().equals(xid))
.map(PduObject::payload)
.forEach(payload -> liMediaExtractor.extractMediaFromRtp(buf, payload));
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM) // TODO: set the content type from getPayloadTypeNames()?
.body(responseBody);
}

// ================================
Expand Down

0 comments on commit 6717b68

Please sign in to comment.