parent
0d3a2c7207
commit
f31ef14b89
@ -0,0 +1,24 @@
|
||||
EXTRA_DIST = xrdpvr.h
|
||||
|
||||
EXTRA_DEFINES =
|
||||
EXTRA_INCLUDES =
|
||||
EXTRA_LIBS =
|
||||
EXTRA_FLAGS =
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(EXTRA_DEFINES)
|
||||
|
||||
INCLUDES = \
|
||||
$(EXTRA_INCLUDES)
|
||||
|
||||
lib_LTLIBRARIES = \
|
||||
libxrdpvr.la
|
||||
|
||||
libxrdpvr_la_SOURCES = \
|
||||
xrdpvr.c
|
||||
|
||||
libxrdpvr_la_LDFLAGS = \
|
||||
$(EXTRA_FLAGS)
|
||||
|
||||
libxrdpvr_la_LIBADD = \
|
||||
$(EXTRA_LIBS)
|
@ -0,0 +1,522 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Laxmikant Rashinkar 2012 LK.Rashinkar@gmail.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* a program that uses xrdpapi and ffmpeg to redirect media streams
|
||||
* to a FreeRDP client where it is decompressed and played locally
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xrdpvr.h"
|
||||
#include "xrdpvr_internal.h"
|
||||
|
||||
/* globals */
|
||||
PLAYER_STATE_INFO g_psi;
|
||||
|
||||
/**
|
||||
* initialize the media player
|
||||
*
|
||||
* @param channel opaque handle returned by WTSVirtualChannelOpenEx
|
||||
* @param stream_id unique identification number for this stream
|
||||
* @param filename media file to play
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*****************************************************************************/
|
||||
int
|
||||
xrdpvr_init_player(void *channel, int stream_id, char *filename)
|
||||
{
|
||||
if ((channel == NULL) || (stream_id <= 0) || (filename == NULL))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send metadata from media file to client */
|
||||
if (xrdpvr_create_metadata_file(channel, filename))
|
||||
{
|
||||
printf("error sending metadata to client\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ask client to get video format from media file */
|
||||
if (xrdpvr_set_video_format(channel, 101))
|
||||
{
|
||||
printf("xrdpvr_set_video_format() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
sleep(3);
|
||||
|
||||
/* ask client to get audio format from media file */
|
||||
if (xrdpvr_set_audio_format(channel, 101))
|
||||
{
|
||||
printf("xrdpvr_set_audio_format() failed\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* de-initialize the media player
|
||||
*
|
||||
* @param channel opaque handle returned by WTSVirtualChannelOpenEx
|
||||
* @param stream_id unique identification number for this stream
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*****************************************************************************/
|
||||
int
|
||||
xrdpvr_deinit_player(void *channel, int stream_id)
|
||||
{
|
||||
STREAM *s;
|
||||
char *cptr;
|
||||
int rv;
|
||||
int len;
|
||||
|
||||
if ((channel == NULL) || (stream_id <= 0))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* do local clean up */
|
||||
av_free(g_psi.frame);
|
||||
avcodec_close(g_psi.p_audio_codec_ctx);
|
||||
avcodec_close(g_psi.p_video_codec_ctx);
|
||||
avformat_close_input(&g_psi.p_format_ctx);
|
||||
|
||||
/* do remote cleanup */
|
||||
|
||||
stream_new(s, MAX_PDU_SIZE);
|
||||
|
||||
stream_ins_u32_le(s, 0); /* number of bytes to follow */
|
||||
stream_ins_u32_le(s, CMD_DEINIT_XRDPVR);
|
||||
stream_ins_u32_le(s, stream_id);
|
||||
|
||||
/* insert number of bytes in stream */
|
||||
len = stream_length(s) - 4;
|
||||
cptr = s->p;
|
||||
s->p = s->data;
|
||||
stream_ins_u32_le(s, len);
|
||||
s->p = cptr;
|
||||
|
||||
/* write data to virtual channel */
|
||||
rv = xrdpvr_write_to_client(channel, s);
|
||||
stream_free(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* play the media
|
||||
*
|
||||
* @param channel opaque handle returned by WTSVirtualChannelOpenEx
|
||||
* @param stream_id unique identification number for this stream
|
||||
* @param filename media file to play
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*****************************************************************************/
|
||||
int
|
||||
xrdpvr_play_media(void *channel, int stream_id, char *filename)
|
||||
{
|
||||
AVDictionary *p_audio_opt_dict = NULL;
|
||||
AVDictionary *p_video_opt_dict = NULL;
|
||||
AVPacket av_pkt;
|
||||
|
||||
int video_index = -1;
|
||||
int audio_index = -1;
|
||||
int i;
|
||||
|
||||
/* register all available fileformats and codecs */
|
||||
av_register_all();
|
||||
|
||||
/* open media file - this will read just the header */
|
||||
if (avformat_open_input(&g_psi.p_format_ctx, filename, NULL, NULL))
|
||||
{
|
||||
printf("ERROR opening %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now get the real stream info */
|
||||
if (avformat_find_stream_info(g_psi.p_format_ctx, NULL) < 0)
|
||||
{
|
||||
printf("ERRRO reading stream info\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* print media info to standard out */
|
||||
av_dump_format(g_psi.p_format_ctx, 0, filename, 0);
|
||||
#endif
|
||||
|
||||
/* find first audio / video stream */
|
||||
for (i = 0; i < g_psi.p_format_ctx->nb_streams; i++)
|
||||
{
|
||||
if (g_psi.p_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
|
||||
video_index < 0)
|
||||
{
|
||||
video_index = i;
|
||||
}
|
||||
|
||||
if (g_psi.p_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
|
||||
audio_index < 0)
|
||||
{
|
||||
audio_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ((audio_index < 0) && (video_index < 0))
|
||||
{
|
||||
/* close file and return with error */
|
||||
printf("ERROR: no audio/video stream found in %s\n", filename);
|
||||
avformat_close_input(&g_psi.p_format_ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_psi.audio_stream_index = audio_index;
|
||||
g_psi.video_stream_index = video_index;
|
||||
|
||||
/* get pointers to codex contexts for both streams */
|
||||
g_psi.p_audio_codec_ctx = g_psi.p_format_ctx->streams[audio_index]->codec;
|
||||
g_psi.p_video_codec_ctx = g_psi.p_format_ctx->streams[video_index]->codec;
|
||||
|
||||
/* find decoder for audio stream */
|
||||
g_psi.p_audio_codec = avcodec_find_decoder(g_psi.p_audio_codec_ctx->codec_id);
|
||||
|
||||
if (g_psi.p_audio_codec == NULL)
|
||||
{
|
||||
printf("ERROR: audio codec not supported\n");
|
||||
}
|
||||
|
||||
/* find decoder for video stream */
|
||||
g_psi.p_video_codec = avcodec_find_decoder(g_psi.p_video_codec_ctx->codec_id);
|
||||
|
||||
if (g_psi.p_video_codec == NULL)
|
||||
{
|
||||
printf("ERROR: video codec not supported\n");
|
||||
}
|
||||
|
||||
/* open decoder for audio stream */
|
||||
if (avcodec_open2(g_psi.p_audio_codec_ctx, g_psi.p_audio_codec,
|
||||
&p_audio_opt_dict) < 0)
|
||||
{
|
||||
printf("ERROR: could not open audio decoder\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* open decoder for video stream */
|
||||
if (avcodec_open2(g_psi.p_video_codec_ctx, g_psi.p_video_codec,
|
||||
&p_video_opt_dict) < 0)
|
||||
{
|
||||
printf("ERROR: could not open video decoder\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (av_read_frame(g_psi.p_format_ctx, &av_pkt) >= 0)
|
||||
{
|
||||
if (av_pkt.stream_index == audio_index)
|
||||
{
|
||||
xrdpvr_send_audio_data(channel, stream_id, av_pkt.size, av_pkt.data);
|
||||
usleep(1000 * 1);
|
||||
}
|
||||
else if (av_pkt.stream_index == video_index)
|
||||
{
|
||||
xrdpvr_send_video_data(channel, stream_id, av_pkt.size, av_pkt.data);
|
||||
usleep(1000 * 40); // was 50
|
||||
}
|
||||
}
|
||||
|
||||
av_free_packet(&av_pkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* code below this is local to this file and cannot be accessed externally;
|
||||
* this code communicates with the xrdpvr plugin in NeutrinoRDP;
|
||||
* NeutrinoRDP is a fork of FreeRDP 1.0.1
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* set video format
|
||||
*
|
||||
* @param channel opaque handle returned by WTSVirtualChannelOpenEx
|
||||
* @param stream_id unique identification number for this stream
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*****************************************************************************/
|
||||
static int
|
||||
xrdpvr_set_video_format(void *channel, uint32_t stream_id)
|
||||
{
|
||||
STREAM *s;
|
||||
char *cptr;
|
||||
int rv;
|
||||
int len;
|
||||
|
||||
stream_new(s, MAX_PDU_SIZE);
|
||||
|
||||
stream_ins_u32_le(s, 0); /* number of bytes to follow */
|
||||
stream_ins_u32_le(s, CMD_SET_VIDEO_FORMAT);
|
||||
stream_ins_u32_le(s, stream_id);
|
||||
|
||||
/* insert number of bytes in stream */
|
||||
len = stream_length(s) - 4;
|
||||
cptr = s->p;
|
||||
s->p = s->data;
|
||||
stream_ins_u32_le(s, len);
|
||||
s->p = cptr;
|
||||
|
||||
/* write data to virtual channel */
|
||||
rv = xrdpvr_write_to_client(channel, s);
|
||||
stream_free(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* set audio format
|
||||
*
|
||||
* @param channel opaque handle returned by WTSVirtualChannelOpenEx
|
||||
* @param stream_id unique identification number for this stream
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*****************************************************************************/
|
||||
static int
|
||||
xrdpvr_set_audio_format(void *channel, uint32_t stream_id)
|
||||
{
|
||||
STREAM *s;
|
||||
char *cptr;
|
||||
int rv;
|
||||
int len;
|
||||
|
||||
stream_new(s, MAX_PDU_SIZE);
|
||||
|
||||
stream_ins_u32_le(s, 0); /* number of bytes to follow */
|
||||
stream_ins_u32_le(s, CMD_SET_AUDIO_FORMAT);
|
||||
stream_ins_u32_le(s, stream_id);
|
||||
|
||||
/* insert number of bytes in stream */
|
||||
len = stream_length(s) - 4;
|
||||
cptr = s->p;
|
||||
s->p = s->data;
|
||||
stream_ins_u32_le(s, len);
|
||||
s->p = cptr;
|
||||
|
||||
/* write data to virtual channel */
|
||||
rv = xrdpvr_write_to_client(channel, s);
|
||||
stream_free(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* send video data to client
|
||||
*
|
||||
* @param channel opaque handle returned by WTSVirtualChannelOpenEx
|
||||
* @param stream_id unique identification number for this stream
|
||||
* @param data_len number of bytes to send
|
||||
* @param data video data to send
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*****************************************************************************/
|
||||
static int
|
||||
xrdpvr_send_video_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data)
|
||||
{
|
||||
STREAM *s;
|
||||
char *cptr;
|
||||
int rv;
|
||||
int len;
|
||||
|
||||
stream_new(s, MAX_PDU_SIZE + data_len);
|
||||
|
||||
stream_ins_u32_le(s, 0); /* number of bytes to follow */
|
||||
stream_ins_u32_le(s, CMD_SEND_VIDEO_DATA);
|
||||
stream_ins_u32_le(s, stream_id);
|
||||
stream_ins_u32_le(s, data_len);
|
||||
stream_ins_byte_array(s, data, data_len);
|
||||
|
||||
/* insert number of bytes in stream */
|
||||
len = stream_length(s) - 4;
|
||||
cptr = s->p;
|
||||
s->p = s->data;
|
||||
stream_ins_u32_le(s, len);
|
||||
s->p = cptr;
|
||||
|
||||
/* write data to virtual channel */
|
||||
rv = xrdpvr_write_to_client(channel, s);
|
||||
stream_free(s);
|
||||
|
||||
#ifdef DEBUG_FRAGMENTS
|
||||
printf("### sent %d + 4 bytes video data to client\n", len);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* send audio data to client
|
||||
*
|
||||
* @param channel opaque handle returned by WTSVirtualChannelOpenEx
|
||||
* @param stream_id unique identification number for this stream
|
||||
* @param data_len number of bytes to send
|
||||
* @param data audio data to send
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*****************************************************************************/
|
||||
static int
|
||||
xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data)
|
||||
{
|
||||
STREAM *s;
|
||||
char *cptr;
|
||||
int rv;
|
||||
int len;
|
||||
|
||||
stream_new(s, MAX_PDU_SIZE + data_len);
|
||||
|
||||
stream_ins_u32_le(s, 0); /* number of bytes to follow */
|
||||
stream_ins_u32_le(s, CMD_SEND_AUDIO_DATA);
|
||||
stream_ins_u32_le(s, stream_id);
|
||||
stream_ins_u32_le(s, data_len);
|
||||
stream_ins_byte_array(s, data, data_len);
|
||||
|
||||
/* insert number of bytes in stream */
|
||||
len = stream_length(s) - 4;
|
||||
cptr = s->p;
|
||||
s->p = s->data;
|
||||
stream_ins_u32_le(s, len);
|
||||
s->p = cptr;
|
||||
|
||||
/* write data to virtual channel */
|
||||
rv = xrdpvr_write_to_client(channel, s);
|
||||
stream_free(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* send media meta-data to client
|
||||
*
|
||||
* @param channel opaque handle returned by WTSVirtualChannelOpenEx
|
||||
* @param filename media file
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*****************************************************************************/
|
||||
static int
|
||||
xrdpvr_create_metadata_file(void *channel, char *filename)
|
||||
{
|
||||
STREAM *s;
|
||||
char *cptr;
|
||||
int rv;
|
||||
int len;
|
||||
int fd;
|
||||
|
||||
if ((fd = open(filename , O_RDONLY)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream_new(s, MAX_PDU_SIZE + 1048576);
|
||||
|
||||
/* send CMD_CREATE_META_DATA_FILE */
|
||||
stream_ins_u32_le(s, 4); /* number of bytes to follow */
|
||||
stream_ins_u32_le(s, CMD_CREATE_META_DATA_FILE);
|
||||
|
||||
if (xrdpvr_write_to_client(channel, s))
|
||||
{
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read first 1MB of file and send to client */
|
||||
s->p = s->data;
|
||||
stream_ins_u32_le(s, 0); /* number of bytes to follow */
|
||||
stream_ins_u32_le(s, CMD_WRITE_META_DATA);
|
||||
stream_ins_u32_le(s, 0); /* number of bytes to follow */
|
||||
|
||||
if ((rv = read(fd, s->p, 1048576)) <= 0)
|
||||
{
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->p += rv;
|
||||
|
||||
/* insert number of bytes in stream */
|
||||
len = stream_length(s) - 4;
|
||||
cptr = s->p;
|
||||
s->p = s->data;
|
||||
stream_ins_u32_le(s, len); /* number of bytes in this cmd */
|
||||
s->p += 4;
|
||||
stream_ins_u32_le(s, rv); /* number of metadata bytes */
|
||||
s->p = cptr;
|
||||
|
||||
/* write data to virtual channel */
|
||||
rv = xrdpvr_write_to_client(channel, s);
|
||||
|
||||
/* send CMD_CLOSE_META_DATA_FILE */
|
||||
s->p = s->data;
|
||||
stream_ins_u32_le(s, 4); /* number of bytes to follow */
|
||||
stream_ins_u32_le(s, CMD_CLOSE_META_DATA_FILE);
|
||||
|
||||
if (xrdpvr_write_to_client(channel, s))
|
||||
{
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream_free(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* write data to a xrdpvr client
|
||||
*
|
||||
* @param channel opaque handle returned by WTSVirtualChannelOpenEx
|
||||
* @param s structure containing data to write
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
******************************************************************************/
|
||||
static int
|
||||
xrdpvr_write_to_client(void *channel, STREAM *s)
|
||||
{
|
||||
int bytes_to_send;
|
||||
int bytes_written;
|
||||
int index = 0;
|
||||
int rv;
|
||||
|
||||
if ((channel == NULL) || (s == NULL))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes_to_send = stream_length(s);
|
||||
|
||||
while (1)
|
||||
{
|
||||
rv = WTSVirtualChannelWrite(channel, &s->data[index], bytes_to_send, &bytes_written);
|
||||
|
||||
if (rv < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
index += bytes_written;
|
||||
bytes_to_send -= bytes_written;
|
||||
|
||||
if ((rv == 0) && (bytes_to_send == 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
usleep(1000 * 3);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Laxmikant Rashinkar 2012 LK.Rashinkar@gmail.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* a program that uses xrdpapi and ffmpeg to redirect media streams
|
||||
* to a FreeRDP client where it is decompressed and played locally
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XRDPVR_H__
|
||||
#define __XRDPVR_H__
|
||||
|
||||
int xrdpvr_init_player(void *channel, int stream_id, char *filename);
|
||||
int xrdpvr_deinit_player(void *channel, int stream_id);
|
||||
int xrdpvr_play_media(void *channel, int stream_id, char *filename);
|
||||
|
||||
#endif /* __XRDPVR_H__ */
|
@ -0,0 +1,203 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Laxmikant Rashinkar 2012 LK.Rashinkar@gmail.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* a program that uses xrdpapi and ffmpeg to redirect media streams
|
||||
* to a FreeRDP client where it is decompressed and played locally
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XRDPVR_INTERNAL_H__
|
||||
#define __XRDPVR_INTERNAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
#define MAX_BUFSIZE (1024 * 1024 * 8)
|
||||
|
||||
#define CMD_SET_VIDEO_FORMAT 1
|
||||
#define CMD_SET_AUDIO_FORMAT 2
|
||||
#define CMD_SEND_VIDEO_DATA 3
|
||||
#define CMD_SEND_AUDIO_DATA 4
|
||||
#define CMD_CREATE_META_DATA_FILE 5
|
||||
#define CMD_CLOSE_META_DATA_FILE 6
|
||||
#define CMD_WRITE_META_DATA 7
|
||||
#define CMD_DEINIT_XRDPVR 8
|
||||
|
||||
/* max number of bytes we can send in one pkt */
|
||||
#define MAX_PDU_SIZE 1600
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
|
||||
typedef struct stream
|
||||
{
|
||||
u8 *data;
|
||||
u8 *p;
|
||||
u32 size;
|
||||
int from_buf;
|
||||
} STREAM;
|
||||
|
||||
/**
|
||||
* create and init a new stream
|
||||
*
|
||||
* @param _s stream to create and init
|
||||
* @param _len number of bytes to store in stream
|
||||
******************************************************************************/
|
||||
#define stream_new(_s, _len) \
|
||||
do \
|
||||
{ \
|
||||
(_s) = (STREAM *) calloc(1, sizeof(STREAM)); \
|
||||
(_s)->data = (u8 *) calloc(1, (_len)); \
|
||||
(_s)->p = (_s)->data; \
|
||||
(_s)->size = (_len); \
|
||||
(_s)->from_buf = 0; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* create a stream from an existing buffer
|
||||
******************************************************************************/
|
||||
#define stream_from_buffer(_s, _buf, _buf_len) \
|
||||
do \
|
||||
{ \
|
||||
(_s) = (STREAM *) calloc(1, sizeof(STREAM)); \
|
||||
(_s)->data = (u8 *) (_buf); \
|
||||
(_s)->p = (_s)->data; \
|
||||
(_s)->size = (_buf_len); \
|
||||
(_s)->from_buf = 1; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* release stream resources, including stream itself
|
||||
* note: release _s->data only if we allocated it
|
||||
*
|
||||
* @param _s the stream whose resources are to be released
|
||||
******************************************************************************/
|
||||
#define stream_free(_s) \
|
||||
do \
|
||||
{ \
|
||||
if (!(_s)->from_buf) \
|
||||
{ \
|
||||
free((_s)->data); \
|
||||
} \
|
||||
free((_s)); \
|
||||
(_s) = NULL; \
|
||||
} while (0)
|
||||
|
||||
/** return number of bytes in stream */
|
||||
#define stream_length(_s) (int) ((_s)->p - (_s)->data)
|
||||
|
||||
/** insert a 8 bit value into stream */
|
||||
#define stream_ins_u8(_s, _val) \
|
||||
do \
|
||||
{ \
|
||||
*(_s)->p++ = (unsigned char) (_val); \
|
||||
} while(0)
|
||||
|
||||
/** insert a 16 bit value into stream */
|
||||
#define stream_ins_u16_le(_s, _val) \
|
||||
do \
|
||||
{ \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 0); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 8); \
|
||||
} while (0)
|
||||
|
||||
/** insert a 32 bit value into stream */
|
||||
#define stream_ins_u32_le(_s, _val) \
|
||||
do \
|
||||
{ \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 0); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 8); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 16); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 24); \
|
||||
} while (0)
|
||||
|
||||
/** insert a 64 bit value into stream */
|
||||
#define stream_ins_u64_le(_s, _val) \
|
||||
do \
|
||||
{ \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 0); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 8); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 16); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 24); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 32); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 40); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 48); \
|
||||
*(_s)->p++ = (unsigned char) ((_val) >> 56); \
|
||||
} while (0)
|
||||
|
||||
/** insert array of chars into stream */
|
||||
#define stream_ins_byte_array(_s, _ba, _count) \
|
||||
do \
|
||||
{ \
|
||||
memcpy((_s)->p, (_ba), (_count)); \
|
||||
(_s)->p += (_count); \
|
||||
} while (0)
|
||||
|
||||
/** extract a 8 bit value from stream */
|
||||
#define stream_ext_u8(_s, _v) \
|
||||
do \
|
||||
{ \
|
||||
(_v) = (u8) *(_s)->p++; \
|
||||
} while (0)
|
||||
|
||||
/** extract a 16 bit value from stream */
|
||||
#define stream_ext_u16_le(_s, _v) \
|
||||
do \
|
||||
{ \
|
||||
(_v) = (u16) ((_s)->p[1] << 8 | (_s)->p[0]); \
|
||||
(_s)->p += 2; \
|
||||
} while (0)
|
||||
|
||||
/** extract a 32 bit value from stream */
|
||||
#define stream_ext_u32_le(_s, _v) \
|
||||
do \
|
||||
{ \
|
||||
(_v) = (u32) ((_s)->p[3] << 24 | \
|
||||
(_s)->p[2] << 16 | \
|
||||
(_s)->p[1] << 8 | \
|
||||
(_s)->p[0]); \
|
||||
(_s)->p += 4; \
|
||||
} while (0)
|
||||
|
||||
typedef struct _player_state_info
|
||||
{
|
||||
AVFormatContext *p_format_ctx;
|
||||
AVCodecContext *p_audio_codec_ctx;
|
||||
AVCodecContext *p_video_codec_ctx;
|
||||
AVCodec *p_audio_codec;
|
||||
AVCodec *p_video_codec;
|
||||
|
||||
int audio_stream_index;
|
||||
int video_stream_index;
|
||||
|
||||
/* LK_TODO delete this after we fix the problem */
|
||||
AVFrame *frame;
|
||||
AVPacket avpkt;
|
||||
|
||||
} PLAYER_STATE_INFO;
|
||||
|
||||
static int xrdpvr_set_video_format(void *channel, uint32_t stream_id);
|
||||
static int xrdpvr_set_audio_format(void *channel, uint32_t stream_id);
|
||||
static int xrdpvr_send_video_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data);
|
||||
static int xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data);
|
||||
static int xrdpvr_create_metadata_file(void *channel, char *filename);
|
||||
static int xrdpvr_write_to_client(void *channel, STREAM *s);
|
||||
|
||||
#endif /* __XRDPVR_INTERNAL_H__ */
|
Loading…
Reference in new issue