62 lines
4.1 KiB
C
62 lines
4.1 KiB
C
/* Индекс медиапотока поверх общего RS-кольца: хранит только позиции/PTS, без копии кодированного потока.
|
|
* Один uasync-поток; store принадлежит stream-session, cursor — конкретному локальному reader.
|
|
* feed получает уже проверенные последовательные пачки; gap обозначает окончательно потерянный диапазон.
|
|
* Независимые audio/video позиции читают оригинал из кольца. Рабочая память cursor — один видеокадр,
|
|
* один Opus-пакет и два scratch медиаблока. Курсоры ничего не закрепляют против вытеснения.
|
|
* read возвращает заимствованный packet до следующего read/destroy; frontend копирует только ближайшие записи.
|
|
* Каждый cursor допускает новую video revision только с полным KEY; готовый KEY выдаётся без дополнительного ожидания.
|
|
* Смена video revision не сбрасывает аудио и не запрещает другим readers дочитать прежнюю revision.
|
|
* WAIT — материал ещё не готов/дальше audio lookahead. GAP/EXPIRED требуют новой точки KEY; END — весь материал выдан. */
|
|
#ifndef STREAM_MEDIA_BUFFER_H
|
|
#define STREAM_MEDIA_BUFFER_H
|
|
|
|
#include "stream_buffer.h"
|
|
#include "stream_media.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define STREAM_MEDIA_INDEX_BYTES (4u * 1024u * 1024u)
|
|
#define STREAM_MEDIA_READ_AHEAD_US 80000
|
|
#define STREAM_MEDIA_PREROLL_US 500000
|
|
#define STREAM_MEDIA_TRACK_VIDEO 1
|
|
#define STREAM_MEDIA_TRACK_AUDIO 2
|
|
|
|
struct stream_media_store;
|
|
struct stream_media_cursor;
|
|
enum stream_media_read_kind { STREAM_MEDIA_READ_VIDEO, STREAM_MEDIA_READ_AUDIO, STREAM_MEDIA_READ_END };
|
|
struct stream_media_packet {
|
|
enum stream_media_read_kind kind;
|
|
struct stream_media_format format;
|
|
struct stream_media_video video;
|
|
struct stream_media_audio audio;
|
|
};
|
|
struct stream_media_status {
|
|
int64_t ready_us, video_us, audio_us, start_us;
|
|
uint64_t generation;
|
|
int initialized, audio_enabled, finished, video_ended, audio_ended;
|
|
};
|
|
|
|
int stream_media_store_create(struct stream_media_store **out, struct stream_buffer *buffer, const struct stream_descriptor *descriptor);
|
|
void stream_media_store_destroy(struct stream_media_store *store);
|
|
int stream_media_store_feed(struct stream_media_store *store, uint64_t seq, const uint8_t *data, size_t length);
|
|
void stream_media_store_gap(struct stream_media_store *store, uint64_t first, uint64_t last);
|
|
void stream_media_store_finish(struct stream_media_store *store);
|
|
void stream_media_store_trim(struct stream_media_store *store);
|
|
int stream_media_cursor_create(struct stream_media_cursor **out, struct stream_media_store *store, unsigned tracks);
|
|
void stream_media_cursor_destroy(struct stream_media_cursor *cursor);
|
|
void stream_media_cursor_reset(struct stream_media_cursor *cursor);
|
|
int stream_media_cursor_status(struct stream_media_cursor *cursor, struct stream_media_status *status);
|
|
/* want_video=1 запрашивает следующий кадр независимо от часов показа; 0 оставляет видео в кольце.
|
|
* position_us<0 прогревает аудио перед KEY; затем звук выдаётся до position_us+audio_ahead_us, -1 отключает звук.
|
|
* При GAP/EXPIRED cursor сбрасывают отдельно: это позволяет frontend сначала обработать разрыв.
|
|
* Бюджет одного вызова ограничен; MORE требует отложенного продолжения, WAIT — новых данных/позиции. */
|
|
int stream_media_cursor_read(struct stream_media_cursor *cursor, int64_t position_us, int want_video, int64_t audio_ahead_us,
|
|
struct stream_media_packet *packet);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif
|