comparison MediaPlayer.cpp @ 2324:b2e3ac05f2b3

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