Pass StreamInfo to Video Receiver

This commit is contained in:
Florian Märkl 2019-06-01 13:30:27 +02:00
commit ef106073d9
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
6 changed files with 148 additions and 2 deletions

View file

@ -18,6 +18,7 @@ set(HEADER_FILES
include/chiaki/gkcrypt.h
include/chiaki/audio.h
include/chiaki/audioreceiver.h
include/chiaki/video.h
include/chiaki/videoreceiver.h)
set(SOURCE_FILES

View file

@ -0,0 +1,40 @@
/*
* This file is part of Chiaki.
*
* Chiaki is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Chiaki is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Chiaki. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef CHIAKI_VIDEO_H
#define CHIAKI_VIDEO_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct chiaki_video_profile_t
{
unsigned int width;
unsigned int height;
size_t header_sz;
uint8_t *header;
} ChiakiVideoProfile;
#ifdef __cplusplus
}
#endif
#endif // CHIAKI_VIDEO_H

View file

@ -20,21 +20,34 @@
#include "common.h"
#include "log.h"
#include "video.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CHIAKI_VIDEO_PROFILES_MAX 8
typedef struct chiaki_video_receiver_t
{
struct chiaki_session_t *session;
ChiakiLog *log;
ChiakiVideoProfile profiles[CHIAKI_VIDEO_PROFILES_MAX];
size_t profiles_count;
} ChiakiVideoReceiver;
CHIAKI_EXPORT void chiaki_video_receiver_init(ChiakiVideoReceiver *video_receiver, struct chiaki_session_t *session);
CHIAKI_EXPORT void chiaki_video_receiver_fini(ChiakiVideoReceiver *video_receiver);
/**
* Called after receiving the Stream Info Packet.
*
* @param video_receiver
* @param profiles Array of profiles. Ownership of the contained header buffers will be transferred to the ChiakiVideoReceiver!
* @param profiles_count must be <= CHIAKI_VIDEO_PROFILES_MAX
*/
CHIAKI_EXPORT void chiaki_video_receiver_stream_info(ChiakiVideoReceiver *video_receiver, ChiakiVideoProfile *profiles, size_t profiles_count);
static inline ChiakiVideoReceiver *chiaki_video_receiver_new(struct chiaki_session_t *session)
{
ChiakiVideoReceiver *video_receiver = CHIAKI_NEW(ChiakiVideoReceiver);

View file

@ -21,6 +21,7 @@
#include <chiaki/launchspec.h>
#include <chiaki/base64.h>
#include <chiaki/audio.h>
#include <chiaki/video.h>
#include <string.h>
#include <assert.h>
@ -305,6 +306,44 @@ error:
chiaki_mirai_signal(&nagare->mirai, NAGARE_MIRAI_RESPONSE_FAIL);
}
typedef struct decode_resolutions_context_t
{
ChiakiNagare *nagare;
ChiakiVideoProfile video_profiles[CHIAKI_VIDEO_PROFILES_MAX];
size_t video_profiles_count;
} DecodeResolutionsContext;
static bool pb_decode_resolution(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
DecodeResolutionsContext *ctx = *arg;
tkproto_ResolutionPayload resolution = { 0 };
ChiakiPBDecodeBufAlloc header_buf = { 0 };
resolution.video_header.arg = &header_buf;
resolution.video_header.funcs.decode = chiaki_pb_decode_buf_alloc;
if(!pb_decode(stream, tkproto_ResolutionPayload_fields, &resolution))
return false;
if(!header_buf.buf)
{
CHIAKI_LOGE(&ctx->nagare->session->log, "Failed to decode video header\n");
return true;
}
if(ctx->video_profiles_count >= CHIAKI_VIDEO_PROFILES_MAX)
{
CHIAKI_LOGE(&ctx->nagare->session->log, "Received more resolutions than the maximum\n");
return true;
}
ChiakiVideoProfile *profile = &ctx->video_profiles[ctx->video_profiles_count++];
profile->width = resolution.width;
profile->height = resolution.height;
profile->header_sz = header_buf.size;
profile->header = header_buf.buf;
return true;
}
static void nagare_takion_data_expect_streaminfo(ChiakiNagare *nagare, uint8_t *buf, size_t buf_size)
{
@ -316,7 +355,12 @@ static void nagare_takion_data_expect_streaminfo(ChiakiNagare *nagare, uint8_t *
msg.stream_info_payload.audio_header.arg = &audio_header_buf;
msg.stream_info_payload.audio_header.funcs.decode = chiaki_pb_decode_buf;
// TODO: msg.stream_info_payload.resolution
DecodeResolutionsContext decode_resolutions_context;
decode_resolutions_context.nagare = nagare;
memset(decode_resolutions_context.video_profiles, 0, sizeof(decode_resolutions_context.video_profiles));
decode_resolutions_context.video_profiles_count = 0;
msg.stream_info_payload.resolution.arg = &decode_resolutions_context;
msg.stream_info_payload.resolution.funcs.decode = pb_decode_resolution;
pb_istream_t stream = pb_istream_from_buffer(buf, buf_size);
bool r = pb_decode(&stream, tkproto_TakionMessage_fields, &msg);
@ -342,6 +386,10 @@ static void nagare_takion_data_expect_streaminfo(ChiakiNagare *nagare, uint8_t *
chiaki_audio_header_load(&audio_header_s, audio_header);
chiaki_audio_receiver_stream_info(nagare->session->audio_receiver, &audio_header_s);
chiaki_video_receiver_stream_info(nagare->session->video_receiver,
decode_resolutions_context.video_profiles,
decode_resolutions_context.video_profiles_count);
// TODO: do some checks?
nagare_send_streaminfo_ack(nagare);

View file

@ -72,4 +72,23 @@ static bool chiaki_pb_decode_buf(pb_istream_t *stream, const pb_field_t *field,
}
typedef struct chiaki_pb_decode_buf_alloc_t
{
size_t size;
uint8_t *buf;
} ChiakiPBDecodeBufAlloc;
static bool chiaki_pb_decode_buf_alloc(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
ChiakiPBDecodeBufAlloc *buf = *arg;
buf->size = stream->bytes_left;
buf->buf = malloc(buf->size);
if(!buf->buf)
return false;
bool r = pb_read(stream, buf->buf, buf->size);
if(!r)
buf->size = 0;
return r;
}
#endif // CHIAKI_PB_UTILS_H

View file

@ -18,13 +18,38 @@
#include <chiaki/videoreceiver.h>
#include <chiaki/session.h>
#include <string.h>
CHIAKI_EXPORT void chiaki_video_receiver_init(ChiakiVideoReceiver *video_receiver, struct chiaki_session_t *session)
{
video_receiver->session = session;
video_receiver->log = &session->log;
memset(video_receiver->profiles, 0, sizeof(video_receiver->profiles));
video_receiver->profiles_count = 0;
}
CHIAKI_EXPORT void chiaki_video_receiver_fini(ChiakiVideoReceiver *video_receiver)
{
for(size_t i=0; i<video_receiver->profiles_count; i++)
free(video_receiver->profiles[i].header);
}
CHIAKI_EXPORT void chiaki_video_receiver_stream_info(ChiakiVideoReceiver *video_receiver, ChiakiVideoProfile *profiles, size_t profiles_count)
{
if(video_receiver->profiles_count > 0)
{
CHIAKI_LOGE(video_receiver->log, "Video Receiver profiles already set\n");
return;
}
memcpy(video_receiver->profiles, profiles, profiles_count * sizeof(ChiakiVideoProfile));
video_receiver->profiles_count = profiles_count;
CHIAKI_LOGI(video_receiver->log, "Video Profiles:\n");
for(size_t i=0; i<video_receiver->profiles_count; i++)
{
ChiakiVideoProfile *profile = &video_receiver->profiles[i];
CHIAKI_LOGI(video_receiver->log, " %zu: %ux%u\n", i, profile->width, profile->height);
chiaki_log_hexdump(video_receiver->log, CHIAKI_LOG_DEBUG, profile->header, profile->header_sz);
}
}