Frame rendering optimizations
This commit is contained in:
parent
126469df76
commit
f64429b7b4
11 changed files with 268 additions and 44 deletions
4
Makefile
4
Makefile
|
|
@ -1,6 +1,7 @@
|
||||||
CC ?= cc
|
CC ?= cc
|
||||||
CSTD ?= -std=c11
|
CSTD ?= -std=c11
|
||||||
CFLAGS ?= -O2 -Wall -Wextra -Wpedantic $(CSTD)
|
CFLAGS ?= -O2 -Wall -Wextra -Wpedantic $(CSTD)
|
||||||
|
CFLAGS += -MMD -MP
|
||||||
|
|
||||||
SDL_CFLAGS := $(shell pkg-config --cflags SDL2 SDL2_ttf SDL2_image 2>/dev/null)
|
SDL_CFLAGS := $(shell pkg-config --cflags SDL2 SDL2_ttf SDL2_image 2>/dev/null)
|
||||||
SDL_LIBS := $(shell pkg-config --libs SDL2 SDL2_ttf SDL2_image 2>/dev/null)
|
SDL_LIBS := $(shell pkg-config --libs SDL2 SDL2_ttf SDL2_image 2>/dev/null)
|
||||||
|
|
@ -19,6 +20,7 @@ endif
|
||||||
|
|
||||||
SRC := $(wildcard src/*.c)
|
SRC := $(wildcard src/*.c)
|
||||||
OBJ := $(SRC:.c=.o)
|
OBJ := $(SRC:.c=.o)
|
||||||
|
DEP := $(OBJ:.o=.d)
|
||||||
BIN := passport-c-media-player
|
BIN := passport-c-media-player
|
||||||
|
|
||||||
CPPFLAGS += -I./src $(SDL_CFLAGS) $(FFMPEG_CFLAGS)
|
CPPFLAGS += -I./src $(SDL_CFLAGS) $(FFMPEG_CFLAGS)
|
||||||
|
|
@ -31,6 +33,8 @@ all: $(BIN)
|
||||||
$(BIN): $(OBJ)
|
$(BIN): $(OBJ)
|
||||||
$(CC) $(OBJ) -o $@ $(LDLIBS)
|
$(CC) $(OBJ) -o $@ $(LDLIBS)
|
||||||
|
|
||||||
|
-include $(DEP)
|
||||||
|
|
||||||
run: $(BIN)
|
run: $(BIN)
|
||||||
./$(BIN)
|
./$(BIN)
|
||||||
|
|
||||||
|
|
|
||||||
8
src/app.d
Normal file
8
src/app.d
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
src/app.o: src/app.c src/app.h src/channel.h src/player.h \
|
||||||
|
src/frame_queue.h src/theme.h src/ui.h
|
||||||
|
src/app.h:
|
||||||
|
src/channel.h:
|
||||||
|
src/player.h:
|
||||||
|
src/frame_queue.h:
|
||||||
|
src/theme.h:
|
||||||
|
src/ui.h:
|
||||||
8
src/channel.d
Normal file
8
src/channel.d
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
src/channel.o: src/channel.c src/channel.h \
|
||||||
|
/usr/include/i386-linux-gnu/sys/stat.h \
|
||||||
|
/usr/include/i386-linux-gnu/bits/stat.h \
|
||||||
|
/usr/include/i386-linux-gnu/bits/struct_stat.h
|
||||||
|
src/channel.h:
|
||||||
|
/usr/include/i386-linux-gnu/sys/stat.h:
|
||||||
|
/usr/include/i386-linux-gnu/bits/stat.h:
|
||||||
|
/usr/include/i386-linux-gnu/bits/struct_stat.h:
|
||||||
|
|
@ -9,10 +9,114 @@ void frame_data_free(FrameData *frame) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_freep(&frame->buffer);
|
if (frame->pool && frame->buffer) {
|
||||||
|
video_buffer_pool_release(frame->pool, frame->buffer);
|
||||||
|
}
|
||||||
memset(frame, 0, sizeof(*frame));
|
memset(frame, 0, sizeof(*frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int frame_queue_is_full(FrameQueue *queue) {
|
||||||
|
int full;
|
||||||
|
if (!queue || !queue->mutex) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SDL_LockMutex(queue->mutex);
|
||||||
|
full = (queue->count >= FRAME_QUEUE_CAPACITY);
|
||||||
|
SDL_UnlockMutex(queue->mutex);
|
||||||
|
return full;
|
||||||
|
}
|
||||||
|
|
||||||
|
int video_buffer_pool_init(VideoBufferPool *pool) {
|
||||||
|
int i;
|
||||||
|
int yuv420p_size;
|
||||||
|
|
||||||
|
if (!pool) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(pool, 0, sizeof(*pool));
|
||||||
|
pool->mutex = SDL_CreateMutex();
|
||||||
|
if (!pool->mutex) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
yuv420p_size = TARGET_WIDTH * TARGET_HEIGHT * 3 / 2;
|
||||||
|
pool->buffer_size = yuv420p_size;
|
||||||
|
|
||||||
|
for (i = 0; i < VIDEO_BUFFER_POOL_SIZE; i++) {
|
||||||
|
pool->buffers[i] = (unsigned char *)av_malloc(yuv420p_size + 32);
|
||||||
|
if (!pool->buffers[i]) {
|
||||||
|
video_buffer_pool_destroy(pool);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pool->available[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void video_buffer_pool_destroy(VideoBufferPool *pool) {
|
||||||
|
int i;
|
||||||
|
if (!pool) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pool->mutex) {
|
||||||
|
SDL_LockMutex(pool->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < VIDEO_BUFFER_POOL_SIZE; i++) {
|
||||||
|
if (pool->buffers[i]) {
|
||||||
|
av_freep(&pool->buffers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pool->mutex) {
|
||||||
|
SDL_UnlockMutex(pool->mutex);
|
||||||
|
SDL_DestroyMutex(pool->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(pool, 0, sizeof(*pool));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *video_buffer_pool_acquire(VideoBufferPool *pool) {
|
||||||
|
unsigned char *buffer = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!pool || !pool->mutex) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_LockMutex(pool->mutex);
|
||||||
|
for (i = 0; i < VIDEO_BUFFER_POOL_SIZE; i++) {
|
||||||
|
if (pool->available[i]) {
|
||||||
|
pool->available[i] = 0;
|
||||||
|
buffer = pool->buffers[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_UnlockMutex(pool->mutex);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void video_buffer_pool_release(VideoBufferPool *pool, unsigned char *buffer) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!pool || !pool->mutex || !buffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_LockMutex(pool->mutex);
|
||||||
|
for (i = 0; i < VIDEO_BUFFER_POOL_SIZE; i++) {
|
||||||
|
if (pool->buffers[i] == buffer) {
|
||||||
|
pool->available[i] = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_UnlockMutex(pool->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
int frame_queue_init(FrameQueue *queue) {
|
int frame_queue_init(FrameQueue *queue) {
|
||||||
if (!queue) {
|
if (!queue) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
2
src/frame_queue.d
Normal file
2
src/frame_queue.d
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
src/frame_queue.o: src/frame_queue.c src/frame_queue.h
|
||||||
|
src/frame_queue.h:
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
#ifndef FRAME_QUEUE_H
|
#ifndef FRAME_QUEUE_H
|
||||||
#define FRAME_QUEUE_H
|
#define FRAME_QUEUE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#define FRAME_QUEUE_CAPACITY 12
|
#define FRAME_QUEUE_CAPACITY 6
|
||||||
|
#define TARGET_WIDTH 640
|
||||||
|
#define TARGET_HEIGHT 360
|
||||||
|
#define VIDEO_BUFFER_POOL_SIZE 16
|
||||||
|
|
||||||
typedef struct FrameData {
|
typedef struct FrameData {
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
|
struct VideoBufferPool *pool;
|
||||||
unsigned char *plane_y;
|
unsigned char *plane_y;
|
||||||
unsigned char *plane_u;
|
unsigned char *plane_u;
|
||||||
unsigned char *plane_v;
|
unsigned char *plane_v;
|
||||||
|
|
@ -26,6 +31,13 @@ typedef struct FrameQueue {
|
||||||
SDL_cond *cond;
|
SDL_cond *cond;
|
||||||
} FrameQueue;
|
} FrameQueue;
|
||||||
|
|
||||||
|
typedef struct VideoBufferPool {
|
||||||
|
unsigned char *buffers[VIDEO_BUFFER_POOL_SIZE];
|
||||||
|
int buffer_size;
|
||||||
|
int available[VIDEO_BUFFER_POOL_SIZE];
|
||||||
|
SDL_mutex *mutex;
|
||||||
|
} VideoBufferPool;
|
||||||
|
|
||||||
int frame_queue_init(FrameQueue *queue);
|
int frame_queue_init(FrameQueue *queue);
|
||||||
void frame_queue_destroy(FrameQueue *queue);
|
void frame_queue_destroy(FrameQueue *queue);
|
||||||
void frame_queue_clear(FrameQueue *queue);
|
void frame_queue_clear(FrameQueue *queue);
|
||||||
|
|
@ -34,5 +46,11 @@ int frame_queue_pop_latest(FrameQueue *queue, FrameData *out);
|
||||||
int frame_queue_peek_first(FrameQueue *queue, FrameData *out);
|
int frame_queue_peek_first(FrameQueue *queue, FrameData *out);
|
||||||
int frame_queue_pop_first(FrameQueue *queue, FrameData *out);
|
int frame_queue_pop_first(FrameQueue *queue, FrameData *out);
|
||||||
void frame_data_free(FrameData *frame);
|
void frame_data_free(FrameData *frame);
|
||||||
|
int frame_queue_is_full(FrameQueue *queue);
|
||||||
|
|
||||||
|
int video_buffer_pool_init(VideoBufferPool *pool);
|
||||||
|
void video_buffer_pool_destroy(VideoBufferPool *pool);
|
||||||
|
unsigned char *video_buffer_pool_acquire(VideoBufferPool *pool);
|
||||||
|
void video_buffer_pool_release(VideoBufferPool *pool, unsigned char *buffer);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
8
src/main.d
Normal file
8
src/main.d
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
src/main.o: src/main.c src/app.h src/channel.h src/player.h \
|
||||||
|
src/frame_queue.h src/theme.h src/ui.h
|
||||||
|
src/app.h:
|
||||||
|
src/channel.h:
|
||||||
|
src/player.h:
|
||||||
|
src/frame_queue.h:
|
||||||
|
src/theme.h:
|
||||||
|
src/ui.h:
|
||||||
125
src/player.c
125
src/player.c
|
|
@ -15,6 +15,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define AUDIO_BUFFER_SAMPLES 48000
|
||||||
|
|
||||||
typedef struct DecoderThreadArgs {
|
typedef struct DecoderThreadArgs {
|
||||||
Player *player;
|
Player *player;
|
||||||
const Channel *channel;
|
const Channel *channel;
|
||||||
|
|
@ -186,7 +188,7 @@ static int queue_audio_frame(Player *player,
|
||||||
AVFrame *audio_frame,
|
AVFrame *audio_frame,
|
||||||
double pts_base_offset,
|
double pts_base_offset,
|
||||||
int *queued_any_audio) {
|
int *queued_any_audio) {
|
||||||
uint8_t **converted_data = NULL;
|
uint8_t *converted_data[1] = {NULL};
|
||||||
int out_rate;
|
int out_rate;
|
||||||
int out_channels;
|
int out_channels;
|
||||||
enum AVSampleFormat out_format;
|
enum AVSampleFormat out_format;
|
||||||
|
|
@ -196,10 +198,10 @@ static int queue_audio_frame(Player *player,
|
||||||
int sample_count;
|
int sample_count;
|
||||||
int buffer_size;
|
int buffer_size;
|
||||||
int queued_limit;
|
int queued_limit;
|
||||||
int line_size = 0;
|
|
||||||
int result;
|
int result;
|
||||||
double audio_pts;
|
double audio_pts;
|
||||||
double frame_duration;
|
double frame_duration;
|
||||||
|
int wait_ms = 2;
|
||||||
|
|
||||||
if (!player || !audio_codec_context || !audio_frame) {
|
if (!player || !audio_codec_context || !audio_frame) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -236,16 +238,20 @@ static int queue_audio_frame(Player *player,
|
||||||
audio_codec_context->sample_rate,
|
audio_codec_context->sample_rate,
|
||||||
AV_ROUND_UP);
|
AV_ROUND_UP);
|
||||||
|
|
||||||
if (av_samples_alloc_array_and_samples(&converted_data,
|
if (max_samples > player->audio_convert_buffer_samples) {
|
||||||
&line_size,
|
int new_size = max_samples * out_channels * sizeof(int16_t);
|
||||||
out_channels,
|
uint8_t *new_buffer = (uint8_t *)av_realloc(player->audio_convert_buffer, new_size);
|
||||||
max_samples,
|
if (!new_buffer) {
|
||||||
out_format,
|
|
||||||
0) < 0) {
|
|
||||||
av_channel_layout_uninit(&out_layout);
|
av_channel_layout_uninit(&out_layout);
|
||||||
player_set_error(player, "Unable to allocate audio buffer");
|
player_set_error(player, "Unable to resize audio buffer");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
player->audio_convert_buffer = new_buffer;
|
||||||
|
player->audio_convert_buffer_samples = max_samples;
|
||||||
|
player->audio_convert_buffer_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
converted_data[0] = player->audio_convert_buffer;
|
||||||
|
|
||||||
sample_count = swr_convert(*swr_context,
|
sample_count = swr_convert(*swr_context,
|
||||||
converted_data,
|
converted_data,
|
||||||
|
|
@ -253,17 +259,13 @@ static int queue_audio_frame(Player *player,
|
||||||
(const uint8_t * const *) audio_frame->extended_data,
|
(const uint8_t * const *) audio_frame->extended_data,
|
||||||
audio_frame->nb_samples);
|
audio_frame->nb_samples);
|
||||||
if (sample_count < 0) {
|
if (sample_count < 0) {
|
||||||
av_freep(&converted_data[0]);
|
|
||||||
av_freep(&converted_data);
|
|
||||||
av_channel_layout_uninit(&out_layout);
|
av_channel_layout_uninit(&out_layout);
|
||||||
player_set_error(player, "Audio resample failed");
|
player_set_error(player, "Audio resample failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_size = av_samples_get_buffer_size(&line_size, out_channels, sample_count, out_format, 1);
|
buffer_size = sample_count * out_channels * sizeof(int16_t);
|
||||||
if (buffer_size <= 0) {
|
if (buffer_size <= 0) {
|
||||||
av_freep(&converted_data[0]);
|
|
||||||
av_freep(&converted_data);
|
|
||||||
av_channel_layout_uninit(&out_layout);
|
av_channel_layout_uninit(&out_layout);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -275,12 +277,11 @@ static int queue_audio_frame(Player *player,
|
||||||
|
|
||||||
queued_limit = (int) (player_audio_bytes_per_second(player) * 0.18);
|
queued_limit = (int) (player_audio_bytes_per_second(player) * 0.18);
|
||||||
while (!should_stop(player) && (int) SDL_GetQueuedAudioSize(player->audio_device) > queued_limit) {
|
while (!should_stop(player) && (int) SDL_GetQueuedAudioSize(player->audio_device) > queued_limit) {
|
||||||
SDL_Delay(2);
|
SDL_Delay(wait_ms);
|
||||||
|
wait_ms = (wait_ms < 10) ? wait_ms + 1 : 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = SDL_QueueAudio(player->audio_device, converted_data[0], (Uint32) buffer_size);
|
result = SDL_QueueAudio(player->audio_device, player->audio_convert_buffer, (Uint32) buffer_size);
|
||||||
av_freep(&converted_data[0]);
|
|
||||||
av_freep(&converted_data);
|
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
av_channel_layout_uninit(&out_layout);
|
av_channel_layout_uninit(&out_layout);
|
||||||
|
|
@ -403,8 +404,8 @@ static int decode_context_open(DecodeContext *ctx, const ProgramEntry *program,
|
||||||
ctx->sws_context = sws_getContext(ctx->video_codec_context->width,
|
ctx->sws_context = sws_getContext(ctx->video_codec_context->width,
|
||||||
ctx->video_codec_context->height,
|
ctx->video_codec_context->height,
|
||||||
ctx->video_codec_context->pix_fmt,
|
ctx->video_codec_context->pix_fmt,
|
||||||
ctx->video_codec_context->width,
|
TARGET_WIDTH,
|
||||||
ctx->video_codec_context->height,
|
TARGET_HEIGHT,
|
||||||
AV_PIX_FMT_YUV420P,
|
AV_PIX_FMT_YUV420P,
|
||||||
SWS_BILINEAR,
|
SWS_BILINEAR,
|
||||||
NULL,
|
NULL,
|
||||||
|
|
@ -612,23 +613,40 @@ static int decode_thread_main(void *userdata) {
|
||||||
FrameData frame = {0};
|
FrameData frame = {0};
|
||||||
uint8_t *dest_data[4] = {0};
|
uint8_t *dest_data[4] = {0};
|
||||||
int dest_linesize[4] = {0};
|
int dest_linesize[4] = {0};
|
||||||
int image_size;
|
int needs_conversion = 1;
|
||||||
|
|
||||||
frame.width = ctx.video_codec_context->width;
|
while (!should_stop(player) && frame_queue_is_full(&player->frame_queue)) {
|
||||||
frame.height = ctx.video_codec_context->height;
|
SDL_Delay(5);
|
||||||
|
}
|
||||||
|
if (should_stop(player)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.width = TARGET_WIDTH;
|
||||||
|
frame.height = TARGET_HEIGHT;
|
||||||
frame.pts_seconds = frame_seconds;
|
frame.pts_seconds = frame_seconds;
|
||||||
image_size = av_image_alloc(dest_data, dest_linesize, frame.width, frame.height, AV_PIX_FMT_YUV420P, 1);
|
|
||||||
if (image_size < 0) {
|
frame.buffer = video_buffer_pool_acquire(&player->video_buffer_pool);
|
||||||
player_set_error(player, "Unable to allocate frame buffer");
|
if (!frame.buffer) {
|
||||||
|
player_set_error(player, "Unable to acquire frame buffer from pool");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
frame.buffer = dest_data[0];
|
|
||||||
frame.plane_y = dest_data[0];
|
frame.pool = &player->video_buffer_pool;
|
||||||
frame.plane_u = dest_data[1];
|
dest_data[0] = frame.buffer;
|
||||||
frame.plane_v = dest_data[2];
|
dest_data[1] = frame.buffer + (TARGET_WIDTH * TARGET_HEIGHT);
|
||||||
frame.pitch_y = dest_linesize[0];
|
dest_data[2] = frame.buffer + (TARGET_WIDTH * TARGET_HEIGHT * 5 / 4);
|
||||||
frame.pitch_u = dest_linesize[1];
|
dest_linesize[0] = TARGET_WIDTH;
|
||||||
frame.pitch_v = dest_linesize[2];
|
dest_linesize[1] = TARGET_WIDTH / 2;
|
||||||
|
dest_linesize[2] = TARGET_WIDTH / 2;
|
||||||
|
|
||||||
|
if (ctx.video_codec_context->width == TARGET_WIDTH &&
|
||||||
|
ctx.video_codec_context->height == TARGET_HEIGHT &&
|
||||||
|
ctx.video_codec_context->pix_fmt == AV_PIX_FMT_YUV420P) {
|
||||||
|
needs_conversion = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needs_conversion) {
|
||||||
sws_scale(ctx.sws_context,
|
sws_scale(ctx.sws_context,
|
||||||
(const uint8_t *const *) ctx.decoded_frame->data,
|
(const uint8_t *const *) ctx.decoded_frame->data,
|
||||||
ctx.decoded_frame->linesize,
|
ctx.decoded_frame->linesize,
|
||||||
|
|
@ -636,6 +654,21 @@ static int decode_thread_main(void *userdata) {
|
||||||
ctx.video_codec_context->height,
|
ctx.video_codec_context->height,
|
||||||
dest_data,
|
dest_data,
|
||||||
dest_linesize);
|
dest_linesize);
|
||||||
|
} else {
|
||||||
|
av_image_copy(dest_data, dest_linesize,
|
||||||
|
(const uint8_t *const *) ctx.decoded_frame->data,
|
||||||
|
ctx.decoded_frame->linesize,
|
||||||
|
AV_PIX_FMT_YUV420P,
|
||||||
|
TARGET_WIDTH, TARGET_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.plane_y = dest_data[0];
|
||||||
|
frame.plane_u = dest_data[1];
|
||||||
|
frame.plane_v = dest_data[2];
|
||||||
|
frame.pitch_y = dest_linesize[0];
|
||||||
|
frame.pitch_u = dest_linesize[1];
|
||||||
|
frame.pitch_v = dest_linesize[2];
|
||||||
|
|
||||||
frame_queue_push(&player->frame_queue, &frame);
|
frame_queue_push(&player->frame_queue, &frame);
|
||||||
queued_first_video = 1;
|
queued_first_video = 1;
|
||||||
MAYBE_MARK_PREROLL_READY();
|
MAYBE_MARK_PREROLL_READY();
|
||||||
|
|
@ -696,6 +729,28 @@ int player_init(Player *player, const ChannelList *channels, Uint64 app_start_ti
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (video_buffer_pool_init(&player->video_buffer_pool) != 0) {
|
||||||
|
frame_queue_destroy(&player->frame_queue);
|
||||||
|
SDL_DestroyMutex(player->audio_mutex);
|
||||||
|
SDL_DestroyMutex(player->clock_mutex);
|
||||||
|
SDL_DestroyMutex(player->error_mutex);
|
||||||
|
memset(player, 0, sizeof(*player));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
player->audio_convert_buffer_samples = AUDIO_BUFFER_SAMPLES;
|
||||||
|
player->audio_convert_buffer_size = AUDIO_BUFFER_SAMPLES * 2 * sizeof(int16_t);
|
||||||
|
player->audio_convert_buffer = (uint8_t *)av_malloc(player->audio_convert_buffer_size);
|
||||||
|
if (!player->audio_convert_buffer) {
|
||||||
|
video_buffer_pool_destroy(&player->video_buffer_pool);
|
||||||
|
frame_queue_destroy(&player->frame_queue);
|
||||||
|
SDL_DestroyMutex(player->audio_mutex);
|
||||||
|
SDL_DestroyMutex(player->clock_mutex);
|
||||||
|
SDL_DestroyMutex(player->error_mutex);
|
||||||
|
memset(player, 0, sizeof(*player));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -706,6 +761,10 @@ void player_destroy(Player *player) {
|
||||||
|
|
||||||
player_stop_thread(player);
|
player_stop_thread(player);
|
||||||
player_close_audio(player);
|
player_close_audio(player);
|
||||||
|
video_buffer_pool_destroy(&player->video_buffer_pool);
|
||||||
|
if (player->audio_convert_buffer) {
|
||||||
|
av_freep(&player->audio_convert_buffer);
|
||||||
|
}
|
||||||
frame_queue_destroy(&player->frame_queue);
|
frame_queue_destroy(&player->frame_queue);
|
||||||
if (player->audio_mutex) {
|
if (player->audio_mutex) {
|
||||||
SDL_DestroyMutex(player->audio_mutex);
|
SDL_DestroyMutex(player->audio_mutex);
|
||||||
|
|
|
||||||
4
src/player.d
Normal file
4
src/player.d
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
src/player.o: src/player.c src/player.h src/channel.h src/frame_queue.h
|
||||||
|
src/player.h:
|
||||||
|
src/channel.h:
|
||||||
|
src/frame_queue.h:
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef PLAYER_H
|
#ifndef PLAYER_H
|
||||||
#define PLAYER_H
|
#define PLAYER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
|
@ -9,6 +10,7 @@
|
||||||
|
|
||||||
typedef struct Player {
|
typedef struct Player {
|
||||||
FrameQueue frame_queue;
|
FrameQueue frame_queue;
|
||||||
|
VideoBufferPool video_buffer_pool;
|
||||||
SDL_Thread *thread;
|
SDL_Thread *thread;
|
||||||
SDL_atomic_t stop_requested;
|
SDL_atomic_t stop_requested;
|
||||||
const ChannelList *channels;
|
const ChannelList *channels;
|
||||||
|
|
@ -27,6 +29,9 @@ typedef struct Player {
|
||||||
char audio_driver[32];
|
char audio_driver[32];
|
||||||
SDL_mutex *error_mutex;
|
SDL_mutex *error_mutex;
|
||||||
char last_error[256];
|
char last_error[256];
|
||||||
|
uint8_t *audio_convert_buffer;
|
||||||
|
int audio_convert_buffer_size;
|
||||||
|
int audio_convert_buffer_samples;
|
||||||
} Player;
|
} Player;
|
||||||
|
|
||||||
int player_init(Player *player, const ChannelList *channels, Uint64 app_start_ticks);
|
int player_init(Player *player, const ChannelList *channels, Uint64 app_start_ticks);
|
||||||
|
|
|
||||||
4
src/ui.d
Normal file
4
src/ui.d
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
src/ui.o: src/ui.c src/ui.h src/channel.h src/theme.h
|
||||||
|
src/ui.h:
|
||||||
|
src/channel.h:
|
||||||
|
src/theme.h:
|
||||||
Loading…
Add table
Add a link
Reference in a new issue