Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/neutrinolabs/NeutrinoRDP.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJay Sorg <jay.sorg@gmail.com>2016-09-16 09:16:08 +0300
committerJay Sorg <jay.sorg@gmail.com>2016-09-16 09:16:08 +0300
commit70ddb961100ce4ffd4fae86e653b5cbd5d8f1f6e (patch)
tree1eef5e136a38ae84c91ab30c30e9603257139238
parenteee121bccd3c46782095dc03bdc95b14a2530d90 (diff)
test work on aac audio codec
-rw-r--r--channels/rdpsnd/pulse/rdpsnd_pulse.c114
-rw-r--r--channels/rdpsnd/rdpsnd_main.c6
-rw-r--r--client/X11/xfreerdp.c4
-rw-r--r--include/freerdp/utils/nrdp_avcodec.h54
-rw-r--r--libfreerdp-utils/CMakeLists.txt5
-rw-r--r--libfreerdp-utils/nrdp_avcodec.c719
6 files changed, 898 insertions, 4 deletions
diff --git a/channels/rdpsnd/pulse/rdpsnd_pulse.c b/channels/rdpsnd/pulse/rdpsnd_pulse.c
index 0610907..573ca86 100644
--- a/channels/rdpsnd/pulse/rdpsnd_pulse.c
+++ b/channels/rdpsnd/pulse/rdpsnd_pulse.c
@@ -26,6 +26,8 @@
#include <freerdp/utils/dsp.h>
#include <freerdp/utils/svc_plugin.h>
+#include <freerdp/utils/nrdp_avcodec.h>
+
#include "rdpsnd_main.h"
typedef void (*SourceDataAvailable) (void* user_data, void* buf, int buf_len);
@@ -60,6 +62,8 @@ struct rdpsnd_pulse_plugin
int rec_block_size;
int rec_bytes_per_frame;
uint32 rec_frames_per_packet;
+
+ void* aac_handle;
};
static int rdpsnd_pulse_rec_close(rdpsndDevicePlugin* device);
@@ -427,8 +431,33 @@ static tbool rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndFor
if (!pulse->context)
return false;
+ //printf("format->wFormatTag %x\n", format->wFormatTag);
switch (format->wFormatTag)
{
+
+ case 41222: /* AAC */
+ freerdp_hexdump(format, sizeof(rdpsndFormat));
+ printf("cbSize %d\n", format->cbSize);
+ printf("nAvgBytesPerSec %d\n", format->nAvgBytesPerSec);
+ printf("nChannels %d\n", format->nChannels);
+ printf("nSamplesPerSec %d\n", format->nSamplesPerSec);
+ if (format->nChannels == 2)
+ {
+ if (format->nSamplesPerSec == 44100)
+ {
+ if (format->nAvgBytesPerSec == 12000)
+ //if (format->nAvgBytesPerSec == 16000)
+ //if (format->nAvgBytesPerSec == 20000)
+ //if (format->nAvgBytesPerSec == 24000)
+ {
+ printf("good\n");
+ return true;
+ }
+ }
+ }
+ printf("not good\n");
+ return false;
+
case 1: /* PCM */
if (format->cbSize == 0 &&
(format->nSamplesPerSec <= PA_RATE_MAX) &&
@@ -438,7 +467,7 @@ static tbool rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndFor
return true;
}
break;
-
+#if 0
case 6: /* A-LAW */
case 7: /* U-LAW */
if (format->cbSize == 0 &&
@@ -458,6 +487,10 @@ static tbool rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndFor
return true;
}
break;
+#endif
+ default:
+ //printf("unknown format format->wFormatTag %x\n", format->wFormatTag);
+ break;
}
return false;
}
@@ -481,6 +514,10 @@ static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, uint32 value)
{
}
+//#include <fcntl.h>
+//#include <sys/stat.h>
+//#include <unistd.h>
+
static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, uint8* data, int size)
{
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device;
@@ -490,6 +527,7 @@ static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, uint8* data, int size)
uint8* src;
int decoded_size;
+ printf("rdpsnd_pulse_play: format %d\n", pulse->format);
if (!pulse->stream)
return;
@@ -500,6 +538,80 @@ static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, uint8* data, int size)
size = decoded_size;
src = decoded_data;
}
+ if (pulse->format == 41222)
+ {
+ int cdata_bytes_processed;
+ int decoded;
+ int channels;
+ int format;
+ int bytes;
+ int error;
+
+ printf("rdpsnd_pulse_play: acc data size %d\n", size);
+
+ decoded_data = NULL;
+ src = data;
+
+ if (pulse->aac_handle == NULL)
+ {
+ error = nrdp_avcodec_audio_create(&(pulse->aac_handle), AUDIO_CODEC_ID_AAC);
+ if (error != 0)
+ {
+ printf("rdpsnd_pulse_play: nrdp_avcodec_audio_create failed, error %d\n", error);
+ return;
+ }
+ }
+
+ error = nrdp_avcodec_audio_decode(pulse->aac_handle, data, size, &cdata_bytes_processed, &decoded);
+ if (error == 0)
+ {
+ printf("ok cdata_bytes_processed %d decoded %d\n", cdata_bytes_processed, decoded);
+ }
+ else
+ {
+ printf("not ok\n");
+ return;
+ }
+
+ if (decoded)
+ {
+ error = nrdp_avcodec_audio_get_frame_info(pulse->aac_handle, &channels, &format, &bytes);
+ if (error == 0)
+ {
+ printf("ok channels %d format %d bytes %d\n", channels, format, bytes);
+ decoded_data = (uint8*)xzalloc(bytes);
+ error = nrdp_avcodec_audio_get_frame_data(pulse->aac_handle, decoded_data, bytes);
+ if (error == 0)
+ {
+ printf("ok nrdp_avcodec_audio_get_frame_data\n");
+ }
+ else
+ {
+ printf("not ok nrdp_avcodec_audio_get_frame_data\n");
+ return;
+ }
+ size = bytes / 2;
+ src = decoded_data;
+ }
+ else
+ {
+ printf("not ok\n");
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ //int fd;
+ //fd = open("/tmp/audio.aac", O_RDWR | O_CREAT, 0666);
+ //lseek(fd, 0, SEEK_END);
+ //write(fd, data, size);
+ //close(fd);
+ //return;
+
+ }
else
{
decoded_data = NULL;
diff --git a/channels/rdpsnd/rdpsnd_main.c b/channels/rdpsnd/rdpsnd_main.c
index 81af317..8bb05fc 100644
--- a/channels/rdpsnd/rdpsnd_main.c
+++ b/channels/rdpsnd/rdpsnd_main.c
@@ -271,7 +271,7 @@ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in
stream_read_uint16(data_in, format->wFormatTag);
stream_read_uint16(data_in, format->nChannels);
stream_read_uint32(data_in, format->nSamplesPerSec);
- stream_seek_uint32(data_in); /* nAvgBytesPerSec */
+ stream_read_uint32(data_in, format->nAvgBytesPerSec);
stream_read_uint16(data_in, format->nBlockAlign);
stream_read_uint16(data_in, format->wBitsPerSample);
stream_read_uint16(data_in, format->cbSize);
@@ -283,6 +283,10 @@ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in
format->wFormatTag, format->nChannels, format->nSamplesPerSec,
format->nBlockAlign, format->wBitsPerSample);
+ printf("wFormatTag=%d nChannels=%d nSamplesPerSec=%d nBlockAlign=%d wBitsPerSample=%d\n",
+ format->wFormatTag, format->nChannels, format->nSamplesPerSec,
+ format->nBlockAlign, format->wBitsPerSample);
+
if (rdpsnd->fixed_format > 0 && rdpsnd->fixed_format != format->wFormatTag)
continue;
if (rdpsnd->fixed_channel > 0 && rdpsnd->fixed_channel != format->nChannels)
diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c
index df28cb6..2ce99e7 100644
--- a/client/X11/xfreerdp.c
+++ b/client/X11/xfreerdp.c
@@ -55,6 +55,8 @@
#include <freerdp/plugins/cliprdr.h>
#include <freerdp/rail.h>
+#include <freerdp/utils/nrdp_avcodec.h>
+
#include "xf_gdi.h"
#include "xf_rail.h"
#include "xf_tsmf.h"
@@ -1128,6 +1130,8 @@ int main(int argc, char* argv[])
setlocale(LC_ALL, "");
+ nrdp_avcodec_init();
+
freerdp_channels_global_init();
g_sem = freerdp_sem_new(1);
diff --git a/include/freerdp/utils/nrdp_avcodec.h b/include/freerdp/utils/nrdp_avcodec.h
new file mode 100644
index 0000000..7e01fe2
--- /dev/null
+++ b/include/freerdp/utils/nrdp_avcodec.h
@@ -0,0 +1,54 @@
+/**
+ * avcodec / ffmpeg calls
+ *
+ * Copyright 2015-2016 Jay Sorg <jay.sorg@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.
+ */
+
+#ifndef _NRDP_AVCODEC_H_
+#define _NRDP_AVCODEC_H_
+
+#define AUDIO_CODEC_ID_AC3 0
+#define AUDIO_CODEC_ID_AAC 1
+
+#define VIDEO_CODEC_ID_MPEG2 0
+
+int
+nrdp_avcodec_init(void);
+int
+nrdp_avcodec_audio_create(void** obj, int codec_id);
+int
+nrdp_avcodec_audio_decode(void* obj, void* cdata, int cdata_bytes,
+ int* cdata_bytes_processed, int* decoded);
+int
+nrdp_avcodec_audio_get_frame_info(void* obj, int* channels, int* format,
+ int* bytes);
+int
+nrdp_avcodec_audio_get_frame_data(void* obj, void* data, int data_bytes);
+
+int
+nrdp_avcodec_video_create(void** obj, int codec_id);
+int
+nrdp_avcodec_video_delete(void* obj);
+int
+nrdp_avcodec_video_decode(void* obj, void* cdata, int cdata_bytes,
+ int* cdata_bytes_processed, int* decoded);
+int
+nrdp_avcodec_video_get_frame_info(void* obj, int* width, int* height,
+ int* format, int* bytes);
+int
+nrdp_avcodec_video_get_frame_data(void* obj, void* data, int data_bytes);
+
+#endif
+
diff --git a/libfreerdp-utils/CMakeLists.txt b/libfreerdp-utils/CMakeLists.txt
index bf5e12d..652b6de 100644
--- a/libfreerdp-utils/CMakeLists.txt
+++ b/libfreerdp-utils/CMakeLists.txt
@@ -48,7 +48,8 @@ set(FREERDP_UTILS_SRCS
thread.c
unicode.c
wait_obj.c
- git_ref.h)
+ git_ref.h
+ nrdp_avcodec.c)
if(WIN32)
else()
@@ -62,7 +63,7 @@ add_library(freerdp-utils ${FREERDP_UTILS_SRCS})
set_target_properties(freerdp-utils PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib")
-target_link_libraries(freerdp-utils ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})
+target_link_libraries(freerdp-utils ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} ${FFMPEG_LIBRARIES})
if(WIN32)
target_link_libraries(freerdp-utils ws2_32)
diff --git a/libfreerdp-utils/nrdp_avcodec.c b/libfreerdp-utils/nrdp_avcodec.c
new file mode 100644
index 0000000..0646597
--- /dev/null
+++ b/libfreerdp-utils/nrdp_avcodec.c
@@ -0,0 +1,719 @@
+/**
+ * avcodec / ffmpeg calls
+ *
+ * Copyright 2015-2016 Jay Sorg <jay.sorg@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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libavcodec/avcodec.h>
+#include <libavutil/mem.h>
+
+#include <freerdp/utils/nrdp_avcodec.h>
+
+#ifndef LIBAVCODEC_VERSION_MAJOR
+#warning LIBAVCODEC_VERSION_MAJOR not defined
+#endif
+
+#define LLOG_LEVEL 1
+#define LLOGLN(_level, _args) \
+ do \
+ { \
+ if (_level < LLOG_LEVEL) \
+ { \
+ printf _args ; \
+ printf("\n"); \
+ } \
+ } \
+ while (0)
+
+// LIBAVCODEC_VERSION_MAJOR 52 LIBAVCODEC_VERSION_MINOR 20 ubuntu 10.04
+// LIBAVCODEC_VERSION_MAJOR 52 LIBAVCODEC_VERSION_MINOR 20 debian 6
+// LIBAVCODEC_VERSION_MAJOR 53 LIBAVCODEC_VERSION_MINOR 35 ubuntu 12.04
+// LIBAVCODEC_VERSION_MAJOR 53 LIBAVCODEC_VERSION_MINOR 35 debian 7
+// LIBAVCODEC_VERSION_MAJOR 54 LIBAVCODEC_VERSION_MINOR 35 ubuntu 14.04
+// LIBAVCODEC_VERSION_MAJOR 56 LIBAVCODEC_VERSION_MINOR 1 debian 8
+// LIBAVCODEC_VERSION_MAJOR 56 LIBAVCODEC_VERSION_MINOR 60 ubuntu 16.04
+// LIBAVCODEC_VERSION_MAJOR 56 LIBAVCODEC_VERSION_MINOR 60 FreeBSD(PCBSD10.1.2-05-22-2015)
+
+//example
+//#if (LIBAVCODEC_VERSION_INT <= ((51<<16) + (28<<8) + 0))
+// len = avcodec_decode_audio(cc, (int16_t *)output->buffer, &frame_size,
+// input->curr_pkt_buf, input->curr_pkt_size);
+//#else
+// /* The change to avcodec_decode_audio3 occurred between
+// * 52.25.0 and 52.26.0 */
+//#elif (LIBAVCODEC_VERSION_INT <= ((52<<16) + (25<<8) + 0))
+// len = avcodec_decode_audio2(cc, (int16_t *) output->buffer, &frame_size,
+// input->curr_pkt_buf, input->curr_pkt_size);
+//#else
+// AVPacket avpkt;
+// av_init_packet(&avpkt);
+// avpkt.data = input->curr_pkt_buf;
+// avpkt.size = input->curr_pkt_size;
+// len = avcodec_decode_audio3(cc, (int16_t *) output->buffer, &frame_size, &avpkt);
+// av_free_packet(&avpkt);
+
+#if LIBAVCODEC_VERSION_MAJOR > 55
+#define CODEC_ID_AC3 AV_CODEC_ID_AC3
+#define CODEC_ID_AAC AV_CODEC_ID_AAC
+#define CODEC_ID_MPEG2VIDEO AV_CODEC_ID_MPEG2VIDEO
+#define AVCODEC_ALLOC_FRAME av_frame_alloc
+#define AVCODEC_FREE_FRAME(_frame) av_frame_free(_frame);
+#else
+#define AVCODEC_ALLOC_FRAME avcodec_alloc_frame
+#define AVCODEC_FREE_FRAME(_frame) av_free(*(_frame));
+#endif
+
+#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
+#define AVCODEC_ALLOC_CONTEXT avcodec_alloc_context()
+#else
+#define AVCODEC_ALLOC_CONTEXT avcodec_alloc_context3(NULL)
+#endif
+
+#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
+#define AVCODEC_OPEN(_context, _codec) avcodec_open(_context, _codec)
+#else
+#define AVCODEC_OPEN(_context, _codec) avcodec_open2(_context, _codec, NULL)
+#endif
+
+struct avcodec_audio
+{
+ AVCodecContext* codec_context;
+ AVCodec* codec;
+ AVFrame* frame;
+ short* dst;
+ int dst_bytes;
+ int pad0;
+};
+
+struct avcodec_video
+{
+ AVCodecContext* codec_context;
+ AVCodec* codec;
+ AVFrame* frame;
+};
+
+/*****************************************************************************/
+int
+nrdp_avcodec_init(void)
+{
+ avcodec_register_all();
+ return 0;
+}
+
+/*****************************************************************************/
+int
+nrdp_avcodec_audio_create(void** obj, int codec_id)
+{
+ struct avcodec_audio* self;
+ int error;
+ int avcodec_id;
+
+ if (obj == NULL)
+ {
+ return 1;
+ }
+ avcodec_id = 0;
+ switch (codec_id)
+ {
+ case AUDIO_CODEC_ID_AC3:
+ avcodec_id = CODEC_ID_AC3;
+ break;
+ case AUDIO_CODEC_ID_AAC:
+ avcodec_id = CODEC_ID_AAC;
+ //avcodec_id = CODEC_ID_AAC_LATM;
+ break;
+ default:
+ return 6;
+ }
+ self = (struct avcodec_audio*)malloc(sizeof(struct avcodec_audio));
+ if (self == NULL)
+ {
+ return 2;
+ }
+ memset(self, 0, sizeof(struct avcodec_audio));
+ self->codec_context = AVCODEC_ALLOC_CONTEXT;
+ if (self->codec_context == NULL)
+ {
+ free(self);
+ return 3;
+ }
+ self->codec = avcodec_find_decoder(avcodec_id);
+ if (self->codec == NULL)
+ {
+ avcodec_close(self->codec_context);
+ free(self);
+ return 4;
+ }
+
+ self->codec_context->channels = 2;
+ self->codec_context->bit_rate = 12000 * 8;
+ self->codec_context->sample_rate = 44100;
+ //self->codec_context->sample_rate = 48000;
+ self->codec_context->bits_per_raw_sample = 16;
+ self->codec_context->block_align = 4;
+
+ self->codec_context->profile = FF_PROFILE_AAC_LOW;
+
+ //self->codec_context-> AV_SAMPLE_FMT_S16
+
+ if (0)
+ {
+ unsigned short* ptr16;
+ self->codec_context->extradata_size = 12 + 8;
+ self->codec_context->extradata = calloc(1, self->codec_context->extradata_size);
+ ptr16 = (unsigned short*)(self->codec_context->extradata);
+ ptr16[0] = 0;
+ ptr16[1] = 0xFE;
+ ptr16[2] = 0;
+ }
+
+ error = AVCODEC_OPEN(self->codec_context, self->codec);
+ if (error != 0)
+ {
+ avcodec_close(self->codec_context);
+ free(self);
+ return 5;
+ }
+ self->frame = AVCODEC_ALLOC_FRAME();
+ *obj = self;
+ return 0;
+}
+
+/*****************************************************************************/
+int
+nrdp_avcodec_audio_delete(void* obj)
+{
+ struct avcodec_audio* self;
+
+ self = (struct avcodec_audio*)obj;
+ if (self == NULL)
+ {
+ return 0;
+ }
+ avcodec_close(self->codec_context);
+ AVCODEC_FREE_FRAME(&(self->frame));
+ free(self);
+ return 0;
+}
+
+#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
+/* debian 6 */
+
+/*****************************************************************************/
+int
+nrdp_avcodec_audio_decode(void* obj, void* cdata, int cdata_bytes,
+ int* cdata_bytes_processed, int* decoded)
+{
+ struct avcodec_audio* self;
+ int len;
+ int bytes_processed;
+ unsigned char* src;
+ int src_size;
+
+ self = (struct avcodec_audio*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ *cdata_bytes_processed = 0;
+ *decoded = 0;
+ bytes_processed = 0;
+ src = cdata;
+ src_size = cdata_bytes;
+ while (src_size > 0)
+ {
+ self->dst_bytes = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ free(self->dst);
+ self->dst = (short*) malloc(self->dst_bytes);
+ len = avcodec_decode_audio2(self->codec_context,
+ self->dst, &(self->dst_bytes),
+ src, src_size);
+ *decoded = self->dst_bytes > 0;
+ if (len < 0)
+ {
+ return 1;
+ }
+ src_size -= len;
+ src += len;
+ bytes_processed += len;
+ if (*decoded)
+ {
+ *cdata_bytes_processed = bytes_processed;
+ return 0;
+ }
+ }
+ *cdata_bytes_processed = bytes_processed;
+ return 0;
+}
+
+/*****************************************************************************/
+int
+nrdp_avcodec_audio_get_frame_info(void* obj, int* channels, int* format,
+ int* bytes)
+{
+ struct avcodec_audio* self;
+
+ self = (struct avcodec_audio*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ *channels = self->codec_context->channels;
+ *format = 1; /* AV_SAMPLE_FMT_S16 */
+ *bytes = self->dst_bytes;
+ return 0;
+}
+
+/*****************************************************************************/
+int
+nrdp_avcodec_audio_get_frame_data(void* obj, void* data, int data_bytes)
+{
+ struct avcodec_audio* self;
+
+ self = (struct avcodec_audio*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ memcpy(data, self->dst, data_bytes);
+ return 0;
+}
+
+#else
+
+/*****************************************************************************/
+int
+nrdp_avcodec_audio_decode(void* obj, void* cdata, int cdata_bytes,
+ int* cdata_bytes_processed, int* decoded)
+{
+ struct avcodec_audio* self;
+ AVPacket pkt;
+ int len;
+ int bytes_processed;
+
+ self = (struct avcodec_audio*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ *cdata_bytes_processed = 0;
+ *decoded = 0;
+ bytes_processed = 0;
+ av_init_packet(&pkt);
+ pkt.data = cdata;
+ pkt.size = cdata_bytes;
+ while (pkt.size > 0)
+ {
+ len = avcodec_decode_audio4(self->codec_context,
+ self->frame,
+ decoded, &pkt);
+ if (len < 0)
+ {
+ av_free_packet(&pkt);
+ return 1;
+ }
+ pkt.size -= len;
+ pkt.data += len;
+ bytes_processed += len;
+ if (*decoded)
+ {
+ *cdata_bytes_processed = bytes_processed;
+ av_free_packet(&pkt);
+ return 0;
+ }
+ }
+ *cdata_bytes_processed = bytes_processed;
+ av_free_packet(&pkt);
+ return 0;
+}
+
+/*****************************************************************************/
+int
+nrdp_avcodec_audio_get_frame_info(void* obj, int* channels, int* format,
+ int* bytes)
+{
+ struct avcodec_audio* self;
+ int frame_size;
+
+ self = (struct avcodec_audio*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ if ((self->frame->format != AV_SAMPLE_FMT_S16) &&
+ (self->frame->format != AV_SAMPLE_FMT_FLTP))
+ {
+ return 2;
+ }
+ frame_size = av_samples_get_buffer_size(NULL,
+ self->codec_context->channels,
+ self->frame->nb_samples,
+ AV_SAMPLE_FMT_S16,
+ 1);
+ *channels = self->codec_context->channels;
+ *format = AV_SAMPLE_FMT_S16;
+ *bytes = frame_size;
+ return 0;
+}
+
+/*****************************************************************************/
+int
+nrdp_avcodec_audio_get_frame_data(void* obj, void* data, int data_bytes)
+{
+ struct avcodec_audio* self;
+
+ self = (struct avcodec_audio*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ if (self->frame->format == AV_SAMPLE_FMT_S16)
+ {
+#if 0
+ int index;
+ int* src32;
+ short* src16;
+ short* dst16;
+
+ src32 = (int*)(self->frame->data[0]);
+ src16 = (short*)(self->frame->data[0]);
+ dst16 = (short*)data;
+ for (index = 0; index < data_bytes / 2; index++)
+ {
+ //dst16[index] = src32[index] >> 16;
+ dst16[index] = src16[index * 2];
+ }
+#endif
+ memcpy(data, self->frame->data[0], data_bytes);
+ freerdp_hexdump(self->frame->data[0], 64);
+// //printf("hi %d\n", frame->);
+#if 0
+ float* src[8];
+ short* dst;
+ int index;
+
+ src[0] = (float*)(self->frame->data[0]);
+ //src[1] = (float*)(self->frame->data[1]);
+ dst = (short*)data;
+
+ for (index = 0; index < self->frame->nb_samples; index++)
+ {
+ if (data_bytes < 4) /* 2 shorts */
+ {
+ break;
+ }
+ dst[0] = src[0][index] * 32768;
+ //dst[1] = src[1][index] * 32768;
+ dst += 2;
+ data_bytes -= 4; /* 2 shorts */
+ }
+#endif
+ }
+ else if (self->frame->format == AV_SAMPLE_FMT_FLTP)
+ {
+ /* convert float to sint16 */
+#if LIBAVCODEC_VERSION_MAJOR > 53
+ float* src[8];
+ short* dst;
+ int index;
+
+ src[0] = (float*)(self->frame->data[0]);
+ src[1] = (float*)(self->frame->data[1]);
+ src[2] = (float*)(self->frame->data[2]);
+ src[3] = (float*)(self->frame->data[3]);
+ src[4] = (float*)(self->frame->data[4]);
+ src[5] = (float*)(self->frame->data[5]);
+ dst = (short*)data;
+ if (self->codec_context->channels == 6)
+ {
+ for (index = 0; index < self->frame->nb_samples; index++)
+ {
+ if (data_bytes < 12) /* 6 shorts */
+ {
+ break;
+ }
+ dst[0] = src[0][index] * 32768;
+ dst[1] = src[1][index] * 32768;
+ dst[2] = src[2][index] * 32768;
+ dst[3] = src[3][index] * 32768;
+ dst[4] = src[4][index] * 32768;
+ dst[5] = src[5][index] * 32768;
+ dst += 6;
+ data_bytes -= 12; /* 6 shorts */
+ }
+ }
+ else if (self->codec_context->channels == 2)
+ {
+ for (index = 0; index < self->frame->nb_samples; index++)
+ {
+ if (data_bytes < 4) /* 2 shorts */
+ {
+ break;
+ }
+ dst[0] = src[0][index] * 32768;
+ dst[1] = src[1][index] * 32768;
+ dst += 2;
+ data_bytes -= 4; /* 2 shorts */
+ }
+ }
+ else if (self->codec_context->channels == 1)
+ {
+ for (index = 0; index < self->frame->nb_samples; index++)
+ {
+ if (data_bytes < 2) /* 1 short */
+ {
+ break;
+ }
+ dst[0] = src[0][index] * 32768;
+ dst += 1;
+ data_bytes -= 2; /* 1 short */
+ }
+ }
+ else
+ {
+ return 1;
+ }
+#else
+ /* self->frame->data only has 4 elements */
+ return 1;
+#endif
+ }
+ else
+ {
+ return 1;
+ }
+ return 0;
+}
+
+#endif
+
+/*****************************************************************************/
+int
+nrdp_avcodec_video_create(void** obj, int codec_id)
+{
+ struct avcodec_video* self;
+ int error;
+ int avcodec_id;
+
+ if (obj == NULL)
+ {
+ return 1;
+ }
+ avcodec_id = 0;
+ switch (codec_id)
+ {
+ case VIDEO_CODEC_ID_MPEG2:
+ avcodec_id = CODEC_ID_MPEG2VIDEO;
+ break;
+ default:
+ return 6;
+ }
+ self = (struct avcodec_video*)malloc(sizeof(struct avcodec_video));
+ if (self == NULL)
+ {
+ return 2;
+ }
+ memset(self, 0, sizeof(struct avcodec_video));
+ self->codec_context = AVCODEC_ALLOC_CONTEXT;
+ if (self->codec_context == NULL)
+ {
+ free(self);
+ return 3;
+ }
+ self->codec = avcodec_find_decoder(avcodec_id);
+ if (self->codec == NULL)
+ {
+ avcodec_close(self->codec_context);
+ free(self);
+ return 4;
+ }
+ error = AVCODEC_OPEN(self->codec_context, self->codec);
+ if (error != 0)
+ {
+ avcodec_close(self->codec_context);
+ free(self);
+ return 5;
+ }
+ self->frame = AVCODEC_ALLOC_FRAME();
+ *obj = self;
+ return 0;
+}
+
+/*****************************************************************************/
+int
+nrdp_avcodec_video_delete(void* obj)
+{
+ struct avcodec_video* self;
+
+ self = (struct avcodec_video*)obj;
+ if (self == NULL)
+ {
+ return 0;
+ }
+ avcodec_close(self->codec_context);
+ AVCODEC_FREE_FRAME(&(self->frame));
+ free(self);
+ return 0;
+}
+
+#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
+/* debian 6 */
+
+/*****************************************************************************/
+int
+nrdp_avcodec_video_decode(void* obj, void* cdata, int cdata_bytes,
+ int* cdata_bytes_processed, int* decoded)
+{
+ struct avcodec_video* self;
+ int len;
+ int bytes_processed;
+ unsigned char* src;
+ int src_size;
+
+ self = (struct avcodec_video*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ *cdata_bytes_processed = 0;
+ *decoded = 0;
+ bytes_processed = 0;
+ src = cdata;
+ src_size = cdata_bytes;
+ while (src_size > 0)
+ {
+ len = avcodec_decode_video(self->codec_context,
+ self->frame,
+ decoded, src, src_size);
+ if (len < 0)
+ {
+ return 1;
+ }
+ src_size -= len;
+ src += len;
+ bytes_processed += len;
+ if (*decoded)
+ {
+ *cdata_bytes_processed = bytes_processed;
+ return 0;
+ }
+ }
+ *cdata_bytes_processed = bytes_processed;
+ return 0;
+}
+
+#else
+
+/*****************************************************************************/
+int
+nrdp_avcodec_video_decode(void* obj, void* cdata, int cdata_bytes,
+ int* cdata_bytes_processed, int* decoded)
+{
+ struct avcodec_video* self;
+ AVPacket pkt;
+ int len;
+ int bytes_processed;
+
+ self = (struct avcodec_video*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ *cdata_bytes_processed = 0;
+ *decoded = 0;
+ bytes_processed = 0;
+ av_init_packet(&pkt);
+ pkt.data = cdata;
+ pkt.size = cdata_bytes;
+ while (pkt.size > 0)
+ {
+ len = avcodec_decode_video2(self->codec_context,
+ self->frame,
+ decoded, &pkt);
+ if (len < 0)
+ {
+ av_free_packet(&pkt);
+ return 1;
+ }
+ pkt.size -= len;
+ pkt.data += len;
+ bytes_processed += len;
+ if (*decoded)
+ {
+ *cdata_bytes_processed = bytes_processed;
+ av_free_packet(&pkt);
+ return 0;
+ }
+ }
+ *cdata_bytes_processed = bytes_processed;
+ av_free_packet(&pkt);
+ return 0;
+}
+
+#endif
+
+/*****************************************************************************/
+int
+nrdp_avcodec_video_get_frame_info(void* obj, int* width, int* height,
+ int* format, int* bytes)
+{
+ struct avcodec_video* self;
+ int frame_size;
+
+ self = (struct avcodec_video*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ frame_size = avpicture_get_size(PIX_FMT_YUV420P,
+ self->codec_context->width,
+ self->codec_context->height);
+ *width = self->codec_context->width;
+ *height = self->codec_context->height;
+ *format = PIX_FMT_YUV420P; /* 0 */
+ *bytes = frame_size;
+ return 0;
+}
+
+/*****************************************************************************/
+int
+nrdp_avcodec_video_get_frame_data(void* obj, void* data, int data_bytes)
+{
+ struct avcodec_video* self;
+ AVFrame* frame;
+
+ self = (struct avcodec_video*)obj;
+ if (self == NULL)
+ {
+ return 1;
+ }
+ frame = AVCODEC_ALLOC_FRAME();
+ avpicture_fill((AVPicture*)frame, data,
+ PIX_FMT_YUV420P,
+ self->codec_context->width,
+ self->codec_context->height);
+ av_picture_copy((AVPicture*)frame,
+ (AVPicture*)(self->frame),
+ PIX_FMT_YUV420P,
+ self->codec_context->width,
+ self->codec_context->height);
+ AVCODEC_FREE_FRAME(&frame);
+ return 0;
+}
+