docs(media): specify attachment metadata and voice file contracts
This commit is contained in:
1 parent
c1717d4047
commit
28bbd62d74
3 files changed
+21
-10
No files matched your search
@@ -4,7 +4,7 @@
|
||||
#include "../../lib/debug_config.h"
|
||||
#include "attachment.h"
|
||||
|
||||
/* Имя должно быть корректным UTF-8 basename без управляющих символов. */
|
||||
/* Корректный UTF-8 basename без ASCII C0/DEL и разделителей пути. */
|
||||
static int valid_name(const char* name, size_t n) {
|
||||
if (!n || n > 255 || (n == 1 && name[0] == '.') || (n == 2 && !memcmp(name, "..", 2))) return 0;
|
||||
for (size_t i = 0; i < n;) {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/* attachment — общие метаданные file/voice/video, без хранения файла, адресата и транспорта.
|
||||
* validate/decode возвращают 0 / -1, encode — число записанных байтов / -1.
|
||||
* Формат: kind:1, name_len:2, duration_ms:4, width:2, height:2, UTF-8 basename, waveform:100 только для voice.
|
||||
* Числа big-endian; имя 1..255 байт без разделителей пути, лишние wire-байты запрещены.
|
||||
* Caller владеет struct/буферами; DM шифрует эти метаданные, GUI получает разобранные поля. */
|
||||
* Числа big-endian; имя — корректный UTF-8 basename длиной 1..255 байт, без '/'/'\\', ASCII C0/DEL и '.'/'..'.
|
||||
* Лишние wire-байты и NUL внутри переданного имени запрещены. Caller владеет struct/буферами;
|
||||
* вход и выход не пересекаются. DM шифрует эти метаданные, GUI получает разобранные поля. */
|
||||
#ifndef ATTACHMENT_H
|
||||
#define ATTACHMENT_H
|
||||
#include <stdint.h>
|
||||
@@ -16,15 +17,21 @@ enum attachment_kind { ATTACHMENT_FILE = 1, ATTACHMENT_VOICE, ATTACHMENT_VIDEO }
|
||||
#define ATTACHMENT_WIRE_MAX (11 + 255 + ATTACHMENT_WAVE_SIZE)
|
||||
#define ATTACHMENT_DURATION_MAX_MS 86400000u /* Общий максимум длительности voice/video: 24ч. */
|
||||
struct attachment_info {
|
||||
enum attachment_kind kind;
|
||||
char name[256];
|
||||
uint32_t duration_ms;
|
||||
uint16_t width, height;
|
||||
enum attachment_kind kind; /* Только FILE/VOICE/VIDEO. */
|
||||
char name[256]; /* UTF-8 basename с завершающим NUL. */
|
||||
uint32_t duration_ms; /* VOICE/VIDEO: 1..ATTACHMENT_DURATION_MAX_MS; FILE: 0. */
|
||||
uint16_t width, height; /* VIDEO: 1..16384; FILE/VOICE: 0. */
|
||||
char waveform[ATTACHMENT_WAVE_SIZE + 1]; /* 100 уровней из A-Za-z0-9+/; только voice. */
|
||||
};
|
||||
/* Проверить все поля и их согласованность с kind; info не меняется, NULL даёт -1. */
|
||||
int attachment_validate(const struct attachment_info* info);
|
||||
/* Записать полные проверенные метаданные в out ёмкостью capacity; ошибка не меняет out.
|
||||
* Вернуть точную длину wire или -1. out обязателен, ATTACHMENT_WIRE_MAX достаточно для любого kind. */
|
||||
int attachment_encode(const struct attachment_info* info, uint8_t* out, size_t capacity);
|
||||
/* Разобрать ровно length байт и проверить метаданные; data/info обязательны. 0/-1.
|
||||
* При ошибке info может быть изменена: результат используется только при возврате 0. */
|
||||
int attachment_decode(const uint8_t* data, size_t length, struct attachment_info* info);
|
||||
/* Заимствованная постоянная строка: VOICE=audio/opus, VIDEO=video/mp4, иначе application/octet-stream. Не валидатор kind. */
|
||||
const char* attachment_content_type(enum attachment_kind kind);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
/* voice_file — кодирование PCM в общий контейнер Opus голосовых сообщений Qt/Android. Вызывать только в worker.
|
||||
* PCM принадлежит вызывающему; encode заполняет duration/waveform по реально
|
||||
* записанным кадрам. При ошибке неполный файл удаляется; возврат 0 / -1.
|
||||
* PCM принадлежит вызывающему; encode заполняет duration/waveform по реально записанным кадрам. Возврат 0 / -1.
|
||||
* path — собственный файл вызывающего: fopen(wb) перезаписывает прежнее содержимое;
|
||||
* после ошибки записи/close файл удаляется (отказ удаления логируется). fsync/атомарной публикации здесь нет.
|
||||
* count — число interleaved int16 отсчётов; rate — 8/12/16/24/48 kHz, channels — 1/2, preset — 0..2.
|
||||
* Пишутся полные кадры по 20мс (хвост отбрасывается), минимум 500мс, максимум ATTACHMENT_DURATION_MAX_MS.
|
||||
* Недопустимая длительность отвергается до создания encoder, открытия path и изменения info.
|
||||
* name задаёт caller; encode устанавливает kind=VOICE и обнуляет width/height. */
|
||||
* name задаёт caller; encode устанавливает kind=VOICE и обнуляет width/height.
|
||||
* info используется только при rc=0: при поздней ошибке close часть полей уже может быть изменена.
|
||||
* Формат native-endian: magic:uint32=0x5355504f, rate:uint32, channels:uint16, samples_per_channel:uint16;
|
||||
* затем (packet_len:uint16, Opus bytes) для каждого кадра и нулевая длина в конце. */
|
||||
#ifndef VOICE_FILE_H
|
||||
#define VOICE_FILE_H
|
||||
#include "attachment.h"
|
||||
|
||||
Reference in new issue
Block a user