Mercurial > mm7
annotate VideoPlayer.h @ 2195:70b63fe6587c
fixing a few bugs reported by PVS
author | Grumpy7 |
---|---|
date | Thu, 30 Jan 2014 23:03:04 +0100 |
parents | ca548138d6aa |
children | 0b2eea6f80c9 |
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); | |
269 while (num_processed_buffers) | |
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); | |
275 } | |
276 | |
277 int num_queued_buffers; | |
278 alGetSourcei(samples_source_id, AL_BUFFERS_QUEUED, &num_queued_buffers); | |
279 if (num_queued_buffers >= MAX_SAMPLES_BUFFERS) | |
280 { | |
281 __debugbreak(); | |
282 } | |
283 | |
284 alSourceQueueBuffers(samples_source_id, 1, next_buffer); | |
285 CheckError(); | |
286 | |
287 int status; | |
288 alGetSourcei(samples_source_id, AL_SOURCE_STATE, &status); | |
289 if (status != AL_PLAYING) | |
290 { | |
291 alSourcePlay(samples_source_id); | |
292 CheckError(); | |
293 } | |
294 | |
295 if (++samples_current_buffer >= MAX_SAMPLES_BUFFERS) | |
296 samples_current_buffer = 0; | |
297 } | |
298 | |
299 | |
300 | |
301 protected: | |
302 ALCdevice *device; | |
303 ALCcontext *context; | |
304 unsigned int samples_buffer_id[MAX_SAMPLES_BUFFERS]; | |
305 unsigned int samples_source_id; | |
306 int samples_current_buffer; | |
307 | |
308 | |
309 bool CheckError() | |
310 { | |
311 ALenum code = alcGetError(device); | |
312 if (code != ALC_NO_ERROR) | |
313 { | |
314 DWORD w; | |
315 const char *message = alcGetString(device, code); | |
316 WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), message, lstrlenA(message), &w, nullptr); | |
317 return true; | |
318 } | |
319 return false; | |
320 } | |
321 }; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
322 typedef OpenALSoundProviderGeneric<64> OpenALSoundProvider; |
2134 | 323 |
324 | |
325 | |
326 void av_logger(void *, int, const char *format, va_list args); | |
327 | |
328 | |
329 | |
330 #include <memory> | |
331 using std::tr1::shared_ptr; | |
332 using std::tr1::make_shared; | |
333 | |
334 class MultimediaFrame | |
335 { | |
336 public: | |
337 typedef shared_ptr<MultimediaFrame> Ptr; | |
338 inline MultimediaFrame(AVMediaType type, AVPacket *packet, AVCodecContext *dec_ctx) | |
339 { | |
340 this->type = type; | |
341 this->f = nullptr; | |
342 this->p = packet; | |
343 this->dec_ctx = dec_ctx; | |
344 } | |
345 virtual ~MultimediaFrame() { return; } | |
346 | |
347 | |
348 AVMediaType Type() const { return type; } | |
349 AVFrame *GetAVFrame() { return f; } | |
350 | |
351 virtual int Decode() = 0; | |
352 virtual void *GetData() = 0; | |
353 virtual int GetDataPitch() = 0; | |
354 | |
355 | |
356 protected: | |
357 AVMediaType type; | |
358 AVFrame *f; | |
359 AVPacket *p; | |
360 AVCodecContext *dec_ctx; | |
361 }; | |
362 | |
363 | |
364 | |
365 class MultimediaVideoFrame : public MultimediaFrame | |
366 { | |
367 public: | |
368 inline MultimediaVideoFrame(AVMediaType type, AVPacket *packet, AVCodecContext *dec_ctx, int width, int height) : | |
369 MultimediaFrame(type, packet, dec_ctx) | |
370 { | |
371 this->width = width; | |
372 this->height = height; | |
373 this->rescaled_data[0] = nullptr; | |
374 this->rescaled_linesize[0] = 0; | |
375 } | |
376 virtual ~MultimediaVideoFrame() | |
377 { | |
378 av_freep(&rescaled_data); | |
379 av_frame_free(&f); | |
380 } | |
381 | |
382 int Decode() override | |
383 { | |
384 f = avcodec_alloc_frame(); | |
385 avcodec_get_frame_defaults(f); | |
386 | |
387 volatile int done = false; | |
388 do | |
389 { | |
390 int ret; | |
391 if ((ret = avcodec_decode_video2(dec_ctx, f, (int *)&done, p)) < 0) | |
392 return ret; | |
393 } while (!done); | |
394 if (Rescale(f, width, height, AV_PIX_FMT_RGB32, rescaled_data, rescaled_linesize)) | |
395 return 0; | |
396 else return -1; | |
397 } | |
398 | |
399 virtual void *GetData() { return rescaled_data[0]; } | |
400 virtual int GetDataPitch() { return rescaled_linesize[0]; } | |
401 | |
402 protected: | |
403 int width; | |
404 int height; | |
405 uint8_t *rescaled_data[8]; | |
406 int rescaled_linesize[8]; | |
407 | |
408 bool Rescale(AVFrame *frame, int dst_width, int dst_height, AVPixelFormat format, uint8_t **out_data, int *out_linesize) | |
409 { | |
410 if (av_image_alloc(out_data, out_linesize, dst_width, dst_height, format, 1) < 0) | |
411 return false; | |
412 | |
413 SwsContext *converter = sws_getContext(frame->width, frame->height, (AVPixelFormat)frame->format, | |
414 dst_width, dst_height, format, | |
415 SWS_BICUBIC, nullptr, nullptr, nullptr); | |
416 sws_scale(converter, frame->data, frame->linesize, 0, frame->height, out_data, out_linesize); | |
417 sws_freeContext(converter); | |
418 | |
419 return true; | |
420 } | |
421 }; | |
422 | |
423 | |
424 | |
425 class MultimediaAudioFrame : public MultimediaFrame | |
426 { | |
427 public: | |
428 inline MultimediaAudioFrame(AVMediaType type, AVPacket *packet, AVCodecContext *dec_ctx) : | |
429 MultimediaFrame(type, packet, dec_ctx) | |
430 { | |
431 this->resampled_data = nullptr; | |
432 } | |
433 virtual ~MultimediaAudioFrame() | |
434 { | |
435 av_free(resampled_data); | |
436 av_frame_free(&f); | |
437 } | |
438 | |
439 int Decode() override | |
440 { | |
441 f = avcodec_alloc_frame(); | |
442 avcodec_get_frame_defaults(f); | |
443 | |
444 volatile int done = false; | |
445 do | |
446 { | |
447 int ret; | |
448 if ((ret = avcodec_decode_audio4(dec_ctx, f, (int *)&done, p)) < 0) | |
449 return ret; | |
450 } while (!done); | |
451 if (Resample(f, f->channel_layout, f->sample_rate, | |
452 f->channel_layout, f->sample_rate, AV_SAMPLE_FMT_S16, &resampled_data)) | |
453 return 0; | |
454 else return -1; | |
455 } | |
456 | |
457 virtual void *GetData() { return resampled_data; } | |
458 virtual int GetDataPitch() { return 2 * f->nb_samples; } | |
459 | |
460 protected: | |
461 uint8_t *resampled_data; | |
462 | |
463 bool Resample(AVFrame *frame, | |
464 int64_t src_channel_layout, int src_sample_rate, | |
465 int64_t dst_channel_layout, int dst_sample_rate, AVSampleFormat dst_format, uint8_t **out_data) | |
466 { | |
467 SwrContext *converter = swr_alloc(); | |
468 | |
469 av_opt_set_int(converter, "in_channel_layout", src_channel_layout, 0); | |
470 av_opt_set_int(converter, "in_sample_rate", src_sample_rate, 0); | |
471 av_opt_set_sample_fmt(converter, "in_sample_fmt", (AVSampleFormat)frame->format, 0); | |
472 | |
473 av_opt_set_int(converter, "out_channel_layout", dst_channel_layout, 0); | |
474 av_opt_set_int(converter, "out_sample_rate", dst_sample_rate, 0); | |
475 av_opt_set_sample_fmt(converter, "out_sample_fmt", dst_format, 0); | |
476 | |
477 if (swr_init(converter) < 0) | |
478 return false; | |
479 | |
480 int dst_nb_samples; | |
481 int max_dst_nb_samples = dst_nb_samples = av_rescale_rnd(frame->nb_samples, dst_sample_rate, src_channel_layout, AV_ROUND_UP); | |
482 | |
483 uint8_t **dst_data; | |
484 int dst_linesize; | |
485 int dst_nb_channels = av_get_channel_layout_nb_channels(dst_channel_layout); | |
486 if (av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_format, 0) < 0) | |
487 { | |
488 swr_free(&converter); | |
489 return false; | |
490 } | |
491 | |
492 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); | |
493 if (dst_nb_samples > max_dst_nb_samples) | |
494 { | |
495 av_free(dst_data[0]); | |
496 if (av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_format, 1) < 0) | |
497 { | |
498 swr_free(&converter); | |
499 return false; | |
500 } | |
501 max_dst_nb_samples = dst_nb_samples; | |
502 } | |
503 | |
504 | |
505 if (swr_convert(converter, dst_data, dst_nb_samples, (const uint8_t **)frame->data, frame->nb_samples) < 0) | |
506 { | |
507 av_free(dst_data[0]); | |
508 swr_free(&converter); | |
509 return false; | |
510 } | |
511 | |
512 *out_data = dst_data[0]; | |
513 return true; | |
514 } | |
515 }; | |
516 | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
517 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
|
518 |
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
519 int64_t seekFunction(void* opaque, int64_t offset, int whence); |
2134 | 520 |
521 template<int NUM_PRECACHED_FRAMES> | |
522 class MovieCached | |
523 { | |
524 public: | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
525 bool Stopped() { return stopped; } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
526 int GetWidth() { return width; } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
527 int GetHeight() { return height; } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
528 inline ~MovieCached() |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
529 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
530 Release(); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
531 } |
2134 | 532 protected: |
533 friend class MultimediaPlayer; | |
534 inline MovieCached(OpenALSoundProvider *sound_provider) | |
535 { | |
536 this->format_ctx = nullptr; | |
537 this->sound_provider = sound_provider; | |
538 this->stopped = false; | |
539 | |
540 this->video_stream_idx = -1; | |
541 this->video_stream = nullptr; | |
542 this->video_stream_dec = nullptr; | |
543 this->video_stream_dec_ctx = nullptr; | |
544 | |
545 this->audio_stream_idx = -1; | |
546 this->audio_stream = nullptr; | |
547 this->audio_stream_dec = nullptr; | |
548 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
|
549 |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
550 packet = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
551 ioBuffer = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
552 format_ctx = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
553 avioContext = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
554 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
555 |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
556 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
|
557 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
558 if (!ioBuffer) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
559 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
|
560 if (!avioContext) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
561 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
|
562 if (!format_ctx) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
563 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
|
564 format_ctx->pb = avioContext; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
565 return Load("dummyFilename", width, height); |
2134 | 566 } |
567 | |
568 bool Load(const char *video_filename, int width, int height) | |
569 { | |
570 this->width = width; | |
571 this->height = height; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
572 |
2134 | 573 if (avformat_open_input(&format_ctx, video_filename, nullptr, nullptr) >= 0) |
574 { | |
575 if (avformat_find_stream_info(format_ctx, nullptr) >= 0) | |
576 { | |
577 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
|
578 |
2134 | 579 video_stream_idx = OpenStream(AVMEDIA_TYPE_VIDEO, &video_stream, &video_stream_dec, &video_stream_dec_ctx); |
580 if (video_stream_idx < 0) | |
581 return Release(), false; | |
582 | |
583 audio_stream_idx = OpenStream(AVMEDIA_TYPE_AUDIO, &audio_stream, &audio_stream_dec, &audio_stream_dec_ctx); | |
584 if (audio_stream_idx < 0) | |
585 return Release(), false; | |
586 | |
587 strcpy(movie_name, video_filename); | |
588 packet = new AVPacket; | |
589 av_init_packet(packet); | |
590 return true; | |
591 } | |
592 } | |
593 return Release(), false; | |
594 } | |
595 | |
596 bool Release() | |
597 { | |
598 if (packet) | |
599 { | |
600 av_free_packet(packet); | |
601 delete packet; | |
602 packet = nullptr; | |
603 } | |
604 | |
605 if (video_stream_idx >= 0) | |
606 { | |
607 video_stream_idx = -1; | |
608 video_stream = nullptr; | |
609 video_stream_dec = nullptr; | |
610 avcodec_close(video_stream_dec_ctx); | |
611 video_stream_dec_ctx = nullptr; | |
612 } | |
613 | |
614 if (audio_stream_idx >= 0) | |
615 { | |
616 audio_stream_idx = -1; | |
617 audio_stream = nullptr; | |
618 audio_stream_dec = nullptr; | |
619 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
|
620 |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
621 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
622 if (avioContext) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
623 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
624 av_free(avioContext); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
625 avioContext = nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
626 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
627 if (format_ctx) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
628 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
629 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
|
630 format_ctx = nullptr; |
2134 | 631 } |
632 return true; | |
633 } | |
634 | |
635 | |
636 int OpenStream(AVMediaType type, AVStream **out_stream, AVCodec **out_dec, AVCodecContext **out_dec_ctx) | |
637 { | |
638 int stream_idx = av_find_best_stream(format_ctx, type, -1, -1, nullptr, 0); | |
639 if (stream_idx < 0) | |
640 return stream_idx; | |
641 | |
642 auto stream = format_ctx->streams[stream_idx]; | |
643 auto dec_ctx = stream->codec; | |
644 auto dec = avcodec_find_decoder(dec_ctx->codec_id); | |
645 if (dec) | |
646 { | |
647 if (avcodec_open2(dec_ctx, dec, nullptr) >= 0) | |
648 { | |
649 *out_stream = stream; | |
650 *out_dec = dec; | |
651 *out_dec_ctx = dec_ctx; | |
652 return stream_idx; | |
653 } | |
654 } | |
655 return -1; | |
656 } | |
657 | |
658 MultimediaFrame::Ptr GetNextFrame() | |
659 { | |
660 packet->data = nullptr; | |
661 packet->size = 0; | |
662 | |
663 volatile int got_frame = false; | |
664 do | |
665 { | |
666 if (av_read_frame(format_ctx, packet) < 0) | |
667 { | |
668 stopped = true; | |
669 return nullptr; | |
670 } | |
671 } while (packet->stream_index != video_stream_idx && | |
672 packet->stream_index != audio_stream_idx); | |
673 | |
674 if (packet->stream_index == video_stream_idx) | |
675 return MultimediaFrame::Ptr(new MultimediaVideoFrame(AVMEDIA_TYPE_VIDEO, packet, video_stream_dec_ctx, width, height)); | |
676 else if (packet->stream_index == audio_stream_idx) | |
677 return MultimediaFrame::Ptr(new MultimediaAudioFrame(AVMEDIA_TYPE_AUDIO, packet, audio_stream_dec_ctx)); | |
678 return nullptr; | |
679 } | |
680 | |
681 | |
682 | |
683 char movie_name[256]; | |
684 int width; | |
685 int height; | |
686 bool stopped; | |
687 AVFormatContext *format_ctx; | |
688 //AVFrame *frame; | |
689 AVPacket *packet; | |
690 //MultimediaFrame *frames[NUM_PRECACHED_FRAMES]; | |
691 OpenALSoundProvider *sound_provider; | |
692 | |
693 int video_stream_idx; | |
694 AVStream *video_stream; | |
695 AVCodec *video_stream_dec; | |
696 AVCodecContext *video_stream_dec_ctx; | |
697 | |
698 int audio_stream_idx; | |
699 AVStream *audio_stream; | |
700 AVCodec *audio_stream_dec; | |
701 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
|
702 unsigned char * ioBuffer; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
703 AVIOContext *avioContext; |
2134 | 704 }; |
705 typedef MovieCached<10> Movie; | |
706 | |
707 | |
708 | |
709 | |
710 class MultimediaPlayer | |
711 { | |
712 public: | |
713 inline MultimediaPlayer() | |
714 { | |
715 } | |
716 | |
717 bool Initialize() | |
718 { | |
719 if (!libavcodec_initialized) | |
720 { | |
721 av_log_set_callback(Logger); | |
722 avcodec_register_all(); | |
723 av_register_all(); | |
724 | |
725 libavcodec_initialized = true; | |
726 } | |
727 | |
728 sound_provider = new OpenALSoundProvider; | |
729 sound_provider->Initialize(); | |
730 | |
731 return true; | |
732 } | |
733 | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
734 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
|
735 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
736 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
|
737 if (movie) |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
738 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
739 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
|
740 { |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
741 current_movie_width = width; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
742 current_movie_height = height; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
743 return current_movie = movie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
744 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
745 delete movie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
746 } |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
747 return nullptr; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
748 } |
2134 | 749 |
750 Movie *LoadMovie(const char *filename, int width, int height) | |
751 { | |
752 auto movie = new Movie(sound_provider); | |
753 if (movie) | |
754 { | |
755 if (movie->Load(filename, width, height)) | |
756 { | |
757 current_movie_width = width; | |
758 current_movie_height = height; | |
759 return current_movie = movie; | |
760 } | |
761 delete movie; | |
762 } | |
763 return nullptr; | |
764 } | |
765 | |
766 inline char *DoFrame() | |
767 { | |
768 if (!current_movie) | |
769 return nullptr; | |
770 | |
771 while (true) | |
772 { | |
773 auto frame = current_movie->GetNextFrame(); | |
774 if (!frame) | |
775 return nullptr; | |
776 | |
777 if (frame->Type() == AVMEDIA_TYPE_AUDIO) | |
778 { | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
779 //continue; |
2134 | 780 uint8_t *data; |
781 if (frame->Decode() >= 0) | |
782 { | |
783 auto f = frame->GetAVFrame(); | |
784 sound_provider->PlaySample(f->channels, f->sample_rate, f->nb_samples, frame->GetData()); | |
785 Sleep(20); | |
786 continue; | |
787 } | |
788 } | |
789 else if (frame->Type() == AVMEDIA_TYPE_VIDEO) | |
790 { | |
791 uint8_t *dst_data[4] = { 0 }; | |
792 int dst_linesize[4] = { 0 }; | |
793 if (frame->Decode() >= 0) | |
794 { | |
795 auto image = new char[current_movie_width * current_movie_height * 4]; | |
796 memcpy(image, frame->GetData(), current_movie_height * frame->GetDataPitch()); | |
797 | |
798 return image; | |
799 } | |
800 } | |
801 return nullptr; | |
802 } | |
803 } | |
804 | |
805 | |
806 | |
807 protected: | |
808 static void Logger(void *, int, const char *format, va_list args); | |
809 | |
810 OpenALSoundProvider *sound_provider; | |
811 Movie *current_movie; | |
812 int current_movie_width; | |
813 int current_movie_height; | |
814 | |
815 static bool libavcodec_initialized; | |
816 }; | |
817 | |
818 | |
819 | |
0 | 820 |
821 | |
822 | |
823 #pragma pack(push, 1) | |
824 struct VideoPlayer | |
825 { | |
1262 | 826 VideoPlayer(); |
0 | 827 //----- (004BECBD) -------------------------------------------------------- |
828 virtual ~VideoPlayer() | |
829 { | |
830 bStopBeforeSchedule = false; | |
165 | 831 pResetflag = 0; |
0 | 832 pVideoFrame.Release(); |
833 } | |
834 | |
835 void PlayDeathMovie(); | |
836 unsigned int SmackCheckSurfaceFromat(); | |
1802 | 837 void Initialize(OSWindow *window); |
0 | 838 void Prepare(); |
839 void Unload(); | |
840 void FastForwardToFrame(unsigned int uFrameNum); | |
1802 | 841 void BinkDrawFrame(int a3, int a4); |
842 void BinkUpdatePalette() {} | |
843 void SmackDrawFrame(int a3, int a4); | |
844 void SmackUpdatePalette(); | |
0 | 845 _BINK *OpenBink(const char *pName); |
846 struct _SMACK *OpenSmack(const char *pFilename); | |
898 | 847 void OpenHouseMovie(const char *pMovieName, unsigned int a3_1);//0x4BF28F |
0 | 848 bool AnyMovieLoaded(); |
898 | 849 void OpenGlobalMovie(const char *pFilename, unsigned int bLoop, int a4); |
0 | 850 void _4BF5B2(); |
898 | 851 void SelectMovieType();//0x4BF73A |
1802 | 852 _BINKBUF *CreateBinkBuffer(unsigned int uWidth, unsigned int uHeight, char a4); |
853 void _inlined_in_463149(); | |
0 | 854 |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
855 void MovieLoop(const char *pMovieName, int a2, int a3, int a4); |
0 | 856 |
857 | |
858 RGBTexture pVideoFrame; | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
859 //struct _SMACK *pSmackerMovie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
860 //struct _SMACKBUF *pSmackerBuffer; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
861 //char *pSomeSmackerBuffer; |
0 | 862 int field_34; |
863 MovieHeader *pMightVideoHeaders; | |
864 MovieHeader *pMagicVideoHeaders; | |
165 | 865 int pResetflag; |
0 | 866 int field_44; |
867 unsigned int uNumMightVideoHeaders; | |
868 unsigned int uNumMagicVideoHeaders; | |
869 int uBinkDirectDrawSurfaceType; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
870 int bBufferLoaded; |
0 | 871 unsigned int bPlayingMovie; |
872 unsigned int bFirstFrame; | |
873 unsigned int bUsingSmackerMMX; | |
874 unsigned int bLoopPlaying; | |
875 int field_68; | |
876 unsigned int bStopBeforeSchedule; | |
1802 | 877 //HWND hWindow; |
878 OSWindow *window; | |
0 | 879 struct _SMACKBLIT *pSmackMovieBlit; |
880 HANDLE hMightVid; | |
881 HANDLE hMagicVid; | |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
882 //_BINK *pBinkMovie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
883 //_BINKBUF *pBinkBuffer; |
0 | 884 char field_88[20]; |
885 unsigned int uMovieFormat; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
886 int uMovieFormatSwapped; |
0 | 887 char pCurrentMovieName[64]; |
888 char pVideoFrameTextureFilename[32]; | |
323 | 889 int field_104; |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
890 MultimediaPlayer *pPlayer; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
891 Movie *pMovie; |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
892 HANDLE hVidFile; |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
893 int uSize; |
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
894 int uOffset; |
2142
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
895 void UpdatePalette(); |
ca548138d6aa
some code cleaning in video playing, loops play but there is a memory leak
zipi
parents:
2137
diff
changeset
|
896 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
|
897 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
|
898 void LoadMovie(const char *); |
0 | 899 }; |
900 #pragma pack(pop) | |
901 | |
902 | |
903 | |
904 | |
905 | |
906 extern VideoPlayer *pVideoPlayer; | |
2137
d24ee391fd1f
libavcodec playing movies and houses, loops not working yet
zipi
parents:
2134
diff
changeset
|
907 extern LRESULT __stdcall wWinProc(HWND hwnd, unsigned int msg, WPARAM wparam, LPARAM lparam); |