comparison MediaPlayer.cpp @ 2315:58be29479e75

add files
author Ritor1
date Wed, 19 Mar 2014 10:09:42 +0600
parents
children 9987f93d7e1f
comparison
equal deleted inserted replaced
2314:8e9be4fa33a8 2315:58be29479e75
1 extern "C"
2 {
3 #include "lib/libavcodec/avcodec.h"
4 #include "lib/libavformat/avformat.h"
5 #include "lib/libavutil/avutil.h"
6 #include "lib/libavutil/imgutils.h"
7 #include "lib/libswscale/swscale.h"
8 #include "lib/libswresample/swresample.h"
9 #include "lib/libavutil/opt.h"
10 //#include "libavutil/samplefmt.h"
11 }
12 #pragma comment(lib, "avcodec.lib")
13 #pragma comment(lib, "avformat.lib")
14 #pragma comment(lib, "avutil.lib")
15 #pragma comment(lib, "swscale.lib")
16 #pragma comment(lib, "swresample.lib")
17
18 #include <vector>
19 #include <deque>
20
21 #include "stuff.h"
22 #include "OpenALSoundProvider.h"
23
24 #include "MediaPlayer.h"
25 using namespace Media;
26
27
28
29
30 class MemoryStream
31 {
32 public:
33 inline MemoryStream(void *data, size_t data_size)
34 {
35 this->data_size = data_size;
36 this->data = data;
37 this->current_pos = 0;
38 }
39 inline MemoryStream()
40 {
41 this->data_size = 0;
42 this->data = nullptr;
43 this->current_pos = 0;
44 }
45
46 inline ~MemoryStream()
47 {
48 if (data)
49 delete [] data;
50 }
51
52 inline size_t Write(void *buffer, size_t num_bytes)
53 {
54 if (!data)
55 {
56 data_size = 32 + num_bytes;
57 data = new char[data_size];
58 current_pos = 0;
59 }
60 else if (current_pos + num_bytes >= data_size)
61 {
62 int new_data_size = data_size + num_bytes + data_size / 8 + 4;
63 auto new_data = new char[new_data_size];
64
65 memcpy(new_data, data, data_size);
66 delete [] data;
67
68 data_size = new_data_size;
69 data = new_data;
70 }
71 memcpy((char *)data + current_pos, buffer, num_bytes);
72 current_pos += num_bytes;
73 return num_bytes;
74 }
75
76 inline size_t Read(void *buffer, size_t num_bytes)
77 {
78 size_t read_size = min(num_bytes, data_size - current_pos);
79 if (read_size)
80 {
81 memcpy(buffer, (char *)data + current_pos, read_size);
82 current_pos += read_size;
83 }
84 return read_size;
85 }
86
87 inline void Reset()
88 {
89 current_pos = 0;
90 }
91 inline void SeekToEnd()
92 {
93 current_pos = data_size;
94 }
95
96 inline size_t Unwind(size_t bytes)
97 {
98 if (bytes > current_pos)
99 current_pos = 0;
100 else
101 current_pos -= bytes;
102 return current_pos;
103 }
104
105 inline size_t Rewind(size_t bytes)
106 {
107 if (current_pos + bytes >= data_size)
108 current_pos = data_size;
109 else
110 current_pos += bytes;
111 return current_pos;
112 }
113
114 inline size_t Size() const {return data_size;}
115 inline size_t Current() const {return current_pos;}
116 inline void *Ptr() const {return data;}
117
118 private:
119 void *data;
120 size_t data_size;
121 size_t current_pos;
122 };
123
124
125
126
127 OpenALSoundProvider *provider = nullptr;
128
129
130
131 static int av_num_bytes_per_sample(AVSampleFormat sample_fmt)
132 {
133 switch (sample_fmt)
134 {
135 case AV_SAMPLE_FMT_U8:
136 case AV_SAMPLE_FMT_U8P:
137 return 1;
138
139 case AV_SAMPLE_FMT_S16:
140 case AV_SAMPLE_FMT_S16P:
141 return 2;
142
143 case AV_SAMPLE_FMT_S32:
144 case AV_SAMPLE_FMT_S32P:
145 case AV_SAMPLE_FMT_FLT:
146 case AV_SAMPLE_FMT_FLTP:
147 return 4;
148
149 case AV_SAMPLE_FMT_DBL:
150 case AV_SAMPLE_FMT_DBLP:
151 return 8;
152
153 default:
154 case AV_SAMPLE_FMT_NONE:
155 Error("Invalid av sample format: %u", sample_fmt);
156 }
157 return 0;
158 }
159
160
161
162 struct AVStreamWrapper
163 {
164 inline AVStreamWrapper()
165 {
166 this->type = AVMEDIA_TYPE_UNKNOWN;
167 this->stream_idx = -1;
168 this->stream = nullptr;
169 this->dec = nullptr;
170 this->dec_ctx = nullptr;
171 }
172
173 inline void Release()
174 {
175 type = AVMEDIA_TYPE_UNKNOWN;
176 stream_idx = -1;
177 stream = nullptr;
178 dec = nullptr;
179 if (dec_ctx)
180 {
181 avcodec_close(dec_ctx);
182 dec_ctx = nullptr;
183 }
184 }
185
186 AVMediaType type;
187 int stream_idx;
188 AVStream *stream;
189 AVCodec *dec;
190 AVCodecContext *dec_ctx;
191 };
192
193 struct AVAudioStream: public AVStreamWrapper
194 {
195 inline AVAudioStream():
196 AVStreamWrapper()
197 {
198 this->bytes_per_sample = 0;
199 this->bytes_per_second = 0;
200 }
201
202 int bytes_per_sample;
203 int bytes_per_second;
204 };
205
206 struct AVVideoStream: public AVStreamWrapper
207 {
208 inline AVVideoStream():
209 AVStreamWrapper()
210 {
211 this->frames_per_second = 0.0;
212 }
213
214 double frames_per_second;
215 };
216
217 static bool av_open_stream(AVFormatContext *format_ctx, AVMediaType type, AVStreamWrapper *out_stream)
218 {
219 int stream_idx = av_find_best_stream(format_ctx, type, -1, -1, nullptr, 0);
220 if (stream_idx >= 0)
221 {
222 auto stream = format_ctx->streams[stream_idx];
223 auto dec_ctx = stream->codec;
224 auto dec = avcodec_find_decoder(dec_ctx->codec_id);
225 if (dec)
226 {
227 if (avcodec_open2(dec_ctx, dec, nullptr) >= 0)
228 {
229 out_stream->type = type;
230 out_stream->stream_idx = stream_idx;
231 out_stream->stream = stream;
232 out_stream->dec = dec;
233 out_stream->dec_ctx = dec_ctx;
234 return true;
235 }
236 }
237 }
238 return false;
239 }
240
241 static bool av_open_audio_stream(AVFormatContext *format_ctx, AVAudioStream *out_stream)
242 {
243 if (!av_open_stream(format_ctx, AVMEDIA_TYPE_AUDIO, out_stream))
244 return Error("Audio stream not found"), false;
245
246 // we support only 2-channel audio for now
247 if (out_stream->dec_ctx->channels != 2)
248 {
249 out_stream->Release();
250 return Error("Unsupported number of channels: %u", out_stream->dec_ctx->channels), false;
251 }
252
253 out_stream->bytes_per_sample = av_num_bytes_per_sample(out_stream->dec_ctx->sample_fmt);
254 out_stream->bytes_per_second = out_stream->dec_ctx->channels * out_stream->dec_ctx->sample_rate * out_stream->bytes_per_sample;
255
256 return true;
257 }
258
259 static bool av_open_video_stream(AVFormatContext *format_ctx, AVVideoStream *out_stream)
260 {
261 if (!av_open_stream(format_ctx, AVMEDIA_TYPE_VIDEO, out_stream))
262 return Error("Video stream not found"), false;
263
264 out_stream->frames_per_second = (double)out_stream->dec_ctx->time_base.den / (double)out_stream->dec_ctx->time_base.num;
265 return true;
266 }
267
268
269
270 void InterleaveAudioData(MemoryStream *stream, AVSampleFormat src_format, int num_channels, int num_samples, uint8_t **channels)
271 {
272 unsigned int bytes_per_sample;
273 switch (src_format)
274 {
275 case AV_SAMPLE_FMT_U8:
276 case AV_SAMPLE_FMT_U8P:
277 __debugbreak();
278
279 case AV_SAMPLE_FMT_S16:
280 bytes_per_sample = sizeof(__int16);
281 stream->Write(channels[0], num_channels * num_samples * bytes_per_sample);
282 break;
283
284 case AV_SAMPLE_FMT_S16P:
285 {
286 bytes_per_sample = sizeof(__int16);
287 for (int i = 0; i < num_samples; ++i)
288 for (int j = 0; j < num_channels; ++j)
289 stream->Write(channels[j] + i * bytes_per_sample, bytes_per_sample);
290 }
291 break;
292
293 case AV_SAMPLE_FMT_FLT:
294 {
295 SwrContext *converter = swr_alloc();
296 av_opt_set_int(converter, "in_channel_layout", av_get_default_channel_layout(2), 0);
297 //av_opt_set_int(converter, "in_sample_rate", sample_ra, 0);
298 av_opt_set_sample_fmt(converter, "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
299
300 av_opt_set_int(converter, "out_channel_layout", av_get_default_channel_layout(2), 0);
301 //av_opt_set_int(converter, "out_sample_rate", dst_sample_rate, 0);
302 av_opt_set_sample_fmt(converter, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
303
304 if (swr_init(converter) < 0)
305 {
306 __debugbreak();
307 swr_free(&converter);
308 return;
309 }
310
311 uint8_t **dst_channels;
312 int dst_linesize[8];
313 //int dst_nb_channels = av_get_channel_layout_nb_channels(dst_channel_layout);
314 if (av_samples_alloc_array_and_samples(&dst_channels, dst_linesize, 2, num_channels * num_samples, AV_SAMPLE_FMT_S16, 0) < 0)
315 {
316 __debugbreak();
317 swr_free(&converter);
318 return;
319 }
320
321 if (swr_convert(converter, dst_channels, num_channels * num_samples, (const uint8_t **)channels, num_channels * num_samples) >= 0)
322 stream->Write(dst_channels[0], num_channels * num_samples * sizeof(__int16));
323 else
324 __debugbreak();
325
326 av_free(dst_channels[0]);
327 swr_free(&converter);
328 }
329 break;
330
331 default:
332 __debugbreak();
333 //if (Resample(next_frame->avframe, next_frame->avframe->channel_layout, next_frame->avframe->sample_rate,
334 // av_get_default_channel_layout(2), next_frame->avframe->sample_rate, AV_SAMPLE_FMT_S16P, resampled_data))
335 }
336 }
337
338
339
340 bool DecodeAudioFrame(AVCodecContext *dec_ctx, AVPacket *avpacket, AVFrame *avframe, MemoryStream *out_audio_data, int *out_num_audio_samples)
341 {
342 volatile int decoded = false;
343 do
344 {
345 if (avcodec_decode_audio4(dec_ctx, avframe, (int *)&decoded, avpacket) < 0)
346 {
347 log("Cannot decode audio frame\n");
348 return false;
349 }
350
351 if (!decoded)
352 log("Cannot decode audio frame in one piece\n");
353 } while (!decoded);
354
355 switch (dec_ctx->codec_id)
356 {
357 case AV_CODEC_ID_BINKAUDIO_RDFT:
358 {//pts samples dpts
359 // 0 960
360 //17280 960 17280 18x960
361 //18240 960 960 1x960
362 //20160 960 1920 2x960
363 //21120 960 960 1x960
364 //23040 960 1920 2x960
365 static int bink_next_pts = 0;
366
367 // there's a gap in the sound - fill empty samples in
368 if (bink_next_pts < avpacket->pts)
369 {
370 short silence[1024];
371 memset(silence, 0, sizeof(silence));
372
373 int samples_to_fill = /*dec_ctx->channels * */(avpacket->pts - bink_next_pts);
374 while (samples_to_fill > 0)
375 {
376 int samples_to_fill_this_step = samples_to_fill >= 1024 ? 1024 : samples_to_fill;
377 out_audio_data->Write(silence, samples_to_fill_this_step * sizeof(short));
378
379 samples_to_fill -= samples_to_fill_this_step;
380 }
381 }
382
383 bink_next_pts = avpacket->pts + /*dec_ctx->channels * */avframe->nb_samples;
384 }
385 break;
386 /*
387 case AV_CODEC_ID_SMACKAUDIO:
388 {
389 static int smack_debug_next_audio_time = 0;
390 if (smack_debug_next_audio_time != packet->pts)
391 {
392 Error("There's a gap in the sound before frame %u\n", num_audio_frames);
393 __debugbreak(); // there's a gap in the sound
394 }
395
396 int num_actual_data_channels = 0;
397 switch (dec_ctx->sample_fmt)
398 {
399 case AV_SAMPLE_FMT_U8:
400 case AV_SAMPLE_FMT_S16:
401 case AV_SAMPLE_FMT_S32:
402 case AV_SAMPLE_FMT_FLT:
403 case AV_SAMPLE_FMT_DBL:
404 num_actual_data_channels = 1;
405 break;
406
407 case AV_SAMPLE_FMT_U8P:
408 case AV_SAMPLE_FMT_S16P:
409 case AV_SAMPLE_FMT_S32P:
410 case AV_SAMPLE_FMT_FLTP:
411 case AV_SAMPLE_FMT_DBLP:
412 num_actual_data_channels = dec_ctx->channels;
413 break;
414
415 default:
416 case AV_SAMPLE_FMT_NONE:
417 case AV_SAMPLE_FMT_NB:
418 __debugbreak();
419 }
420
421 smack_debug_next_audio_time += dec_ctx->channels * frame->nb_samples * bytes_per_sample;
422 Assert(frame->avframe->linesize[0] == audio.dec_ctx->channels * frame->avframe->nb_samples * audio.bytes_per_sample / num_actual_data_channels,
423 "Smack audio size mismatch in frame %u in %s\n", audio_num_read_frames, movie_filename);
424
425 frame->play_time = (double)frame->avpacket->pts / (double)audio.bytes_per_second;
426 }
427 break;
428
429 case AV_CODEC_ID_MP3:
430 {
431 static int mp3_samples_decoded_so_far = 0;
432 static int mp3_prev_samples_count = frame->avframe->nb_samples; // mp3 seems to always feed same amount of samples
433 frame->play_time = (double)mp3_samples_decoded_so_far / (double)audio.dec_ctx->sample_rate;
434
435 mp3_samples_decoded_so_far += frame->avframe->nb_samples;
436 Assert(mp3_prev_samples_count == frame->avframe->nb_samples,
437 "MP3 audio have variable sample count in frame %u in %s\n", audio_num_read_frames, movie_filename);
438 }
439 break;
440
441 default:
442 {
443 __debugbreak();
444 double samples_per_second = (double)audio.dec_ctx->time_base.den / (double)audio.dec_ctx->time_base.num;
445 double play_length = frame->avframe->nb_samples / samples_per_second;
446 frame->play_time = (double)frame->avpacket->pts / samples_per_second;
447 }
448 break;*/
449 }
450
451 if (!avframe->channel_layout)
452 {
453 log("Audio channel layout not specified, rolling back to default\n");
454 avframe->channel_layout = av_get_default_channel_layout(dec_ctx->channels);
455 }
456
457 *out_num_audio_samples = dec_ctx->channels * avframe->nb_samples;
458 InterleaveAudioData(out_audio_data, dec_ctx->sample_fmt,
459 dec_ctx->channels, avframe->nb_samples, avframe->data);
460 return true;
461 }
462
463
464 bool LoadAudioTrack(AVFormatContext *format_ctx, AVCodecContext *dec_ctx, int audio_stream_idx, MemoryStream *out_audio_stream, int *out_num_audio_frames, int *out_num_audio_samples)
465 {
466 out_audio_stream->Reset();
467
468 AVFrame *frame = avcodec_alloc_frame();
469 AVPacket *packet = new AVPacket;
470 av_init_packet(packet);
471
472 int num_audio_frames = 0;
473 int num_audio_samples = 0;
474 while (av_read_frame(format_ctx, packet) >= 0)
475 {
476 if (packet->stream_index != audio_stream_idx)
477 {
478 //log("Suspicious stream id %u in %s", packet->stream_index, filenamea);
479 continue;
480 }
481
482 int num_samples_decoded;
483 DecodeAudioFrame(dec_ctx, packet, frame, out_audio_stream, &num_samples_decoded);
484
485 num_audio_samples += num_samples_decoded;
486 num_audio_frames++;
487 }
488 *out_num_audio_frames = num_audio_frames;
489 *out_num_audio_samples = num_audio_samples;
490
491 avcodec_free_frame(&frame);
492 delete packet;
493
494 return true;
495 }
496
497
498 class Track: public Media::ITrack
499 {
500 public:
501 inline Track()
502 {
503 this->format_ctx = nullptr;
504 this->audio_num_samples = 0;
505 }
506
507 void Release()
508 {
509 ReleaseAvcodec();
510 }
511
512 void ReleaseAvcodec()
513 {
514 audio.Release();
515 if (format_ctx)
516 {
517 av_close_input_file(format_ctx);
518 format_ctx = nullptr;
519 }
520 }
521
522 bool Load(const wchar_t *filename)
523 {
524 char filenamea[1024];
525 sprintf(filenamea, "%S", filename);
526
527 if (avformat_open_input(&format_ctx, filenamea, nullptr, nullptr) >= 0)
528 {
529 if (avformat_find_stream_info(format_ctx, nullptr) >= 0)
530 {
531 av_dump_format(format_ctx, 0, filenamea, 0);
532
533 if (!av_open_audio_stream(format_ctx, &audio))
534 {
535 Error("Cannot open strack: %s", filenamea);
536 return Release(), false;
537 }
538
539 MemoryStream audio_plain_data;
540 int num_audio_frames;
541 int num_audio_samples;
542 if (LoadAudioTrack(format_ctx, audio.dec_ctx, audio.stream_idx, &audio_plain_data, &num_audio_frames, &num_audio_samples))
543 {
544 /*#ifdef _DEBUG
545 char debug_filename[1024];
546 sprintf(debug_filename, "%s.wav", filenamea);
547 FILE *wav = fopen(debug_filename, "w+b");
548
549 extern void write_wav_header(FILE *wav, int channel_count = 2, int sample_rate = 22050, int bytes_per_sample = 2);
550 write_wav_header(wav, audio.dec_ctx->channels, audio.dec_ctx->sample_rate, audio.bytes_per_sample);
551
552 fwrite(audio_plain_data.Ptr(), audio_plain_data.Current(), 1, wav);
553
554 extern void fix_wav_header(FILE *wav, int wav_bytes_in_stream);
555 fix_wav_header(wav, audio_plain_data.Current());
556 #endif*/
557
558 device_buffer = provider->CreateTrack16(audio.dec_ctx->channels, audio.dec_ctx->sample_rate, 2, num_audio_samples, audio_plain_data.Ptr());
559
560 ReleaseAvcodec();
561 return true;
562 }
563 }
564 Release();
565 }
566 return false;
567 }
568
569 virtual void Play(bool loop)
570 {
571 provider->PlayTrack16(device_buffer, loop);
572 }
573
574
575 protected:
576 AVFormatContext *format_ctx;
577 AVAudioStream audio;
578 int audio_num_samples;
579
580 OpenALSoundProvider::TrackBuffer *device_buffer;
581 };
582
583
584
585 class Movie: public Media::IMovie
586 {
587 public:
588 inline Movie()
589 {
590 this->movie_filename[0] = 0;
591 this->width = 0;
592 this->height = 0;
593 this->format_ctx = nullptr;
594 this->end_of_file = false;
595 this->playback_time = 0.0;
596
597 this->num_audio_frames = 0;
598 this->num_audio_samples = 0;
599
600 this->last_resampled_frame_num = -1;
601 memset(last_resampled_frame_data, 0, sizeof(last_resampled_frame_data));
602 memset(last_resampled_frame_linesize, 0, sizeof(last_resampled_frame_linesize));
603 }
604
605
606 inline void Release()
607 {
608 ReleaseAVCodec();
609 }
610
611 inline void ReleaseAVCodec()
612 {
613 audio.Release();
614 video.Release();
615 if (format_ctx)
616 {
617 av_close_input_file(format_ctx);
618 format_ctx = nullptr;
619 }
620 }
621
622 bool Load(const wchar_t *filename, int dst_width, int dst_height, int cache_ms)
623 {
624 char filenamea[1024];
625 sprintf(filenamea, "%S", filename);
626 sprintf(movie_filename, "%S", filename);
627
628 width = dst_width;
629 height = dst_height;
630 if (avformat_open_input(&format_ctx, filenamea, nullptr, nullptr) >= 0)
631 {
632 if (avformat_find_stream_info(format_ctx, nullptr) >= 0)
633 {
634 av_dump_format(format_ctx, 0, filenamea, 0);
635
636 if (!av_open_audio_stream(format_ctx, &audio))
637 {
638 Error("Cannot open audio stream: %s", filenamea);
639 return Release(), false;
640 }
641
642 if (!av_open_video_stream(format_ctx, &video))
643 {
644 Error("Cannot open video stream: %s", filenamea);
645 return Release(), false;
646 }
647
648 decoding_packet = new AVPacket;
649 av_init_packet(decoding_packet);
650
651 decoding_frame = avcodec_alloc_frame();
652
653 audio_data_in_device = provider->CreateStreamingTrack16(audio.dec_ctx->channels, audio.dec_ctx->sample_rate, 2);
654
655 return true;
656 }
657 }
658 return false;
659 }
660
661 virtual void Play()
662 {
663 }
664
665 virtual void GetNextFrame(double dt, void *dst_surface)
666 {
667 playback_time += dt;
668
669 AVPacket *avpacket = decoding_packet;
670 AVFrame *avframe = decoding_frame;
671 avcodec_get_frame_defaults(avframe);
672
673 int desired_frame_number = floor(playback_time * video.dec_ctx->time_base.den / video.dec_ctx->time_base.num + 0.5);
674 if (last_resampled_frame_num == desired_frame_number)
675 {
676 memcpy(dst_surface, last_resampled_frame_data[0], height * last_resampled_frame_linesize[0]);
677 return;
678 }
679
680 volatile int decoded = false;
681 do
682 {
683 if (av_read_frame(format_ctx, avpacket) < 0)
684 {
685 // probably movie is finished
686 __debugbreak();
687 }
688
689 // audio packet - queue into playing
690 if (avpacket->stream_index == audio.stream_idx)
691 {
692 MemoryStream audio_data;
693 if (DecodeAudioFrame(audio.dec_ctx, avpacket, avframe, &audio_data, &num_audio_samples))
694 provider->Stream16(audio_data_in_device, num_audio_samples, audio_data.Ptr());
695 }
696 // video packet - decode & maybe show
697 else if (avpacket->stream_index == video.stream_idx)
698 {
699 do
700 {
701 if (avcodec_decode_video2(video.dec_ctx, avframe, (int *)&decoded, avpacket) < 0)
702 __debugbreak();
703 } while (!decoded);
704 }
705
706 } while (avpacket->stream_index != video.stream_idx ||
707 avpacket->pts != desired_frame_number);
708
709 if (decoded)
710 {
711 if (last_resampled_frame_data[0])
712 av_freep(&last_resampled_frame_data[0]);
713
714 AVPixelFormat rescaled_format = AV_PIX_FMT_RGB32;
715 uint8_t *rescaled_data[4] = {nullptr, nullptr, nullptr, nullptr};
716 int rescaled_linesize[4] = {0, 0, 0, 0};
717 if (av_image_alloc(rescaled_data, rescaled_linesize, width, height, rescaled_format, 1) >= 0)
718 {
719 SwsContext *converter = sws_getContext(avframe->width, avframe->height, (AVPixelFormat)avframe->format,
720 width, height, rescaled_format,
721 SWS_BICUBIC, nullptr, nullptr, nullptr);
722 sws_scale(converter, avframe->data, avframe->linesize, 0, avframe->height, rescaled_data, rescaled_linesize);
723 sws_freeContext(converter);
724
725 memcpy(dst_surface, rescaled_data[0], height * rescaled_linesize[0]);
726
727 last_resampled_frame_num = desired_frame_number;
728 memcpy(last_resampled_frame_data, rescaled_data, sizeof(rescaled_data));
729 memcpy(last_resampled_frame_linesize, rescaled_linesize, sizeof(rescaled_linesize));
730 }
731 }
732 else
733 memset(dst_surface, 0, width * height * 4);
734 }
735
736 protected:
737 char movie_filename[256];
738 int width;
739 int height;
740 AVFormatContext *format_ctx;
741 double playback_time;
742 bool end_of_file;
743
744 AVPacket *decoding_packet;
745 AVFrame *decoding_frame;
746
747 AVAudioStream audio;
748 int num_audio_frames;
749 int num_audio_samples;
750 OpenALSoundProvider::StreamingTrackBuffer *audio_data_in_device;
751
752 AVVideoStream video;
753 int last_resampled_frame_num;
754 uint8_t *last_resampled_frame_data[4];
755 int last_resampled_frame_linesize[4];
756 };
757
758
759 ITrack *Player::LoadTrack(const wchar_t *filename)
760 {
761 auto track = new Track;
762 if (!track->Load(filename))
763 {
764 delete track;
765 track = nullptr;
766 }
767 return track;
768 }
769
770
771 IMovie *Player::LoadMovie(const wchar_t *filename, int width, int height, int cache_ms)
772 {
773 auto movie = new Movie;
774 if (!movie->Load(filename, width, height, cache_ms))
775 {
776 delete movie;
777 movie = nullptr;
778 }
779 return movie;
780 }
781
782
783
784
785
786
787 void av_logger(void *, int, const char *format, va_list args)
788 {
789 va_list va;
790 va_start(va, format);
791 char msg[256];
792 vsprintf(msg, format, va);
793 va_end(va);
794
795 log("av: %s", msg);
796 }
797
798 Player::Player()
799 {
800 static int libavcodec_initialized = false;
801
802 if (!libavcodec_initialized)
803 {
804 av_log_set_callback(av_logger);
805 avcodec_register_all();
806 av_register_all();
807
808 libavcodec_initialized = true;
809 }
810
811 if (!provider)
812 {
813 provider = new OpenALSoundProvider;
814 provider->Initialize();
815 }
816 }
817
818 Player::~Player()
819 {
820 }