~ubuntu-branches/ubuntu/raring/freerdp/raring-proposed

« back to all changes in this revision

Viewing changes to channels/drdynvc/tsmf/tsmf_media.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Jeremy Bicha, Jean-Louis Dupond, Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120131100214-jaok3uwvni7sqxth
Tags: 1.0.0-0git1
Upload current Debian packaging git to get this rolling for precise.

[ Jeremy Bicha ]
* New upstream release. Closes: #647498.
* Updated symbols and bumped soname
* debian/control:
  - Added new build dependencies
  - Bump Standards-Version to 3.9.2
* debian/source/format: Set to 3.0 (quilt)
* debian/rules: Turn on strict symbols checking
* debian/watch: Watch github

[ Jean-Louis Dupond ]
* debian/control: Updated homepage
* debian/copyright: Reflect upstream switch to the Apache license

[ Martin Pitt ]
* debian/libfreerdp0.symbols: Fix version number, should
  be 1.0~beta5, not 1.0-beta5.
* debian/control: Add libavcodec-dev build dependency, upstream build system
  checks for that. Thanks Jean-Louis Dupond!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * FreeRDP: A Remote Desktop Protocol client.
 
3
 * Video Redirection Virtual Channel - Media Container
 
4
 *
 
5
 * Copyright 2010-2011 Vic Lee
 
6
 *
 
7
 * Licensed under the Apache License, Version 2.0 (the "License");
 
8
 * you may not use this file except in compliance with the License.
 
9
 * You may obtain a copy of the License at
 
10
 *
 
11
 *     http://www.apache.org/licenses/LICENSE-2.0
 
12
 *
 
13
 * Unless required by applicable law or agreed to in writing, software
 
14
 * distributed under the License is distributed on an "AS IS" BASIS,
 
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
16
 * See the License for the specific language governing permissions and
 
17
 * limitations under the License.
 
18
 */
 
19
 
 
20
#include <stdio.h>
 
21
#include <stdlib.h>
 
22
#include <string.h>
 
23
#include <sys/time.h>
 
24
#include <freerdp/utils/memory.h>
 
25
#include <freerdp/utils/stream.h>
 
26
#include <freerdp/utils/list.h>
 
27
#include <freerdp/utils/thread.h>
 
28
#include <freerdp/utils/mutex.h>
 
29
#include <freerdp/utils/event.h>
 
30
#include <freerdp/utils/sleep.h>
 
31
#include <freerdp/plugins/tsmf.h>
 
32
 
 
33
#include "drdynvc_types.h"
 
34
#include "tsmf_constants.h"
 
35
#include "tsmf_types.h"
 
36
#include "tsmf_decoder.h"
 
37
#include "tsmf_audio.h"
 
38
#include "tsmf_main.h"
 
39
#include "tsmf_codec.h"
 
40
#include "tsmf_media.h"
 
41
 
 
42
#define AUDIO_TOLERANCE 10000000LL
 
43
 
 
44
struct _TSMF_PRESENTATION
 
45
{
 
46
        uint8 presentation_id[GUID_SIZE];
 
47
 
 
48
        const char* audio_name;
 
49
        const char* audio_device;
 
50
        int eos;
 
51
 
 
52
        uint32 last_x;
 
53
        uint32 last_y;
 
54
        uint32 last_width;
 
55
        uint32 last_height;
 
56
        uint16 last_num_rects;
 
57
        RDP_RECT* last_rects;
 
58
 
 
59
        uint32 output_x;
 
60
        uint32 output_y;
 
61
        uint32 output_width;
 
62
        uint32 output_height;
 
63
        uint16 output_num_rects;
 
64
        RDP_RECT* output_rects;
 
65
 
 
66
        IWTSVirtualChannelCallback* channel_callback;
 
67
 
 
68
        uint64 audio_start_time;
 
69
        uint64 audio_end_time;
 
70
 
 
71
        /* The stream list could be accessed by differnt threads and need to be protected. */
 
72
        freerdp_mutex mutex;
 
73
 
 
74
        LIST* stream_list;
 
75
};
 
76
 
 
77
struct _TSMF_STREAM
 
78
{
 
79
        uint32 stream_id;
 
80
 
 
81
        TSMF_PRESENTATION* presentation;
 
82
 
 
83
        ITSMFDecoder* decoder;
 
84
 
 
85
        int major_type;
 
86
        int eos;
 
87
        uint32 width;
 
88
        uint32 height;
 
89
 
 
90
        ITSMFAudioDevice* audio;
 
91
        uint32 sample_rate;
 
92
        uint32 channels;
 
93
        uint32 bits_per_sample;
 
94
 
 
95
        /* The end_time of last played sample */
 
96
        uint64 last_end_time;
 
97
        /* Next sample should not start before this system time. */
 
98
        uint64 next_start_time;
 
99
 
 
100
        freerdp_thread* thread;
 
101
 
 
102
        LIST* sample_list;
 
103
 
 
104
        /* The sample ack response queue will be accessed only by the stream thread. */
 
105
        LIST* sample_ack_list;
 
106
};
 
107
 
 
108
struct _TSMF_SAMPLE
 
109
{
 
110
        uint32 sample_id;
 
111
        uint64 start_time;
 
112
        uint64 end_time;
 
113
        uint64 duration;
 
114
        uint32 extensions;
 
115
        uint32 data_size;
 
116
        uint8* data;
 
117
        uint32 decoded_size;
 
118
        uint32 pixfmt;
 
119
 
 
120
        TSMF_STREAM* stream;
 
121
        IWTSVirtualChannelCallback* channel_callback;
 
122
        uint64 ack_time;
 
123
};
 
124
 
 
125
static LIST* presentation_list = NULL;
 
126
 
 
127
static uint64 get_current_time(void)
 
128
{
 
129
        struct timeval tp;
 
130
 
 
131
        gettimeofday(&tp, 0);
 
132
        return ((uint64)tp.tv_sec) * 10000000LL + ((uint64)tp.tv_usec) * 10LL;
 
133
}
 
134
 
 
135
static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
 
136
{
 
137
        TSMF_STREAM* s;
 
138
        LIST_ITEM* item;
 
139
        TSMF_SAMPLE* sample;
 
140
        boolean pending = false;
 
141
        TSMF_PRESENTATION* presentation = stream->presentation;
 
142
 
 
143
        if (!stream->sample_list->head)
 
144
                return NULL;
 
145
 
 
146
        if (sync)
 
147
        {
 
148
                if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
 
149
                {
 
150
                        /* Check if some other stream has earlier sample that needs to be played first */
 
151
                        if (stream->last_end_time > AUDIO_TOLERANCE)
 
152
                        {
 
153
                                freerdp_mutex_lock(presentation->mutex);
 
154
                                for (item = presentation->stream_list->head; item; item = item->next)
 
155
                                {
 
156
                                        s = (TSMF_STREAM*) item->data;
 
157
                                        if (s != stream && !s->eos && s->last_end_time &&
 
158
                                                s->last_end_time < stream->last_end_time - AUDIO_TOLERANCE)
 
159
                                        {
 
160
                                                        pending = true;
 
161
                                                        break;
 
162
                                        }
 
163
                                }
 
164
                                freerdp_mutex_unlock(presentation->mutex);
 
165
                        }
 
166
                }
 
167
                else
 
168
                {
 
169
                        if (stream->last_end_time > presentation->audio_end_time)
 
170
                        {
 
171
                                pending = true;
 
172
                        }
 
173
                }
 
174
        }
 
175
        if (pending)
 
176
                return NULL;
 
177
 
 
178
        freerdp_thread_lock(stream->thread);
 
179
        sample = (TSMF_SAMPLE*) list_dequeue(stream->sample_list);
 
180
        freerdp_thread_unlock(stream->thread);
 
181
 
 
182
        if (sample && sample->end_time > stream->last_end_time)
 
183
                stream->last_end_time = sample->end_time;
 
184
 
 
185
        return sample;
 
186
}
 
187
 
 
188
static void tsmf_sample_free(TSMF_SAMPLE* sample)
 
189
{
 
190
        if (sample->data)
 
191
                xfree(sample->data);
 
192
        xfree(sample);
 
193
}
 
194
 
 
195
static void tsmf_sample_ack(TSMF_SAMPLE* sample)
 
196
{
 
197
        tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size);
 
198
}
 
199
 
 
200
static void tsmf_sample_queue_ack(TSMF_SAMPLE* sample)
 
201
{
 
202
        TSMF_STREAM* stream = sample->stream;
 
203
 
 
204
        list_enqueue(stream->sample_ack_list, sample);
 
205
}
 
206
 
 
207
static void tsmf_stream_process_ack(TSMF_STREAM* stream)
 
208
{
 
209
        TSMF_SAMPLE* sample;
 
210
        uint64 ack_time;
 
211
 
 
212
        ack_time = get_current_time();
 
213
        while (stream->sample_ack_list->head && !freerdp_thread_is_stopped(stream->thread))
 
214
        {
 
215
                sample = (TSMF_SAMPLE*) list_peek(stream->sample_ack_list);
 
216
                if (sample->ack_time > ack_time)
 
217
                        break;
 
218
 
 
219
                sample = list_dequeue(stream->sample_ack_list);
 
220
                tsmf_sample_ack(sample);
 
221
                tsmf_sample_free(sample);
 
222
        }
 
223
}
 
224
 
 
225
TSMF_PRESENTATION* tsmf_presentation_new(const uint8* guid, IWTSVirtualChannelCallback* pChannelCallback)
 
226
{
 
227
        TSMF_PRESENTATION* presentation;
 
228
 
 
229
        presentation = tsmf_presentation_find_by_id(guid);
 
230
        if (presentation)
 
231
        {
 
232
                DEBUG_WARN("duplicated presentation id!");
 
233
                return NULL;
 
234
        }
 
235
 
 
236
        presentation = xnew(TSMF_PRESENTATION);
 
237
 
 
238
        memcpy(presentation->presentation_id, guid, GUID_SIZE);
 
239
        presentation->channel_callback = pChannelCallback;
 
240
 
 
241
        presentation->mutex = freerdp_mutex_new();
 
242
        presentation->stream_list = list_new();
 
243
 
 
244
        list_enqueue(presentation_list, presentation);
 
245
 
 
246
        return presentation;
 
247
}
 
248
 
 
249
TSMF_PRESENTATION* tsmf_presentation_find_by_id(const uint8* guid)
 
250
{
 
251
        LIST_ITEM* item;
 
252
        TSMF_PRESENTATION* presentation;
 
253
 
 
254
        for (item = presentation_list->head; item; item = item->next)
 
255
        {
 
256
                presentation = (TSMF_PRESENTATION*) item->data;
 
257
                if (memcmp(presentation->presentation_id, guid, GUID_SIZE) == 0)
 
258
                        return presentation;
 
259
        }
 
260
        return NULL;
 
261
}
 
262
 
 
263
static void tsmf_presentation_restore_last_video_frame(TSMF_PRESENTATION* presentation)
 
264
{
 
265
        RDP_REDRAW_EVENT* revent;
 
266
 
 
267
        if (presentation->last_width && presentation->last_height)
 
268
        {
 
269
                revent = (RDP_REDRAW_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_TSMF, RDP_EVENT_TYPE_TSMF_REDRAW,
 
270
                        NULL, NULL);
 
271
                revent->x = presentation->last_x;
 
272
                revent->y = presentation->last_y;
 
273
                revent->width = presentation->last_width;
 
274
                revent->height = presentation->last_height;
 
275
                if (!tsmf_push_event(presentation->channel_callback, (RDP_EVENT*) revent))
 
276
                {
 
277
                        freerdp_event_free((RDP_EVENT*) revent);
 
278
                }
 
279
                presentation->last_x = 0;
 
280
                presentation->last_y = 0;
 
281
                presentation->last_width = 0;
 
282
                presentation->last_height = 0;
 
283
        }
 
284
}
 
285
 
 
286
static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
 
287
{
 
288
        uint64 t;
 
289
        RDP_VIDEO_FRAME_EVENT* vevent;
 
290
        TSMF_STREAM* stream = sample->stream;
 
291
        TSMF_PRESENTATION* presentation = stream->presentation;
 
292
 
 
293
        DEBUG_DVC("MessageId %d EndTime %d data_size %d consumed.",
 
294
                sample->sample_id, (int)sample->end_time, sample->data_size);
 
295
 
 
296
        if (sample->data)
 
297
        {
 
298
                t = get_current_time();
 
299
                if (stream->next_start_time > t &&
 
300
                        (sample->end_time >= presentation->audio_start_time ||
 
301
                        sample->end_time < stream->last_end_time))
 
302
                {
 
303
                        freerdp_usleep((stream->next_start_time - t) / 10);
 
304
                }
 
305
                stream->next_start_time = t + sample->duration - 50000;
 
306
 
 
307
                if (presentation->last_x != presentation->output_x ||
 
308
                        presentation->last_y != presentation->output_y ||
 
309
                        presentation->last_width != presentation->output_width ||
 
310
                        presentation->last_height != presentation->output_height ||
 
311
                        presentation->last_num_rects != presentation->output_num_rects ||
 
312
                        (presentation->last_rects && presentation->output_rects &&
 
313
                        memcmp(presentation->last_rects, presentation->output_rects,
 
314
                        presentation->last_num_rects * sizeof(RDP_RECT)) != 0))
 
315
                {
 
316
                        tsmf_presentation_restore_last_video_frame(presentation);
 
317
 
 
318
                        presentation->last_x = presentation->output_x;
 
319
                        presentation->last_y = presentation->output_y;
 
320
                        presentation->last_width = presentation->output_width;
 
321
                        presentation->last_height = presentation->output_height;
 
322
 
 
323
                        if (presentation->last_rects)
 
324
                        {
 
325
                                xfree(presentation->last_rects);
 
326
                                presentation->last_rects = NULL;
 
327
                        }
 
328
                        presentation->last_num_rects = presentation->output_num_rects;
 
329
                        if (presentation->last_num_rects > 0)
 
330
                        {
 
331
                                presentation->last_rects = xzalloc(presentation->last_num_rects * sizeof(RDP_RECT));
 
332
                                memcpy(presentation->last_rects, presentation->output_rects,
 
333
                                        presentation->last_num_rects * sizeof(RDP_RECT));
 
334
                        }
 
335
                }
 
336
 
 
337
                vevent = (RDP_VIDEO_FRAME_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_TSMF, RDP_EVENT_TYPE_TSMF_VIDEO_FRAME,
 
338
                        NULL, NULL);
 
339
                vevent->frame_data = sample->data;
 
340
                vevent->frame_size = sample->decoded_size;
 
341
                vevent->frame_pixfmt = sample->pixfmt;
 
342
                vevent->frame_width = sample->stream->width;
 
343
                vevent->frame_height = sample->stream->height;
 
344
                vevent->x = presentation->output_x;
 
345
                vevent->y = presentation->output_y;
 
346
                vevent->width = presentation->output_width;
 
347
                vevent->height = presentation->output_height;
 
348
                if (presentation->output_num_rects > 0)
 
349
                {
 
350
                        vevent->num_visible_rects = presentation->output_num_rects;
 
351
                        vevent->visible_rects = (RDP_RECT*) xzalloc(presentation->output_num_rects * sizeof(RDP_RECT));
 
352
                        memcpy(vevent->visible_rects, presentation->output_rects,
 
353
                                presentation->output_num_rects * sizeof(RDP_RECT));
 
354
                }
 
355
 
 
356
                /* The frame data ownership is passed to the event object, and is freed after the event is processed. */
 
357
                sample->data = NULL;
 
358
                sample->decoded_size = 0;
 
359
 
 
360
                if (!tsmf_push_event(sample->channel_callback, (RDP_EVENT*) vevent))
 
361
                {
 
362
                        freerdp_event_free((RDP_EVENT*) vevent);
 
363
                }
 
364
 
 
365
#if 0
 
366
                /* Dump a .ppm image for every 30 frames. Assuming the frame is in YUV format, we
 
367
                   extract the Y values to create a grayscale image. */
 
368
                static int frame_id = 0;
 
369
                char buf[100];
 
370
                FILE * fp;
 
371
                if ((frame_id % 30) == 0)
 
372
                {
 
373
                        snprintf(buf, sizeof(buf), "/tmp/FreeRDP_Frame_%d.ppm", frame_id);
 
374
                        fp = fopen(buf, "wb");
 
375
                        fwrite("P5\n", 1, 3, fp);
 
376
                        snprintf(buf, sizeof(buf), "%d %d\n", sample->stream->width, sample->stream->height);
 
377
                        fwrite(buf, 1, strlen(buf), fp);
 
378
                        fwrite("255\n", 1, 4, fp);
 
379
                        fwrite(sample->data, 1, sample->stream->width * sample->stream->height, fp);
 
380
                        fflush(fp);
 
381
                        fclose(fp);
 
382
                }
 
383
                frame_id++;
 
384
#endif
 
385
        }
 
386
}
 
387
 
 
388
static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
 
389
{
 
390
        uint64 latency = 0;
 
391
        TSMF_STREAM* stream = sample->stream;
 
392
 
 
393
        DEBUG_DVC("MessageId %d EndTime %d consumed.",
 
394
                sample->sample_id, (int)sample->end_time);
 
395
 
 
396
        if (sample->stream->audio && sample->data)
 
397
        {
 
398
                sample->stream->audio->Play(sample->stream->audio,
 
399
                        sample->data, sample->decoded_size);
 
400
                sample->data = NULL;
 
401
                sample->decoded_size = 0;
 
402
 
 
403
                if (stream->audio && stream->audio->GetLatency)
 
404
                        latency = stream->audio->GetLatency(stream->audio);
 
405
        }
 
406
        else
 
407
        {
 
408
                latency = 0;
 
409
        }
 
410
 
 
411
        sample->ack_time = latency + get_current_time();
 
412
        stream->last_end_time = sample->end_time + latency;
 
413
        stream->presentation->audio_start_time = sample->start_time + latency;
 
414
        stream->presentation->audio_end_time = sample->end_time + latency;
 
415
}
 
416
 
 
417
static void tsmf_sample_playback(TSMF_SAMPLE* sample)
 
418
{
 
419
        boolean ret = false;
 
420
        uint32 width;
 
421
        uint32 height;
 
422
        uint32 pixfmt = 0;
 
423
        TSMF_STREAM* stream = sample->stream;
 
424
 
 
425
        if (stream->decoder)
 
426
                ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size, sample->extensions);
 
427
        if (!ret)
 
428
        {
 
429
                tsmf_sample_ack(sample);
 
430
                tsmf_sample_free(sample);
 
431
                return;
 
432
        }
 
433
 
 
434
        xfree(sample->data);
 
435
        sample->data = NULL;
 
436
 
 
437
        if (stream->major_type == TSMF_MAJOR_TYPE_VIDEO)
 
438
        {
 
439
                if (stream->decoder->GetDecodedFormat)
 
440
                {
 
441
                        pixfmt = stream->decoder->GetDecodedFormat(stream->decoder);
 
442
                        if (pixfmt == ((uint32) -1))
 
443
                        {
 
444
                                tsmf_sample_ack(sample);
 
445
                                tsmf_sample_free(sample);
 
446
                                return;
 
447
                        }
 
448
                        sample->pixfmt = pixfmt;
 
449
                }
 
450
 
 
451
                if (stream->decoder->GetDecodedDimension)
 
452
                        ret = stream->decoder->GetDecodedDimension(stream->decoder, &width, &height);
 
453
                if (ret && (width != stream->width || height != stream->height))
 
454
                {
 
455
                        DEBUG_DVC("video dimension changed to %d x %d", width, height);
 
456
                        stream->width = width;
 
457
                        stream->height = height;
 
458
                }
 
459
        }
 
460
 
 
461
        if (stream->decoder->GetDecodedData)
 
462
        {
 
463
                sample->data = stream->decoder->GetDecodedData(stream->decoder, &sample->decoded_size);
 
464
        }
 
465
 
 
466
        switch (sample->stream->major_type)
 
467
        {
 
468
                case TSMF_MAJOR_TYPE_VIDEO:
 
469
                        tsmf_sample_playback_video(sample);
 
470
                        tsmf_sample_ack(sample);
 
471
                        tsmf_sample_free(sample);
 
472
                        break;
 
473
                case TSMF_MAJOR_TYPE_AUDIO:
 
474
                        tsmf_sample_playback_audio(sample);
 
475
                        tsmf_sample_queue_ack(sample);
 
476
                        break;
 
477
        }
 
478
}
 
479
 
 
480
static void* tsmf_stream_playback_func(void* arg)
 
481
{
 
482
        TSMF_SAMPLE* sample;
 
483
        TSMF_STREAM* stream = (TSMF_STREAM*) arg;
 
484
        TSMF_PRESENTATION* presentation = stream->presentation;
 
485
 
 
486
        DEBUG_DVC("in %d", stream->stream_id);
 
487
 
 
488
        if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO &&
 
489
                stream->sample_rate && stream->channels && stream->bits_per_sample)
 
490
        {
 
491
                stream->audio = tsmf_load_audio_device(
 
492
                        presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL,
 
493
                        presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL);
 
494
                if (stream->audio)
 
495
                {
 
496
                        stream->audio->SetFormat(stream->audio,
 
497
                                stream->sample_rate, stream->channels, stream->bits_per_sample);
 
498
                }
 
499
        }
 
500
        while (!freerdp_thread_is_stopped(stream->thread))
 
501
        {
 
502
                tsmf_stream_process_ack(stream);
 
503
                sample = tsmf_stream_pop_sample(stream, 1);
 
504
                if (sample)
 
505
                        tsmf_sample_playback(sample);
 
506
                else
 
507
                        freerdp_usleep(5000);
 
508
        }
 
509
        if (stream->eos || presentation->eos)
 
510
        {
 
511
                while ((sample = tsmf_stream_pop_sample(stream, 1)) != NULL)
 
512
                        tsmf_sample_playback(sample);
 
513
        }
 
514
        if (stream->audio)
 
515
        {
 
516
                stream->audio->Free(stream->audio);
 
517
                stream->audio = NULL;
 
518
        }
 
519
 
 
520
        freerdp_thread_quit(stream->thread);
 
521
 
 
522
        DEBUG_DVC("out %d", stream->stream_id);
 
523
 
 
524
        return NULL;
 
525
}
 
526
 
 
527
static void tsmf_stream_start(TSMF_STREAM* stream)
 
528
{
 
529
        if (!freerdp_thread_is_running(stream->thread))
 
530
        {
 
531
                freerdp_thread_start(stream->thread, tsmf_stream_playback_func, stream);
 
532
        }
 
533
}
 
534
 
 
535
static void tsmf_stream_stop(TSMF_STREAM* stream)
 
536
{
 
537
        if (freerdp_thread_is_running(stream->thread))
 
538
        {
 
539
                freerdp_thread_stop(stream->thread);
 
540
        }
 
541
}
 
542
 
 
543
void tsmf_presentation_start(TSMF_PRESENTATION* presentation)
 
544
{
 
545
        LIST_ITEM* item;
 
546
        TSMF_STREAM* stream;
 
547
 
 
548
        for (item = presentation->stream_list->head; item; item = item->next)
 
549
        {
 
550
                stream = (TSMF_STREAM*) item->data;
 
551
                tsmf_stream_start(stream);
 
552
        }
 
553
}
 
554
 
 
555
void tsmf_presentation_stop(TSMF_PRESENTATION* presentation)
 
556
{
 
557
        LIST_ITEM* item;
 
558
        TSMF_STREAM* stream;
 
559
 
 
560
        tsmf_presentation_flush(presentation);
 
561
 
 
562
        for (item = presentation->stream_list->head; item; item = item->next)
 
563
        {
 
564
                stream = (TSMF_STREAM*) item->data;
 
565
                tsmf_stream_stop(stream);
 
566
        }
 
567
 
 
568
        tsmf_presentation_restore_last_video_frame(presentation);
 
569
        if (presentation->last_rects)
 
570
        {
 
571
                xfree(presentation->last_rects);
 
572
                presentation->last_rects = NULL;
 
573
        }
 
574
        presentation->last_num_rects = 0;
 
575
        if (presentation->output_rects)
 
576
        {
 
577
                xfree(presentation->output_rects);
 
578
                presentation->output_rects = NULL;
 
579
        }
 
580
        presentation->output_num_rects = 0;
 
581
}
 
582
 
 
583
void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation,
 
584
        uint32 x, uint32 y, uint32 width, uint32 height,
 
585
        int num_rects, RDP_RECT* rects)
 
586
{
 
587
        presentation->output_x = x;
 
588
        presentation->output_y = y;
 
589
        presentation->output_width = width;
 
590
        presentation->output_height = height;
 
591
        if (presentation->output_rects)
 
592
                xfree(presentation->output_rects);
 
593
        presentation->output_rects = rects;
 
594
        presentation->output_num_rects = num_rects;
 
595
}
 
596
 
 
597
void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const char* name, const char* device)
 
598
{
 
599
        presentation->audio_name = name;
 
600
        presentation->audio_device = device;
 
601
}
 
602
 
 
603
static void tsmf_stream_flush(TSMF_STREAM* stream)
 
604
{
 
605
        TSMF_SAMPLE* sample;
 
606
 
 
607
        while ((sample = tsmf_stream_pop_sample(stream, 0)) != NULL)
 
608
                tsmf_sample_free(sample);
 
609
 
 
610
        while ((sample = list_dequeue(stream->sample_ack_list)) != NULL)
 
611
                tsmf_sample_free(sample);
 
612
 
 
613
        if (stream->audio)
 
614
                stream->audio->Flush(stream->audio);
 
615
 
 
616
        stream->eos = 0;
 
617
        stream->last_end_time = 0;
 
618
        stream->next_start_time = 0;
 
619
        if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
 
620
        {
 
621
                stream->presentation->audio_start_time = 0;
 
622
                stream->presentation->audio_end_time = 0;
 
623
        }
 
624
}
 
625
 
 
626
void tsmf_presentation_flush(TSMF_PRESENTATION* presentation)
 
627
{
 
628
        LIST_ITEM* item;
 
629
        TSMF_STREAM * stream;
 
630
 
 
631
        for (item = presentation->stream_list->head; item; item = item->next)
 
632
        {
 
633
                stream = (TSMF_STREAM*) item->data;
 
634
                tsmf_stream_flush(stream);
 
635
        }
 
636
 
 
637
        presentation->eos = 0;
 
638
        presentation->audio_start_time = 0;
 
639
        presentation->audio_end_time = 0;
 
640
}
 
641
 
 
642
void tsmf_presentation_free(TSMF_PRESENTATION* presentation)
 
643
{
 
644
        TSMF_STREAM* stream;
 
645
 
 
646
        tsmf_presentation_stop(presentation);
 
647
        list_remove(presentation_list, presentation);
 
648
 
 
649
        while (presentation->stream_list->head)
 
650
        {
 
651
                stream = (TSMF_STREAM*) list_peek(presentation->stream_list);
 
652
                tsmf_stream_free(stream);
 
653
        }
 
654
        list_free(presentation->stream_list);
 
655
 
 
656
        freerdp_mutex_free(presentation->mutex);
 
657
 
 
658
        xfree(presentation);
 
659
}
 
660
 
 
661
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, uint32 stream_id)
 
662
{
 
663
        TSMF_STREAM* stream;
 
664
 
 
665
        stream = tsmf_stream_find_by_id(presentation, stream_id);
 
666
        if (stream)
 
667
        {
 
668
                DEBUG_WARN("duplicated stream id %d!", stream_id);
 
669
                return NULL;
 
670
        }
 
671
 
 
672
        stream = xnew(TSMF_STREAM);
 
673
 
 
674
        stream->stream_id = stream_id;
 
675
        stream->presentation = presentation;
 
676
        stream->thread = freerdp_thread_new();
 
677
        stream->sample_list = list_new();
 
678
        stream->sample_ack_list = list_new();
 
679
 
 
680
        freerdp_mutex_lock(presentation->mutex);
 
681
        list_enqueue(presentation->stream_list, stream);
 
682
        freerdp_mutex_unlock(presentation->mutex);
 
683
 
 
684
        return stream;
 
685
}
 
686
 
 
687
TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, uint32 stream_id)
 
688
{
 
689
        LIST_ITEM* item;
 
690
        TSMF_STREAM* stream;
 
691
 
 
692
        for (item = presentation->stream_list->head; item; item = item->next)
 
693
        {
 
694
                stream = (TSMF_STREAM*) item->data;
 
695
                if (stream->stream_id == stream_id)
 
696
                        return stream;
 
697
        }
 
698
        return NULL;
 
699
}
 
700
 
 
701
void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, STREAM* s)
 
702
{
 
703
        TS_AM_MEDIA_TYPE mediatype;
 
704
 
 
705
        if (stream->decoder)
 
706
        {
 
707
                DEBUG_WARN("duplicated call");
 
708
                return;
 
709
        }
 
710
 
 
711
        tsmf_codec_parse_media_type(&mediatype, s);
 
712
 
 
713
        if (mediatype.MajorType == TSMF_MAJOR_TYPE_VIDEO)
 
714
        {
 
715
                DEBUG_DVC("video width %d height %d bit_rate %d frame_rate %f codec_data %d",
 
716
                        mediatype.Width, mediatype.Height, mediatype.BitRate,
 
717
                        (double)mediatype.SamplesPerSecond.Numerator / (double)mediatype.SamplesPerSecond.Denominator,
 
718
                        mediatype.ExtraDataSize);
 
719
        }
 
720
        else if (mediatype.MajorType == TSMF_MAJOR_TYPE_AUDIO)
 
721
        {
 
722
                DEBUG_DVC("audio channel %d sample_rate %d bits_per_sample %d codec_data %d",
 
723
                        mediatype.Channels, mediatype.SamplesPerSecond.Numerator, mediatype.BitsPerSample,
 
724
                        mediatype.ExtraDataSize);
 
725
                stream->sample_rate = mediatype.SamplesPerSecond.Numerator;
 
726
                stream->channels = mediatype.Channels;
 
727
                stream->bits_per_sample = mediatype.BitsPerSample;
 
728
                if (stream->bits_per_sample == 0)
 
729
                        stream->bits_per_sample = 16;
 
730
        }
 
731
 
 
732
        stream->major_type = mediatype.MajorType;
 
733
        stream->width = mediatype.Width;
 
734
        stream->height = mediatype.Height;
 
735
        stream->decoder = tsmf_load_decoder(name, &mediatype);
 
736
}
 
737
 
 
738
void tsmf_stream_end(TSMF_STREAM* stream)
 
739
{
 
740
        stream->eos = 1;
 
741
        stream->presentation->eos = 1;
 
742
}
 
743
 
 
744
void tsmf_stream_free(TSMF_STREAM* stream)
 
745
{
 
746
        TSMF_PRESENTATION* presentation = stream->presentation;
 
747
 
 
748
        tsmf_stream_stop(stream);
 
749
        tsmf_stream_flush(stream);
 
750
 
 
751
        freerdp_mutex_lock(presentation->mutex);
 
752
        list_remove(presentation->stream_list, stream);
 
753
        freerdp_mutex_unlock(presentation->mutex);
 
754
 
 
755
        list_free(stream->sample_list);
 
756
        list_free(stream->sample_ack_list);
 
757
 
 
758
        if (stream->decoder)
 
759
                stream->decoder->Free(stream->decoder);
 
760
 
 
761
        freerdp_thread_free(stream->thread);
 
762
 
 
763
        xfree(stream);
 
764
}
 
765
 
 
766
void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pChannelCallback,
 
767
        uint32 sample_id, uint64 start_time, uint64 end_time, uint64 duration, uint32 extensions,
 
768
        uint32 data_size, uint8* data)
 
769
{
 
770
        TSMF_SAMPLE* sample;
 
771
 
 
772
        sample = xnew(TSMF_SAMPLE);
 
773
 
 
774
        sample->sample_id = sample_id;
 
775
        sample->start_time = start_time;
 
776
        sample->end_time = end_time;
 
777
        sample->duration = duration;
 
778
        sample->extensions = extensions;
 
779
        sample->stream = stream;
 
780
        sample->channel_callback = pChannelCallback;
 
781
        sample->data_size = data_size;
 
782
        sample->data = xzalloc(data_size + TSMF_BUFFER_PADDING_SIZE);
 
783
        memcpy(sample->data, data, data_size);
 
784
 
 
785
        freerdp_thread_lock(stream->thread);
 
786
        list_enqueue(stream->sample_list, sample);
 
787
        freerdp_thread_unlock(stream->thread);
 
788
}
 
789
 
 
790
void tsmf_media_init(void)
 
791
{
 
792
        if (presentation_list == NULL)
 
793
                presentation_list = list_new();
 
794
}
 
795