Mercurial > mm7
annotate VideoPlayer.h @ 2254:2e02c384c62b
Merge
author | Grumpy7 |
---|---|
date | Wed, 26 Feb 2014 23:35:46 +0100 |
parents | c69013c186c7 |
children | d65414f65bd4 |
rev | line source |
---|---|
0 | 1 #pragma once |
1802 | 2 #include "OSWindow.h" |
1262 | 3 #include "Texture.h" |
0 | 4 |
5 | |
6 | |
7 | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
8 |
0 | 9 #pragma pack(push, 1) |
10 | |
11 | |
12 | |
13 struct _BINK | |
14 { | |
15 int uWidth; | |
16 int uHeight; | |
17 }; | |
18 | |
19 struct _BINK_1_5_21_0: public _BINK | |
20 { | |
21 int uNumFrames; | |
22 int uCurrentFrame; | |
23 int Data1; | |
24 int uFrameRate; | |
25 int field_18[3]; | |
26 int uFlags; | |
27 }; | |
28 | |
29 struct _BINK_3_0_0_0: public _BINK | |
30 { | |
31 int unk_0; | |
32 int unk_1; | |
33 int uNumFrames; | |
34 int uCurrentFrame; | |
35 int _unk2; | |
36 int _unk_[10]; | |
37 }; | |
38 | |
39 | |
40 struct _BINKBUF | |
41 { | |
42 int uWidth; | |
43 int uHeight; | |
44 int field_8; | |
45 int field_C; | |
46 int uBinkDDSurfaceType; | |
47 void *pDDrawSurfaceData; | |
48 int uDDrawSurfacePitch; | |
49 int field_1C; | |
50 int field_20; | |
1802 | 51 int target_width; |
52 int target_height; | |
0 | 53 int field_2C; |
54 int field_30; | |
55 int field_34; | |
56 int field_38; | |
57 int field_3C; | |
58 int field_40; | |
59 int field_44; | |
60 struct IDirectDrawSurface *pTargetDDrawSurface; | |
61 int field_4C; | |
62 int uRectX; | |
63 int uRectY; | |
64 HWND hWnd; | |
65 int field_5C; | |
66 float field_60; | |
67 float field_64; | |
68 int field_68; | |
69 int field_6C; | |
70 void *pDDrawSurfaceData_; | |
71 int field_74; | |
72 int field_78; | |
73 }; | |
74 struct _BINKBUF_1_5_21_0: public _BINKBUF | |
75 { | |
76 int field_7C; | |
77 int field_80; | |
78 int field_84; | |
79 int field_88; | |
80 int field_8C; | |
81 int field_90; | |
82 int field_94; | |
83 int field_98; | |
84 int field_9C; | |
85 int field_A0; | |
86 }; | |
87 | |
88 struct _BINKBUF_3_0_0_0: public _BINKBUF | |
89 { | |
90 }; | |
91 #pragma pack(pop) | |
92 | |
93 | |
94 | |
95 | |
96 #pragma pack(push, 1) | |
97 struct MovieHeader | |
98 { | |
99 char pVideoName[40]; | |
100 unsigned int uFileOffset; | |
101 }; | |
102 #pragma pack(pop) | |
103 | |
104 | |
105 | |
106 | |
107 | |
1458 | 108 void ShowIntroVideo_and_LoadingScreen(); |
0 | 109 |
2134 | 110 extern "C" |
111 { | |
112 #include "lib/libavcodec/avcodec.h" | |
113 #include "lib/libavformat/avformat.h" | |
114 #include "lib/libavutil/avutil.h" | |
115 #include "lib/libavutil/imgutils.h" | |
116 #include "lib/libswscale/swscale.h" | |
117 #include "lib/libswresample/swresample.h" | |
118 #include "lib/libavutil/opt.h" | |
119 //#include "libavutil/samplefmt.h" | |
120 } | |
121 #pragma comment(lib, "avcodec.lib") | |
122 #pragma comment(lib, "avformat.lib") | |
123 #pragma comment(lib, "avutil.lib") | |
124 #pragma comment(lib, "swscale.lib") | |
125 #pragma comment(lib, "swresample.lib") | |
126 | |
127 #include "lib/OpenAL/al.h" | |
128 #include "lib/OpenAL/alc.h" | |
129 #pragma comment(lib, "OpenAL32.lib") | |
130 | |
131 | |
132 | |
133 template<int MAX_SAMPLES_BUFFERS> | |
134 class OpenALSoundProviderGeneric | |
135 { | |
136 public: | |
137 inline OpenALSoundProviderGeneric() | |
138 { | |
139 this->device = nullptr; | |
140 this->context = nullptr; | |
141 this->samples_current_buffer = 0; | |
142 | |
143 this->samples_source_id = -1; | |
144 for (int i = 0; i < MAX_SAMPLES_BUFFERS; ++i) | |
145 samples_buffer_id[i] = -1; | |
146 } | |
147 | |
148 inline bool Initialize() | |
149 { | |
150 auto device_names = alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER); | |
151 if (!device_names) | |
152 device_names = alcGetString(nullptr, ALC_DEVICE_SPECIFIER); | |
153 if (device_names) | |
154 { | |
155 for (auto device_name = device_names; device_name[0]; device_name += strlen(device_name)) | |
156 { | |
157 continue; | |
158 } | |
159 } | |
160 | |
161 device = alcOpenDevice(nullptr); | |
162 if (!device || CheckError()) | |
163 return false; | |
164 | |
165 context = alcCreateContext(device, nullptr); | |
166 if (!context || CheckError()) | |
167 return Release(), false; | |
168 | |
169 alcMakeContextCurrent(context); | |
170 | |
171 bool eax2 = alIsExtensionPresent("EAX2.0"); | |
172 bool eax3 = alIsExtensionPresent("EAX3.0"); | |
173 bool eax4 = alIsExtensionPresent("EAX4.0"); | |
174 bool eax5 = alIsExtensionPresent("EAX5.0"); | |
175 | |
176 auto vendor = alGetString(AL_VERSION); | |
177 auto version = alGetString(AL_VERSION); | |
178 auto extensions = alcGetString(device, ALC_EXTENSIONS); | |
179 | |
180 alGenBuffers(MAX_SAMPLES_BUFFERS, samples_buffer_id); | |
181 if (CheckError()) | |
182 return Release(), false; | |
183 | |
184 alGenSources(1, &samples_source_id); | |
185 if (CheckError()) | |
186 return Release(), false; | |
187 | |
188 float sound_pos[] = { 0.0f, 0.0f, 0.0f }; | |
189 alSourcefv(samples_source_id, AL_POSITION, sound_pos); | |
190 alSourcei(samples_source_id, AL_LOOPING, AL_FALSE); | |
191 | |
192 return true; | |
193 } | |
194 | |
195 void Release() | |
196 { | |
197 if (samples_source_id != -1) | |
198 { | |
199 alDeleteSources(1, &samples_source_id); | |
200 samples_source_id = -1; | |
201 } | |
202 | |
203 for (int i = 0; i < MAX_SAMPLES_BUFFERS; ++i) | |
204 { | |
205 if (samples_buffer_id[i] != -1) | |
206 alDeleteBuffers(1, &samples_buffer_id[i]); | |
207 samples_buffer_id[i] = -1; | |
208 } | |
209 | |
210 alcMakeContextCurrent(nullptr); | |
211 if (context) | |
212 { | |
213 alcDestroyContext(context); | |
214 context = nullptr; | |
215 } | |
216 if (device) | |
217 { | |
218 alcCloseDevice(device); | |
219 device = nullptr; | |
220 } | |
221 } | |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | |
229 | |
230 void PlaySample(int num_channels, int sample_rate, int num_samples, void *samples) | |
231 { | |
232 //char msg[256];sprintf(msg, "chan %u rate %5u num %5u ptr %p\n", num_channels, sample_rate, num_samples, samples); | |
233 //log(msg); | |
234 ALenum sound_format; | |
235 switch (num_channels) | |
236 { | |
237 case 1: sound_format = AL_FORMAT_MONO16; break; | |
238 case 2: sound_format = AL_FORMAT_STEREO16; break; | |
239 default: | |
240 if (bool multichannel = alIsExtensionPresent("AL_EXT_MCFORMATS")) | |
241 { | |
242 switch (num_channels) | |
243 { | |
244 case 4: sound_format = alGetEnumValue("AL_FORMAT_QUAD16"); break; | |
245 case 6: sound_format = alGetEnumValue("AL_FORMAT_51CHN16"); break; | |
246 case 7: sound_format = alGetEnumValue("AL_FORMAT_61CHN16"); break; | |
247 case 8: sound_format = alGetEnumValue("AL_FORMAT_71CHN16"); break; | |
248 } | |
249 } | |
250 __debugbreak(); | |
251 } | |
252 | |
253 float listener_pos[] = { 0.0f, 0.0f, 0.0f }; | |
254 float listener_vel[] = { 0.0f, 0.0f, 0.0f }; | |
255 float listener_orientation[] = { 0.0f, 0.0f, -1.0f, // direction | |
256 0.0f, 1.0f, 0.0f }; // up vector | |
257 alListenerfv(AL_POSITION, listener_pos); | |
258 alListenerfv(AL_VELOCITY, listener_vel); | |
259 alListenerfv(AL_ORIENTATION, listener_orientation); | |
260 | |
261 unsigned int *next_buffer = samples_buffer_id + samples_current_buffer; | |
262 | |
263 alBufferData(*next_buffer, sound_format, samples, num_samples * sizeof(__int16), sample_rate); | |
264 CheckError(); | |
265 | |
266 | |
267 int num_processed_buffers; | |
268 alGetSourcei(samples_source_id, AL_BUFFERS_PROCESSED, &num_processed_buffers); | |
2208 | 269 /*while (num_processed_buffers) |
2134 | 270 { |
271 unsigned int processed_buffers_id[4]; | |
272 alSourceUnqueueBuffers(samples_source_id, min(4, num_processed_buffers), processed_buffers_id); | |
273 CheckError(); | |
274 alGetSourcei(samples_source_id, AL_BUFFERS_PROCESSED, &num_processed_buffers); | |
2208 | 275 }*/ |
276 for (int i = 0; i < num_processed_buffers; ++i) | |
277 { | |
278 unsigned int processed_buffer_id; | |
279 alSourceUnqueueBuffers(samples_source_id, 1, &processed_buffer_id); | |
280 if (!CheckError()) | |
281 alDeleteBuffers(1, &processed_buffer_id); | |
282 } | |
2134 | 283 |
284 int num_queued_buffers; | |
285 alGetSourcei(samples_source_id, AL_BUFFERS_QUEUED, &num_queued_buffers); | |
286 if (num_queued_buffers >= MAX_SAMPLES_BUFFERS) | |
287 { | |
288 __debugbreak(); | |
289 } | |
290 | |
291 alSourceQueueBuffers(samples_source_id, 1, next_buffer); | |
292 CheckError(); | |
293 | |
294 int status; | |
295 alGetSourcei(samples_source_id, AL_SOURCE_STATE, &status); | |
296 if (status != AL_PLAYING) | |
297 { | |
298 alSourcePlay(samples_source_id); | |
299 CheckError(); | |
300 } | |
301 | |
302 if (++samples_current_buffer >= MAX_SAMPLES_BUFFERS) | |
303 samples_current_buffer = 0; | |
304 } | |
305 | |
306 | |
307 | |
308 protected: | |
309 ALCdevice *device; | |
310 ALCcontext *context; | |
311 unsigned int samples_buffer_id[MAX_SAMPLES_BUFFERS]; | |
312 unsigned int samples_source_id; | |
313 int samples_current_buffer; | |
314 | |
315 | |
316 bool CheckError() | |
317 { | |
318 ALenum code = alcGetError(device); | |
319 if (code != ALC_NO_ERROR) | |
320 { | |
321 DWORD w; | |
322 const char *message = alcGetString(device, code); | |
323 WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), message, lstrlenA(message), &w, nullptr); | |
324 return true; | |
325 } | |
326 return false; | |
327 } | |
328 }; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
329 typedef OpenALSoundProviderGeneric<64> OpenALSoundProvider; |
2134 | 330 |
331 | |
332 | |
333 void av_logger(void *, int, const char *format, va_list args); | |
334 | |
335 | |
336 | |
337 #include <memory> | |
338 using std::tr1::shared_ptr; | |
339 using std::tr1::make_shared; | |
340 | |
341 class MultimediaFrame | |
342 { | |
343 public: | |
344 typedef shared_ptr<MultimediaFrame> Ptr; | |
345 inline MultimediaFrame(AVMediaType type, AVPacket *packet, AVCodecContext *dec_ctx) | |
346 { | |
347 this->type = type; | |
348 this->f = nullptr; | |
349 this->p = packet; | |
350 this->dec_ctx = dec_ctx; | |
351 } | |
352 virtual ~MultimediaFrame() { return; } | |
353 | |
354 | |
355 AVMediaType Type() const { return type; } | |
356 AVFrame *GetAVFrame() { return f; } | |
357 | |
358 virtual int Decode() = 0; | |
359 virtual void *GetData() = 0; | |
360 virtual int GetDataPitch() = 0; | |
361 | |
362 | |
363 protected: | |
364 AVMediaType type; | |
365 AVFrame *f; | |
366 AVPacket *p; | |
367 AVCodecContext *dec_ctx; | |
368 }; | |
369 | |
370 | |
371 | |
372 class MultimediaVideoFrame : public MultimediaFrame | |
373 { | |
374 public: | |
375 inline MultimediaVideoFrame(AVMediaType type, AVPacket *packet, AVCodecContext *dec_ctx, int width, int height) : | |
376 MultimediaFrame(type, packet, dec_ctx) | |
377 { | |
378 this->width = width; | |
379 this->height = height; | |
380 this->rescaled_data[0] = nullptr; | |
381 this->rescaled_linesize[0] = 0; | |
382 } | |
383 virtual ~MultimediaVideoFrame() | |
384 { | |
385 av_freep(&rescaled_data); | |
386 av_frame_free(&f); | |
387 } | |
388 | |
389 int Decode() override | |
390 { | |
391 f = avcodec_alloc_frame(); | |
392 avcodec_get_frame_defaults(f); | |
393 | |
394 volatile int done = false; | |
395 do | |
396 { | |
397 int ret; | |
398 if ((ret = avcodec_decode_video2(dec_ctx, f, (int *)&done, p)) < 0) | |
399 return ret; | |
400 } while (!done); | |
401 if (Rescale(f, width, height, AV_PIX_FMT_RGB32, rescaled_data, rescaled_linesize)) | |
402 return 0; | |
403 else return -1; | |
404 } | |
405 | |
406 virtual void *GetData() { return rescaled_data[0]; } | |
407 virtual int GetDataPitch() { return rescaled_linesize[0]; } | |
408 | |
409 protected: | |
410 int width; | |
411 int height; | |
412 uint8_t *rescaled_data[8]; | |
413 int rescaled_linesize[8]; | |
414 | |
415 bool Rescale(AVFrame *frame, int dst_width, int dst_height, AVPixelFormat format, uint8_t **out_data, int *out_linesize) | |
416 { | |
417 if (av_image_alloc(out_data, out_linesize, dst_width, dst_height, format, 1) < 0) | |
418 return false; | |
419 | |
420 SwsContext *converter = sws_getContext(frame->width, frame->height, (AVPixelFormat)frame->format, | |
421 dst_width, dst_height, format, | |
422 SWS_BICUBIC, nullptr, nullptr, nullptr); | |
423 sws_scale(converter, frame->data, frame->linesize, 0, frame->height, out_data, out_linesize); | |
424 sws_freeContext(converter); | |
425 | |
426 return true; | |
427 } | |
428 }; | |
429 | |
430 | |
431 | |
432 class MultimediaAudioFrame : public MultimediaFrame | |
433 { | |
434 public: | |
435 inline MultimediaAudioFrame(AVMediaType type, AVPacket *packet, AVCodecContext *dec_ctx) : | |
436 MultimediaFrame(type, packet, dec_ctx) | |
437 { | |
438 this->resampled_data = nullptr; | |
439 } | |
440 virtual ~MultimediaAudioFrame() | |
441 { | |
442 av_free(resampled_data); | |
443 av_frame_free(&f); | |
444 } | |
445 | |
446 int Decode() override | |
447 { | |
448 f = avcodec_alloc_frame(); | |
449 avcodec_get_frame_defaults(f); | |
450 | |
451 volatile int done = false; | |
452 do | |
453 { | |
454 int ret; | |
455 if ((ret = avcodec_decode_audio4(dec_ctx, f, (int *)&done, p)) < 0) | |
456 return ret; | |
457 } while (!done); | |
458 if (Resample(f, f->channel_layout, f->sample_rate, | |
459 f->channel_layout, f->sample_rate, AV_SAMPLE_FMT_S16, &resampled_data)) | |
460 return 0; | |
461 else return -1; | |
462 } | |
463 | |
464 virtual void *GetData() { return resampled_data; } | |
465 virtual int GetDataPitch() { return 2 * f->nb_samples; } | |
466 | |
467 protected: | |
468 uint8_t *resampled_data; | |
469 | |
470 bool Resample(AVFrame *frame, | |
471 int64_t src_channel_layout, int src_sample_rate, | |
472 int64_t dst_channel_layout, int dst_sample_rate, AVSampleFormat dst_format, uint8_t **out_data) | |
473 { | |
474 SwrContext *converter = swr_alloc(); | |
475 | |
476 av_opt_set_int(converter, "in_channel_layout", src_channel_layout, 0); | |
477 av_opt_set_int(converter, "in_sample_rate", src_sample_rate, 0); | |
478 av_opt_set_sample_fmt(converter, "in_sample_fmt", (AVSampleFormat)frame->format, 0); | |
479 | |
480 av_opt_set_int(converter, "out_channel_layout", dst_channel_layout, 0); | |
481 av_opt_set_int(converter, "out_sample_rate", dst_sample_rate, 0); | |
482 av_opt_set_sample_fmt(converter, "out_sample_fmt", dst_format, 0); | |
483 | |
484 if (swr_init(converter) < 0) | |
485 return false; | |
486 | |
487 int dst_nb_samples; | |
488 int max_dst_nb_samples = dst_nb_samples = av_rescale_rnd(frame->nb_samples, dst_sample_rate, src_channel_layout, AV_ROUND_UP); | |
489 | |
490 uint8_t **dst_data; | |
491 int dst_linesize; | |
492 int dst_nb_channels = av_get_channel_layout_nb_channels(dst_channel_layout); | |
493 if (av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_format, 0) < 0) | |
494 { | |
495 swr_free(&converter); | |
496 return false; | |
497 } | |
498 | |
499 dst_nb_samples = av_rescale_rnd(swr_get_delay(converter, src_sample_rate) + frame->nb_samples, dst_sample_rate, src_sample_rate, AV_ROUND_UP); | |
500 if (dst_nb_samples > max_dst_nb_samples) | |
501 { | |
502 av_free(dst_data[0]); | |
503 if (av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_format, 1) < 0) | |
504 { | |
505 swr_free(&converter); | |
506 return false; | |
507 } | |
508 max_dst_nb_samples = dst_nb_samples; | |
509 } | |
510 | |
511 | |
512 if (swr_convert(converter, dst_data, dst_nb_samples, (const uint8_t **)frame->data, frame->nb_samples) < 0) | |
513 { | |
514 av_free(dst_data[0]); | |
515 swr_free(&converter); | |
516 return false; | |
517 } | |
518 | |
519 *out_data = dst_data[0]; | |
520 return true; | |
521 } | |
522 }; | |
523 | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
524 int readFunction(void* opaque, uint8_t* buf, int buf_size); |
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
525 |
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
526 int64_t seekFunction(void* opaque, int64_t offset, int whence); |
2134 | 527 |
528 template<int NUM_PRECACHED_FRAMES> | |
529 class MovieCached | |
530 { | |
531 public: | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
532 bool Stopped() { return stopped; } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
533 int GetWidth() { return width; } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
534 int GetHeight() { return height; } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
535 inline ~MovieCached() |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
536 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
537 Release(); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
538 } |
2134 | 539 protected: |
540 friend class MultimediaPlayer; | |
541 inline MovieCached(OpenALSoundProvider *sound_provider) | |
542 { | |
543 this->format_ctx = nullptr; | |
544 this->sound_provider = sound_provider; | |
545 this->stopped = false; | |
546 | |
547 this->video_stream_idx = -1; | |
548 this->video_stream = nullptr; | |
549 this->video_stream_dec = nullptr; | |
550 this->video_stream_dec_ctx = nullptr; | |
551 | |
552 this->audio_stream_idx = -1; | |
553 this->audio_stream = nullptr; | |
554 this->audio_stream_dec = nullptr; | |
555 this->audio_stream_dec_ctx = nullptr; | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
556 |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
557 packet = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
558 ioBuffer = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
559 format_ctx = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
560 avioContext = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
561 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
562 |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
563 bool LoadFromLOD(HANDLE h, int readFunction(void*, uint8_t*, int), int64_t seekFunction(void*, int64_t, int), int width, int height) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
564 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
565 if (!ioBuffer) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
566 ioBuffer = (unsigned char *)av_malloc(16384 + FF_INPUT_BUFFER_PADDING_SIZE); // can get av_free()ed by libav |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
567 if (!avioContext) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
568 avioContext = avio_alloc_context(ioBuffer, 16384, 0, h, &readFunction, NULL, &seekFunction); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
569 if (!format_ctx) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
570 format_ctx = avformat_alloc_context(); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
571 format_ctx->pb = avioContext; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
572 return Load("dummyFilename", width, height); |
2134 | 573 } |
574 | |
575 bool Load(const char *video_filename, int width, int height) | |
576 { | |
577 this->width = width; | |
578 this->height = height; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
579 |
2134 | 580 if (avformat_open_input(&format_ctx, video_filename, nullptr, nullptr) >= 0) |
581 { | |
582 if (avformat_find_stream_info(format_ctx, nullptr) >= 0) | |
583 { | |
584 av_dump_format(format_ctx, 0, video_filename, 0); | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
585 |
2134 | 586 video_stream_idx = OpenStream(AVMEDIA_TYPE_VIDEO, &video_stream, &video_stream_dec, &video_stream_dec_ctx); |
587 if (video_stream_idx < 0) | |
588 return Release(), false; | |
2221 | 589 if (_stricmp("binkvideo", video_stream_dec->name) )//Ritor1: include |
590 { | |
591 this->width = video_stream_dec_ctx->width; | |
592 this->height = video_stream_dec_ctx->height; | |
593 } | |
2134 | 594 |
595 audio_stream_idx = OpenStream(AVMEDIA_TYPE_AUDIO, &audio_stream, &audio_stream_dec, &audio_stream_dec_ctx); | |
596 if (audio_stream_idx < 0) | |
597 return Release(), false; | |
598 | |
599 strcpy(movie_name, video_filename); | |
600 packet = new AVPacket; | |
601 av_init_packet(packet); | |
602 return true; | |
603 } | |
604 } | |
605 return Release(), false; | |
606 } | |
607 | |
608 bool Release() | |
609 { | |
610 if (packet) | |
611 { | |
612 av_free_packet(packet); | |
613 delete packet; | |
614 packet = nullptr; | |
615 } | |
616 | |
617 if (video_stream_idx >= 0) | |
618 { | |
619 video_stream_idx = -1; | |
620 video_stream = nullptr; | |
621 video_stream_dec = nullptr; | |
622 avcodec_close(video_stream_dec_ctx); | |
623 video_stream_dec_ctx = nullptr; | |
624 } | |
625 | |
626 if (audio_stream_idx >= 0) | |
627 { | |
628 audio_stream_idx = -1; | |
629 audio_stream = nullptr; | |
630 audio_stream_dec = nullptr; | |
631 avcodec_close(audio_stream_dec_ctx); | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
632 |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
633 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
634 if (avioContext) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
635 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
636 av_free(avioContext); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
637 avioContext = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
638 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
639 if (format_ctx) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
640 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
641 avformat_free_context(format_ctx); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
642 format_ctx = nullptr; |
2134 | 643 } |
644 return true; | |
645 } | |
646 | |
647 | |
648 int OpenStream(AVMediaType type, AVStream **out_stream, AVCodec **out_dec, AVCodecContext **out_dec_ctx) | |
649 { | |
650 int stream_idx = av_find_best_stream(format_ctx, type, -1, -1, nullptr, 0); | |
651 if (stream_idx < 0) | |
652 return stream_idx; | |
653 | |
654 auto stream = format_ctx->streams[stream_idx]; | |
655 auto dec_ctx = stream->codec; | |
656 auto dec = avcodec_find_decoder(dec_ctx->codec_id); | |
657 if (dec) | |
658 { | |
659 if (avcodec_open2(dec_ctx, dec, nullptr) >= 0) | |
660 { | |
661 *out_stream = stream; | |
662 *out_dec = dec; | |
663 *out_dec_ctx = dec_ctx; | |
664 return stream_idx; | |
665 } | |
666 } | |
667 return -1; | |
668 } | |
669 | |
670 MultimediaFrame::Ptr GetNextFrame() | |
671 { | |
672 packet->data = nullptr; | |
673 packet->size = 0; | |
674 | |
675 volatile int got_frame = false; | |
676 do | |
677 { | |
678 if (av_read_frame(format_ctx, packet) < 0) | |
679 { | |
680 stopped = true; | |
681 return nullptr; | |
682 } | |
683 } while (packet->stream_index != video_stream_idx && | |
684 packet->stream_index != audio_stream_idx); | |
685 | |
686 if (packet->stream_index == video_stream_idx) | |
687 return MultimediaFrame::Ptr(new MultimediaVideoFrame(AVMEDIA_TYPE_VIDEO, packet, video_stream_dec_ctx, width, height)); | |
688 else if (packet->stream_index == audio_stream_idx) | |
689 return MultimediaFrame::Ptr(new MultimediaAudioFrame(AVMEDIA_TYPE_AUDIO, packet, audio_stream_dec_ctx)); | |
690 return nullptr; | |
691 } | |
692 | |
693 | |
694 | |
695 char movie_name[256]; | |
696 int width; | |
697 int height; | |
698 bool stopped; | |
699 AVFormatContext *format_ctx; | |
700 //AVFrame *frame; | |
701 AVPacket *packet; | |
702 //MultimediaFrame *frames[NUM_PRECACHED_FRAMES]; | |
703 OpenALSoundProvider *sound_provider; | |
704 | |
705 int video_stream_idx; | |
706 AVStream *video_stream; | |
707 AVCodec *video_stream_dec; | |
708 AVCodecContext *video_stream_dec_ctx; | |
709 | |
710 int audio_stream_idx; | |
711 AVStream *audio_stream; | |
712 AVCodec *audio_stream_dec; | |
713 AVCodecContext *audio_stream_dec_ctx; | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
714 unsigned char * ioBuffer; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
715 AVIOContext *avioContext; |
2134 | 716 }; |
717 typedef MovieCached<10> Movie; | |
718 | |
719 | |
720 | |
721 | |
722 class MultimediaPlayer | |
723 { | |
724 public: | |
725 inline MultimediaPlayer() | |
726 { | |
727 } | |
728 | |
729 bool Initialize() | |
730 { | |
731 if (!libavcodec_initialized) | |
732 { | |
733 av_log_set_callback(Logger); | |
734 avcodec_register_all(); | |
735 av_register_all(); | |
736 | |
737 libavcodec_initialized = true; | |
738 } | |
739 | |
740 sound_provider = new OpenALSoundProvider; | |
741 sound_provider->Initialize(); | |
742 | |
743 return true; | |
744 } | |
745 | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
746 Movie *LoadMovieFromLOD(HANDLE h, int readFunction(void*, uint8_t*, int), int64_t seekFunction(void*, int64_t, int), int width, int height) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
747 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
748 auto movie = new Movie(sound_provider); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
749 if (movie) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
750 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
751 if (movie->LoadFromLOD(h, readFunction, seekFunction, width, height)) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
752 { |
2221 | 753 if (_stricmp("binkvideo", movie->video_stream_dec->name) ) |
754 { | |
755 current_movie_width = movie->video_stream_dec_ctx->width; | |
756 current_movie_height = movie->video_stream_dec_ctx->height; | |
757 } | |
758 else | |
759 { | |
760 current_movie_width = width; | |
761 current_movie_height = height; | |
762 } | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
763 return current_movie = movie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
764 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
765 delete movie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
766 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
767 return nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
768 } |
2134 | 769 |
770 Movie *LoadMovie(const char *filename, int width, int height) | |
771 { | |
772 auto movie = new Movie(sound_provider); | |
773 if (movie) | |
774 { | |
775 if (movie->Load(filename, width, height)) | |
776 { | |
777 current_movie_width = width; | |
778 current_movie_height = height; | |
779 return current_movie = movie; | |
780 } | |
781 delete movie; | |
782 } | |
783 return nullptr; | |
784 } | |
785 | |
786 inline char *DoFrame() | |
787 { | |
788 if (!current_movie) | |
789 return nullptr; | |
790 | |
791 while (true) | |
792 { | |
793 auto frame = current_movie->GetNextFrame(); | |
794 if (!frame) | |
795 return nullptr; | |
796 | |
797 if (frame->Type() == AVMEDIA_TYPE_AUDIO) | |
798 { | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
799 //continue; |
2134 | 800 uint8_t *data; |
801 if (frame->Decode() >= 0) | |
802 { | |
803 auto f = frame->GetAVFrame(); | |
804 sound_provider->PlaySample(f->channels, f->sample_rate, f->nb_samples, frame->GetData()); | |
805 Sleep(20); | |
806 continue; | |
807 } | |
808 } | |
809 else if (frame->Type() == AVMEDIA_TYPE_VIDEO) | |
810 { | |
811 uint8_t *dst_data[4] = { 0 }; | |
812 int dst_linesize[4] = { 0 }; | |
813 if (frame->Decode() >= 0) | |
814 { | |
815 auto image = new char[current_movie_width * current_movie_height * 4]; | |
816 memcpy(image, frame->GetData(), current_movie_height * frame->GetDataPitch()); | |
817 | |
818 return image; | |
819 } | |
820 } | |
821 return nullptr; | |
822 } | |
823 } | |
824 | |
825 | |
826 | |
827 protected: | |
828 static void Logger(void *, int, const char *format, va_list args); | |
829 | |
830 OpenALSoundProvider *sound_provider; | |
831 Movie *current_movie; | |
832 int current_movie_width; | |
833 int current_movie_height; | |
834 | |
835 static bool libavcodec_initialized; | |
836 }; | |
837 | |
838 | |
839 | |
0 | 840 |
841 | |
842 | |
843 #pragma pack(push, 1) | |
844 struct VideoPlayer | |
845 { | |
1262 | 846 VideoPlayer(); |
0 | 847 //----- (004BECBD) -------------------------------------------------------- |
848 virtual ~VideoPlayer() | |
849 { | |
850 bStopBeforeSchedule = false; | |
165 | 851 pResetflag = 0; |
0 | 852 pVideoFrame.Release(); |
853 } | |
854 | |
855 void PlayDeathMovie(); | |
856 unsigned int SmackCheckSurfaceFromat(); | |
1802 | 857 void Initialize(OSWindow *window); |
0 | 858 void Prepare(); |
859 void Unload(); | |
860 void FastForwardToFrame(unsigned int uFrameNum); | |
1802 | 861 void BinkDrawFrame(int a3, int a4); |
862 void BinkUpdatePalette() {} | |
863 void SmackDrawFrame(int a3, int a4); | |
864 void SmackUpdatePalette(); | |
0 | 865 _BINK *OpenBink(const char *pName); |
866 struct _SMACK *OpenSmack(const char *pFilename); | |
898 | 867 void OpenHouseMovie(const char *pMovieName, unsigned int a3_1);//0x4BF28F |
0 | 868 bool AnyMovieLoaded(); |
898 | 869 void OpenGlobalMovie(const char *pFilename, unsigned int bLoop, int a4); |
0 | 870 void _4BF5B2(); |
898 | 871 void SelectMovieType();//0x4BF73A |
1802 | 872 _BINKBUF *CreateBinkBuffer(unsigned int uWidth, unsigned int uHeight, char a4); |
873 void _inlined_in_463149(); | |
0 | 874 |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
875 void MovieLoop(const char *pMovieName, int a2, int a3, int a4); |
0 | 876 |
877 | |
878 RGBTexture pVideoFrame; | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
879 //struct _SMACK *pSmackerMovie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
880 //struct _SMACKBUF *pSmackerBuffer; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
881 //char *pSomeSmackerBuffer; |
0 | 882 int field_34; |
883 MovieHeader *pMightVideoHeaders; | |
884 MovieHeader *pMagicVideoHeaders; | |
165 | 885 int pResetflag; |
0 | 886 int field_44; |
887 unsigned int uNumMightVideoHeaders; | |
888 unsigned int uNumMagicVideoHeaders; | |
889 int uBinkDirectDrawSurfaceType; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
890 int bBufferLoaded; |
0 | 891 unsigned int bPlayingMovie; |
892 unsigned int bFirstFrame; | |
893 unsigned int bUsingSmackerMMX; | |
894 unsigned int bLoopPlaying; | |
895 int field_68; | |
896 unsigned int bStopBeforeSchedule; | |
1802 | 897 //HWND hWindow; |
898 OSWindow *window; | |
0 | 899 struct _SMACKBLIT *pSmackMovieBlit; |
900 HANDLE hMightVid; | |
901 HANDLE hMagicVid; | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
902 //_BINK *pBinkMovie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
903 //_BINKBUF *pBinkBuffer; |
0 | 904 char field_88[20]; |
905 unsigned int uMovieFormat; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
906 int uMovieFormatSwapped; |
0 | 907 char pCurrentMovieName[64]; |
908 char pVideoFrameTextureFilename[32]; | |
323 | 909 int field_104; |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
910 MultimediaPlayer *pPlayer; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
911 Movie *pMovie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
912 HANDLE hVidFile; |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
913 int uSize; |
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
914 int uOffset; |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
915 void UpdatePalette(); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
916 static int readFunction(void *, uint8_t *, int); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
917 static int64_t seekFunction(void *, int64_t, int); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
918 void LoadMovie(const char *); |
0 | 919 }; |
920 #pragma pack(pop) | |
921 | |
922 | |
923 | |
924 | |
925 | |
926 extern VideoPlayer *pVideoPlayer; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
927 extern LRESULT __stdcall wWinProc(HWND hwnd, unsigned int msg, WPARAM wparam, LPARAM lparam); |