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