comparison VideoPlayer.h @ 2345:182effc4b0ee

for MultimediaPlayer
author Ritor1
date Mon, 07 Apr 2014 19:15:13 +0600
parents ddb803517a48
children d57505d3c70c
comparison
equal deleted inserted replaced
2336:d6887ee81068 2345:182effc4b0ee
1 #pragma once 1 #pragma once
2 #include "OSWindow.h" 2 #include "OSWindow.h"
3 #include "Texture.h" 3 #include "Texture.h"
4 #include "MediaPlayer.h"
4 5
5 6
6 7
7 8
8 9
386 387
387 volatile int done = false; 388 volatile int done = false;
388 do 389 do
389 { 390 {
390 int ret; 391 int ret;
392 //Функция avcodec_decode_video2 осуществляет декодирование пакета в фрейм с использованием кодека,
393 //который мы получили раньше (codec_context). Функция устанавливает положительное значение frame_finished в случае
394 //если фрейм декодирован целиком (то есть один фрейм может занимать несколько пакетов и frame_finished будет
395 //установлен только при декодировании последнего пакета).
391 if ((ret = avcodec_decode_video2(dec_ctx, f, (int *)&done, p)) < 0) 396 if ((ret = avcodec_decode_video2(dec_ctx, f, (int *)&done, p)) < 0)
392 return ret; 397 return ret;
393 } while (!done); 398 } while (!done);
394 if (Rescale(f, width, height, AV_PIX_FMT_RGB32, rescaled_data, rescaled_linesize)) 399 if (Rescale(f, width, height, AV_PIX_FMT_RGB32, rescaled_data, rescaled_linesize))
395 return 0; 400 return 0;
407 412
408 bool Rescale(AVFrame *frame, int dst_width, int dst_height, AVPixelFormat format, uint8_t **out_data, int *out_linesize) 413 bool Rescale(AVFrame *frame, int dst_width, int dst_height, AVPixelFormat format, uint8_t **out_data, int *out_linesize)
409 { 414 {
410 if (av_image_alloc(out_data, out_linesize, dst_width, dst_height, format, 1) < 0) 415 if (av_image_alloc(out_data, out_linesize, dst_width, dst_height, format, 1) < 0)
411 return false; 416 return false;
412 417 // создание контекста для преобразования
413 SwsContext *converter = sws_getContext(frame->width, frame->height, (AVPixelFormat)frame->format, 418 SwsContext *converter = sws_getContext(frame->width, frame->height, (AVPixelFormat)frame->format,
414 dst_width, dst_height, format, 419 dst_width, dst_height, format, SWS_BICUBIC, nullptr, nullptr, nullptr);
415 SWS_BICUBIC, nullptr, nullptr, nullptr); 420 // преобразование кадра
416 sws_scale(converter, frame->data, frame->linesize, 0, frame->height, out_data, out_linesize); 421 sws_scale(converter, frame->data, frame->linesize, 0, frame->height, out_data, out_linesize);
417 sws_freeContext(converter); 422 sws_freeContext(converter);
418 423
419 return true; 424 return true;
420 } 425 }
442 avcodec_get_frame_defaults(f); 447 avcodec_get_frame_defaults(f);
443 448
444 volatile int done = false; 449 volatile int done = false;
445 do 450 do
446 { 451 {
452 //Декодирование аудио-пакета осуществляется функцией avcodec_decode_audio4
447 int ret; 453 int ret;
448 if ((ret = avcodec_decode_audio4(dec_ctx, f, (int *)&done, p)) < 0) 454 if ((ret = avcodec_decode_audio4(dec_ctx, f, (int *)&done, p)) < 0)
449 return ret; 455 return ret;
450 } while (!done); 456 } while (!done);
451 if (Resample(f, f->channel_layout, f->sample_rate, 457 if (Resample(f, f->channel_layout, f->sample_rate,
520 526
521 template<int NUM_PRECACHED_FRAMES> 527 template<int NUM_PRECACHED_FRAMES>
522 class MovieCached 528 class MovieCached
523 { 529 {
524 public: 530 public:
525 bool Stopped() { return stopped; } 531 //bool Stopped() { return stopped; }
526 int GetWidth() { return width; } 532 int GetWidth() { return width; }
527 int GetHeight() { return height; } 533 int GetHeight() { return height; }
528 inline ~MovieCached() 534 inline ~MovieCached()
529 { 535 {
530 Release(); 536 Release();
551 ioBuffer = nullptr; 557 ioBuffer = nullptr;
552 format_ctx = nullptr; 558 format_ctx = nullptr;
553 avioContext = nullptr; 559 avioContext = nullptr;
554 } 560 }
555 561
556 bool LoadFromLOD(HANDLE h, int readFunction(void*, uint8_t*, int), int64_t seekFunction(void*, int64_t, int), int width, int height) 562 /*bool LoadFromLOD(HANDLE h, int readFunction(void*, uint8_t*, int), int64_t seekFunction(void*, int64_t, int), int width, int height)
557 { 563 {
558 if (!ioBuffer) 564 if (!ioBuffer)
559 ioBuffer = (unsigned char *)av_malloc(16384 + FF_INPUT_BUFFER_PADDING_SIZE); // can get av_free()ed by libav 565 ioBuffer = (unsigned char *)av_malloc(16384 + FF_INPUT_BUFFER_PADDING_SIZE); // can get av_free()ed by libav
560 if (!avioContext) 566 if (!avioContext)
561 avioContext = avio_alloc_context(ioBuffer, 16384, 0, h, &readFunction, NULL, &seekFunction); 567 avioContext = avio_alloc_context(ioBuffer, 16384, 0, h, &readFunction, NULL, &seekFunction);
562 if (!format_ctx) 568 if (!format_ctx)
563 format_ctx = avformat_alloc_context(); 569 format_ctx = avformat_alloc_context();
564 format_ctx->pb = avioContext; 570 format_ctx->pb = avioContext;
565 return Load("dummyFilename", width, height); 571 return Load("dummyFilename", width, height);
566 } 572 } */
567 573
568 bool Load(const char *video_filename, int width, int height) 574 /*bool Load(const char *video_filename, int width, int height)
569 { 575 {
570 this->width = width; 576 this->width = width;
571 this->height = height; 577 this->height = height;
572 578 // Open video file
579 //откроем входной файл(Шаг 2)
580 //Функция avformat_open_input читает файловый заголовок и сохраняет информацию о найденных форматах в структуре
581 //AVFormatContext. Остальные аргументы могут быть установлены в NULL, в этом случае libavformat использует
582 //автоматическое определение параметров.
573 if (avformat_open_input(&format_ctx, video_filename, nullptr, nullptr) >= 0) 583 if (avformat_open_input(&format_ctx, video_filename, nullptr, nullptr) >= 0)
574 { 584 {
585 // Retrieve stream information
586 //Т.к. avformat_open_input читает только заголовок файла, то следующим шагом нужно получить информацию о потоках
587 //в файле. Это делается функцией avformat_find_stream_info.(Шаг 3)
575 if (avformat_find_stream_info(format_ctx, nullptr) >= 0) 588 if (avformat_find_stream_info(format_ctx, nullptr) >= 0)
576 { 589 {
590 // Dump information about file onto standard error
591 //После этого format_context->streams содержит все существующие потоки файла.
592 //Их количество равно format_context->nb_streams.
593 //Вывести подробную информацию о файле и обо всех потоках можно функцией av_dump_format.
577 av_dump_format(format_ctx, 0, video_filename, 0); 594 av_dump_format(format_ctx, 0, video_filename, 0);
578 595
579 video_stream_idx = OpenStream(AVMEDIA_TYPE_VIDEO, &video_stream, &video_stream_dec, &video_stream_dec_ctx); 596 video_stream_idx = OpenStream(AVMEDIA_TYPE_VIDEO, &video_stream, &video_stream_dec, &video_stream_dec_ctx);
580 if (video_stream_idx < 0) 597 if (video_stream_idx < 0)
581 return Release(), false; 598 return Release(), false;
588 audio_stream_idx = OpenStream(AVMEDIA_TYPE_AUDIO, &audio_stream, &audio_stream_dec, &audio_stream_dec_ctx); 605 audio_stream_idx = OpenStream(AVMEDIA_TYPE_AUDIO, &audio_stream, &audio_stream_dec, &audio_stream_dec_ctx);
589 if (audio_stream_idx < 0) 606 if (audio_stream_idx < 0)
590 return Release(), false; 607 return Release(), false;
591 608
592 strcpy(movie_name, video_filename); 609 strcpy(movie_name, video_filename);
610 //Данные из файла читаются пакетами (AVPacket)
593 packet = new AVPacket; 611 packet = new AVPacket;
594 av_init_packet(packet); 612 av_init_packet(packet);
595 return true; 613 return true;
596 } 614 }
597 } 615 fprintf(stderr, "ffmpeg: Unable to find stream info\n");
616 return Release(), false;
617 }
618 fprintf(stderr, "ffmpeg: Unable to open input file\n");
598 return Release(), false; 619 return Release(), false;
599 } 620 } */
600 621
601 bool Release() 622 bool Release()
602 { 623 {
603 if (packet) 624 if (packet)
604 { 625 {
610 if (video_stream_idx >= 0) 631 if (video_stream_idx >= 0)
611 { 632 {
612 video_stream_idx = -1; 633 video_stream_idx = -1;
613 video_stream = nullptr; 634 video_stream = nullptr;
614 video_stream_dec = nullptr; 635 video_stream_dec = nullptr;
636
637 // закрытие видео кодека
615 avcodec_close(video_stream_dec_ctx); 638 avcodec_close(video_stream_dec_ctx);
616 video_stream_dec_ctx = nullptr; 639 video_stream_dec_ctx = nullptr;
617 } 640 }
618 641
619 if (audio_stream_idx >= 0) 642 if (audio_stream_idx >= 0)
620 { 643 {
621 audio_stream_idx = -1; 644 audio_stream_idx = -1;
622 audio_stream = nullptr; 645 audio_stream = nullptr;
623 audio_stream_dec = nullptr; 646 audio_stream_dec = nullptr;
647
648 // закрытие аудио кодека
624 avcodec_close(audio_stream_dec_ctx); 649 avcodec_close(audio_stream_dec_ctx);
625 650
626 } 651 }
627 if (avioContext) 652 if (avioContext)
628 { 653 {
636 } 661 }
637 return true; 662 return true;
638 } 663 }
639 664
640 665
641 int OpenStream(AVMediaType type, AVStream **out_stream, AVCodec **out_dec, AVCodecContext **out_dec_ctx) 666 /*int OpenStream(AVMediaType type, AVStream **out_stream, AVCodec **out_dec, AVCodecContext **out_dec_ctx)
642 { 667 {
643 int stream_idx = av_find_best_stream(format_ctx, type, -1, -1, nullptr, 0); 668 int stream_idx = av_find_best_stream(format_ctx, type, -1, -1, nullptr, 0);
644 if (stream_idx < 0) 669 if (stream_idx < 0)
645 return stream_idx; 670 return stream_idx;
646 671
647 auto stream = format_ctx->streams[stream_idx]; 672 auto stream = format_ctx->streams[stream_idx];
673 //Информация о кодеке в потоке называется «контекстом кодека» (AVCodecContext).
674 //Используя эту информацию, мы можем найти необходимый кодек (AVCodec) и открыть его.
648 auto dec_ctx = stream->codec; 675 auto dec_ctx = stream->codec;
649 auto dec = avcodec_find_decoder(dec_ctx->codec_id); 676 auto dec = avcodec_find_decoder(dec_ctx->codec_id);
650 if (dec) 677 if (dec)
651 { 678 {
652 if (avcodec_open2(dec_ctx, dec, nullptr) >= 0) 679 if (avcodec_open2(dec_ctx, dec, nullptr) >= 0)
655 *out_dec = dec; 682 *out_dec = dec;
656 *out_dec_ctx = dec_ctx; 683 *out_dec_ctx = dec_ctx;
657 return stream_idx; 684 return stream_idx;
658 } 685 }
659 } 686 }
687 fprintf(stderr, "ffmpeg: Unable to open codec\n");
660 return -1; 688 return -1;
661 } 689 } */
662 690
663 MultimediaFrame::Ptr GetNextFrame() 691 MultimediaFrame::Ptr GetNextFrame()
664 { 692 {
665 packet->data = nullptr; 693 packet->data = nullptr;
666 packet->size = 0; 694 packet->size = 0;
667 695
668 volatile int got_frame = false; 696 volatile int got_frame = false;
697 //чтение пакетов
669 do 698 do
670 { 699 {
671 if (av_read_frame(format_ctx, packet) < 0) 700 if (av_read_frame(format_ctx, packet) < 0)
672 { 701 {
673 stopped = true; 702 stopped = true;
674 return nullptr; 703 return nullptr;
675 } 704 }
676 } while (packet->stream_index != video_stream_idx && 705 } while (packet->stream_index != video_stream_idx && //пока пакет не пренадлежит к видеопотоку
677 packet->stream_index != audio_stream_idx); 706 packet->stream_index != audio_stream_idx); //и не принадлежит аудиопотоку
678 707
679 if (packet->stream_index == video_stream_idx) 708 if (packet->stream_index == video_stream_idx)
680 return MultimediaFrame::Ptr(new MultimediaVideoFrame(AVMEDIA_TYPE_VIDEO, packet, video_stream_dec_ctx, width, height)); 709 return MultimediaFrame::Ptr(new MultimediaVideoFrame(AVMEDIA_TYPE_VIDEO, packet, video_stream_dec_ctx, width, height));
681 else if (packet->stream_index == audio_stream_idx) 710 else if (packet->stream_index == audio_stream_idx)
682 return MultimediaFrame::Ptr(new MultimediaAudioFrame(AVMEDIA_TYPE_AUDIO, packet, audio_stream_dec_ctx)); 711 return MultimediaFrame::Ptr(new MultimediaAudioFrame(AVMEDIA_TYPE_AUDIO, packet, audio_stream_dec_ctx));
686 715
687 716
688 char movie_name[256]; 717 char movie_name[256];
689 int width; 718 int width;
690 int height; 719 int height;
691 bool stopped; 720 //bool stopped;
692 AVFormatContext *format_ctx; 721 AVFormatContext *format_ctx;
693 //AVFrame *frame; 722 //AVFrame *frame;
694 AVPacket *packet; 723 AVPacket *packet;
695 //MultimediaFrame *frames[NUM_PRECACHED_FRAMES]; 724 //MultimediaFrame *frames[NUM_PRECACHED_FRAMES];
696 OpenALSoundProvider *sound_provider; 725 OpenALSoundProvider *sound_provider;
697 726
698 int video_stream_idx; 727 int video_stream_idx;
699 AVStream *video_stream; 728 AVStream *video_stream;//содержат информацию о видео потоке
700 AVCodec *video_stream_dec; 729 AVCodec *video_stream_dec;
701 AVCodecContext *video_stream_dec_ctx; 730 AVCodecContext *video_stream_dec_ctx;
702 731
703 int audio_stream_idx; 732 int audio_stream_idx;
704 AVStream *audio_stream; 733 AVStream *audio_stream;//содержат информацию о аудио потоке
705 AVCodec *audio_stream_dec; 734 AVCodec *audio_stream_dec;
706 AVCodecContext *audio_stream_dec_ctx; 735 AVCodecContext *audio_stream_dec_ctx;
707 unsigned char * ioBuffer; 736 unsigned char * ioBuffer;
708 AVIOContext *avioContext; 737 AVIOContext *avioContext;
709 }; 738 };
710 typedef MovieCached<10> Movie; 739 //typedef MovieCached<10> Movie;
711 740
712 741
713 742
714 743
715 class MultimediaPlayer 744 /*class MultimediaPlayer
716 { 745 {
717 public: 746 public:
718 inline MultimediaPlayer() 747 inline MultimediaPlayer()
719 { 748 {
720 } 749 }
723 { 752 {
724 if (!libavcodec_initialized) 753 if (!libavcodec_initialized)
725 { 754 {
726 av_log_set_callback(Logger); 755 av_log_set_callback(Logger);
727 avcodec_register_all(); 756 avcodec_register_all();
757
758 // Register all available file formats and codecs
759 //инициализируем библиотеку ffmpeg(Шаг 1)
760 //Во время инициализации регистрируются все имеющиеся в библиотеке форматы файлов и кодеков.
761 //После этого они будут использоваться автоматически при открытии файлов этого формата и с этими кодеками.
728 av_register_all(); 762 av_register_all();
729 763
730 libavcodec_initialized = true; 764 libavcodec_initialized = true;
731 } 765 }
732 766
734 sound_provider->Initialize(); 768 sound_provider->Initialize();
735 769
736 return true; 770 return true;
737 } 771 }
738 772
739 Movie *LoadMovieFromLOD(HANDLE h, int readFunction(void*, uint8_t*, int), int64_t seekFunction(void*, int64_t, int), int width, int height) 773 /*Movie *LoadMovieFromLOD(HANDLE h, int readFunction(void*, uint8_t*, int), int64_t seekFunction(void*, int64_t, int), int width, int height)
740 { 774 {
741 auto movie = new Movie(sound_provider); 775 auto movie = new Movie(sound_provider);
742 if (movie) 776 if (movie)
743 { 777 {
744 if (movie->LoadFromLOD(h, readFunction, seekFunction, width, height)) 778 if (movie->LoadFromLOD(h, readFunction, seekFunction, width, height))
756 return current_movie = movie; 790 return current_movie = movie;
757 } 791 }
758 delete movie; 792 delete movie;
759 } 793 }
760 return nullptr; 794 return nullptr;
761 } 795 } */
762 796
763 Movie *LoadMovie(const char *filename, int width, int height) 797 /*Movie *LoadMovie(const char *filename, int width, int height)
764 { 798 {
765 auto movie = new Movie(sound_provider); 799 auto movie = new Movie(sound_provider);
766 if (movie) 800 if (movie)
767 { 801 {
768 if (movie->Load(filename, width, height)) 802 if (movie->Load(filename, width, height))
772 return current_movie = movie; 806 return current_movie = movie;
773 } 807 }
774 delete movie; 808 delete movie;
775 } 809 }
776 return nullptr; 810 return nullptr;
777 } 811 }
778 812
779 inline char *DoFrame() 813 inline char *DoFrame()
780 { 814 {
781 if (!current_movie) 815 if (!current_movie)
782 return nullptr; 816 return nullptr;
819 853
820 protected: 854 protected:
821 static void Logger(void *, int, const char *format, va_list args); 855 static void Logger(void *, int, const char *format, va_list args);
822 856
823 OpenALSoundProvider *sound_provider; 857 OpenALSoundProvider *sound_provider;
824 Movie *current_movie; 858 //Movie *current_movie;
825 int current_movie_width; 859 int current_movie_width;
826 int current_movie_height; 860 int current_movie_height;
827 861
828 static bool libavcodec_initialized; 862 static bool libavcodec_initialized;
829 }; 863 };*/
830 864
831 865
832 866
833 867
834 868
898 unsigned int uMovieFormat; 932 unsigned int uMovieFormat;
899 int uMovieFormatSwapped; 933 int uMovieFormatSwapped;
900 char pCurrentMovieName[64]; 934 char pCurrentMovieName[64];
901 char pVideoFrameTextureFilename[32]; 935 char pVideoFrameTextureFilename[32];
902 int field_104; 936 int field_104;
903 MultimediaPlayer *pPlayer; 937 Media::Player *pPlayer;
904 Movie *pMovie; 938 Media::IMovie *pMovie;
905 HANDLE hVidFile; 939 HANDLE hVidFile;
906 int uSize; 940 int uSize;
907 int uOffset; 941 int uOffset;
908 void UpdatePalette(); 942 void UpdatePalette();
909 static int readFunction(void *, uint8_t *, int); 943 static int readFunction(void *, uint8_t *, int);
910 static int64_t seekFunction(void *, int64_t, int); 944 static int64_t seekFunction(void *, int64_t, int);
911 void LoadMovie(const char *); 945 void LoadMovie(const char *);
946 void PlayAudio(const wchar_t * pFilename);
947 void PlayMovie(const wchar_t * pFilename);
912 }; 948 };
913 #pragma pack(pop) 949 #pragma pack(pop)
914 950
915 951
916 952