media: reject voice duration by complete frames before encoding
This commit is contained in:
1 parent
6f3d634c77
commit
68a7695d81
3 files changed
+15
-6
No files matched your search
@@ -133,7 +133,7 @@ static void attachment_publish(struct attachment_send_req* req, int error) {
|
||||
|
||||
static void attachment_video_done(void* arg, int error, const struct video_info* info) {
|
||||
struct attachment_send_req* req = arg;
|
||||
if (!error && info && info->is_video && info->duration_ms > 0 && info->duration_ms <= 86400000 &&
|
||||
if (!error && info && info->is_video && info->duration_ms > 0 && info->duration_ms <= ATTACHMENT_DURATION_MAX_MS &&
|
||||
info->width > 0 && info->width <= 16384 && info->height > 0 && info->height <= 16384) {
|
||||
req->info.duration_ms = (uint32_t)info->duration_ms;
|
||||
req->info.width = (uint16_t)info->width; req->info.height = (uint16_t)info->height;
|
||||
|
||||
@@ -12,8 +12,16 @@ int voice_file_encode(const int16_t* pcm, size_t count, int rate, int channels,
|
||||
static const char levels[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
if (!pcm || !info || !path || (rate != 8000 && rate != 12000 && rate != 16000 && rate != 24000 && rate != 48000) ||
|
||||
(channels != 1 && channels != 2) || preset < 0 || preset > 2) goto invalid;
|
||||
size_t frame = (size_t)(rate / 50) * channels, samples = count / frame * frame;
|
||||
if (samples < (size_t)rate * channels / 2 || samples / channels / rate > 86400) goto invalid;
|
||||
size_t frame = (size_t)(rate / 50) * channels, frames = count / frame;
|
||||
if (frames < 25 || frames > ATTACHMENT_DURATION_MAX_MS / 20) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_MEDIA,
|
||||
"voice_file: invalid duration count=%zu rate=%d channels=%d frames=%zu allowed_frames=25..%u",
|
||||
count, rate, channels, frames, ATTACHMENT_DURATION_MAX_MS / 20);
|
||||
return -1;
|
||||
}
|
||||
size_t samples = frames * frame;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_MEDIA, "voice_file: encode count=%zu rate=%d channels=%d frames=%zu duration=%ums discarded=%zu",
|
||||
count, rate, channels, frames, (uint32_t)(frames * 20), count - samples);
|
||||
opus_codec_encoder_t* encoder = opus_codec_encoder_create(rate, channels);
|
||||
if (!encoder) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "voice_file: encoder creation failed"); return -1; }
|
||||
opus_codec_encoder_bitrate_set(encoder, bitrates[preset]);
|
||||
@@ -34,7 +42,7 @@ int voice_file_encode(const int16_t* pcm, size_t count, int rate, int channels,
|
||||
}
|
||||
uint16_t end = 0;
|
||||
if (fwrite(&end, 2, 1, file) != 1 || fflush(file)) goto done;
|
||||
info->kind = ATTACHMENT_VOICE; info->duration_ms = (uint32_t)(samples / frame * 20);
|
||||
info->kind = ATTACHMENT_VOICE; info->duration_ms = (uint32_t)(frames * 20);
|
||||
info->width = info->height = 0;
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
size_t first = i * samples / 100, last = (i + 1) * samples / 100;
|
||||
@@ -57,6 +65,6 @@ done:
|
||||
} else DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "voice_file: prepared path=%s duration=%ums rate=%d channels=%d", path, info->duration_ms, rate, channels);
|
||||
return error;
|
||||
invalid:
|
||||
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "voice_file: invalid/short recording count=%zu rate=%d channels=%d preset=%d", count, rate, channels, preset);
|
||||
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "voice_file: invalid parameters count=%zu rate=%d channels=%d preset=%d", count, rate, channels, preset);
|
||||
return -1;
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
* PCM принадлежит вызывающему; encode заполняет duration/waveform по реально
|
||||
* записанным кадрам. При ошибке неполный файл удаляется; возврат 0 / -1.
|
||||
* count — число interleaved int16 отсчётов; rate — 8/12/16/24/48 kHz, channels — 1/2, preset — 0..2.
|
||||
* Пишутся полные кадры по 20мс (хвост отбрасывается), минимум 500мс, максимум 24ч.
|
||||
* Пишутся полные кадры по 20мс (хвост отбрасывается), минимум 500мс, максимум ATTACHMENT_DURATION_MAX_MS.
|
||||
* Недопустимая длительность отвергается до создания encoder, открытия path и изменения info.
|
||||
* name задаёт caller; encode устанавливает kind=VOICE и обнуляет width/height. */
|
||||
#ifndef VOICE_FILE_H
|
||||
#define VOICE_FILE_H
|
||||
|
||||
Reference in new issue
Block a user