59 lines
3.6 KiB
C
59 lines
3.6 KiB
C
/* Строгие метаданные и реальный Opus-файл: границы, повреждения, длительность. */
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "../lib/mem.h"
|
|
#include "../lib/debug_config.h"
|
|
#include "../lib/opus_codec.h"
|
|
#include "../src/media_async/attachment.h"
|
|
#include "../src/media_async/voice_file.h"
|
|
#define REQUIRE(value) do { if (!(value)) { fprintf(stderr, "attachment check failed line=%d\n", __LINE__); return 1; } } while (0)
|
|
|
|
int main(void) {
|
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
|
|
struct attachment_info in = { .kind = ATTACHMENT_VOICE, .name = "голос.opus", .duration_ms = 1200 }, out;
|
|
memset(in.waveform, 'A', 100);
|
|
uint8_t wire[ATTACHMENT_WIRE_MAX + 1];
|
|
int length = attachment_encode(&in, wire, sizeof(wire));
|
|
REQUIRE(length > 0 && !attachment_decode(wire, length, &out));
|
|
REQUIRE(out.kind == in.kind && out.duration_ms == 1200 && !strcmp(in.name, out.name) && !strcmp(in.waveform, out.waveform));
|
|
for (int i = 0; i < length; i++) REQUIRE(attachment_decode(wire, i, &out) < 0);
|
|
REQUIRE(attachment_decode(wire, length + 1, &out) < 0);
|
|
wire[0] = 99; REQUIRE(attachment_decode(wire, length, &out) < 0);
|
|
wire[0] = ATTACHMENT_VOICE; wire[length - 1] = '?'; REQUIRE(attachment_decode(wire, length, &out) < 0);
|
|
in.kind = ATTACHMENT_VIDEO; in.waveform[0] = 0; in.width = 640; in.height = 480;
|
|
length = attachment_encode(&in, wire, sizeof(wire)); REQUIRE(length > 0 && !attachment_decode(wire, length, &out));
|
|
REQUIRE(out.width == 640 && out.height == 480);
|
|
in.width = 0; REQUIRE(attachment_validate(&in) < 0);
|
|
in = (struct attachment_info){ .kind = ATTACHMENT_FILE, .name = "../unsafe" }; REQUIRE(attachment_validate(&in) < 0);
|
|
strcpy(in.name, "\xc0\xaf"); REQUIRE(attachment_validate(&in) < 0);
|
|
memset(in.name, 'n', 255); in.name[255] = 0;
|
|
REQUIRE(attachment_encode(&in, wire, 265) < 0); REQUIRE(attachment_encode(&in, wire, 266) == 266);
|
|
int16_t* pcm = u_calloc(48001, sizeof(*pcm)); REQUIRE(pcm != NULL);
|
|
for (unsigned i = 0; i < 48001; i++) pcm[i] = (int16_t)((i % 200) * 100 - 10000);
|
|
in = (struct attachment_info){ .name = "voice.opus" };
|
|
const char* path = "test_attachment_voice.opus";
|
|
REQUIRE(!voice_file_encode(pcm, 48001, 48000, 1, 1, path, &in));
|
|
REQUIRE(in.duration_ms == 1000 && strlen(in.waveform) == 100 && !attachment_validate(&in));
|
|
FILE* file = fopen(path, "rb"); REQUIRE(file != NULL);
|
|
uint8_t header[12]; REQUIRE(fread(header, 1, 12, file) == 12);
|
|
uint32_t magic, rate; uint16_t channels, frame;
|
|
memcpy(&magic, header, 4); memcpy(&rate, header + 4, 4); memcpy(&channels, header + 8, 2); memcpy(&frame, header + 10, 2);
|
|
REQUIRE(magic == 0x5355504f && rate == 48000 && channels == 1 && frame == 960);
|
|
opus_codec_decoder_t* decoder = opus_codec_decoder_create(48000, 1); REQUIRE(decoder != NULL);
|
|
uint8_t packet[4000]; int16_t decoded[960]; unsigned frames = 0;
|
|
for (;;) {
|
|
uint16_t n; REQUIRE(fread(&n, 2, 1, file) == 1);
|
|
if (!n) break;
|
|
REQUIRE(n <= sizeof(packet) && fread(packet, 1, n, file) == n);
|
|
REQUIRE(opus_codec_decode(decoder, packet, n, decoded, 960) == 960); frames++;
|
|
}
|
|
REQUIRE(frames == 50 && fgetc(file) == EOF);
|
|
fclose(file); remove(path); opus_codec_decoder_destroy(decoder);
|
|
REQUIRE(voice_file_encode(pcm, 23999, 48000, 1, 1, path, &in) < 0);
|
|
REQUIRE(voice_file_encode(pcm, 48000, 48000, 1, 3, path, &in) < 0);
|
|
REQUIRE(voice_file_encode(pcm, 48000, 44100, 1, 1, path, &in) < 0);
|
|
u_free(pcm);
|
|
printf("test_attachment: strict metadata and shared Opus encode/decode PASS\n");
|
|
return 0;
|
|
}
|