diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml deleted file mode 100644 index 5cc1b69..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: Bug report -description: Something is not working correctly. -title: "[BUG]" -labels: "bug, to be solved" - -body: - - type: checkboxes - attributes: - label: Get started - options: - - label: >- - I have read [Contributing guidelines](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CONTRIBUTING.md). - required: true - - label: >- - I have confirmed that my problem could not be solved by the [troubleshooting](https://cainmagi.github.io/FFmpeg-Encoder-Decoder-for-Python/docs/troubleshooting/installation) section in the documentation. - required: true - - label: >- - I agree to follow the [Code of Conduct](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CODE_OF_CONDUCT.md). - required: true - - label: >- - I have confirmed that my issue is not duplicated with an existing issue. - required: true - - - type: textarea - attributes: - label: Description - description: >- - A clear and concise description of what the bug is. - validations: - required: true - - - type: textarea - attributes: - label: To Reproduce - description: >- - Steps to reproduce the behavior. Instead of describing the steps, you could also provide your codes related to the error here. - value: | - 1. Get package from '...' - 2. Then run '...' - 3. An error occurs. - - - type: textarea - attributes: - label: Traceback - description: >- - The python trackback of the bug. If there is no traceback, please describe (1) The expected behaviors. (2) The actual behaviors. - render: sh-session - - - type: textarea - attributes: - label: Behaviors - description: >- - If there is no traceback, please describe (1) The expected behaviors. (2) The actual behaviors. - value: | - 1. The expected behaviors: - 2. The actual behaviors: - - - type: textarea - attributes: - label: Screenshots - description: >- - If applicable, add screenshots to help explain your problem. - - - type: input - attributes: - label: OS - description: >- - e.g. Ubuntu 20.04, Debian 10, Windows 10 21H1 - validations: - required: true - - type: input - attributes: - label: Python version - description: >- - e.g. 3.8 - validations: - required: true - - type: input - attributes: - label: numpy version - description: >- - e.g. 1.21.1 - validations: - required: true - - type: input - attributes: - label: mpegCoder version - description: >- - e.g. 3.1.0 - validations: - required: true - - - type: textarea - attributes: - label: Additional context - description: >- - Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/docs_request.yml b/.github/ISSUE_TEMPLATE/docs_request.yml deleted file mode 100644 index 6df461f..0000000 --- a/.github/ISSUE_TEMPLATE/docs_request.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Docs request -description: Report a problem or a request for the docs. -title: "[Docs]" -labels: documentation, to be solved - -body: - - type: checkboxes - attributes: - label: Get started - options: - - label: >- - I have read [Contributing guidelines](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CONTRIBUTING.md). - required: true - - label: >- - I agree to follow the [Code of Conduct](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CODE_OF_CONDUCT.md). - required: true - - label: >- - I have confirmed that my issue is not duplicated with an existing issue. - required: true - - - type: textarea - attributes: - label: Problem - description: >- - If you meet any problems with the documentation, please describe your problems here. - - - type: textarea - attributes: - label: Required feature - description: >- - If you need more explanations in the documentation, please describe your needs here. - - - type: input - attributes: - label: mpegCoder version - description: >- - e.g. 3.1.0 - validations: - required: true - - - type: textarea - attributes: - label: Additional context - description: >- - Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml deleted file mode 100644 index fdf4016..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Feature request -description: Suggest an idea for this project -title: "[Feature]" -labels: enhancement, to be solved - -body: - - type: checkboxes - attributes: - label: Get started - options: - - label: >- - I have read [Contributing guidelines](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CONTRIBUTING.md). - required: true - - label: >- - I agree to follow the [Code of Conduct](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CODE_OF_CONDUCT.md). - required: true - - label: >- - I have confirmed that my issue is not duplicated with an existing issue. - required: true - - - type: textarea - attributes: - label: Problem - description: >- - If your feature request is related to a problem, please describe the problem clearly and concisely. - - - type: textarea - attributes: - label: Required feature - description: >- - A clear and concise description of what you want to happen. - validations: - required: true - - - type: textarea - attributes: - label: Alternative solution - description: >- - A clear and concise description of any alternative solutions or features you've considered. - - - type: input - attributes: - label: mpegCoder version - description: >- - e.g. 3.1.0 - validations: - required: true - - - type: textarea - attributes: - label: Additional context - description: >- - Add any other context about the problem here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 2701a3e..0000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,33 +0,0 @@ -# Pull request - -## Get started - -- [ ] I have read [Contributing guidelines](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CONTRIBUTING.md). -- [ ] I agree to follow the [Code of Conduct](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CODE_OF_CONDUCT.md). -- [ ] I have confirmed that my pull request (PR) is not duplicated with an existing PR. -- [ ] I have confirmed that my pull request (PR) passes the testing workflow of the project. - -## Description - -Describe what you have done with this PR. List any dependencies that are required for this change. - -If your PR is designed for an issue, please refer to the issue by the following example: - -Fixes # (issue) - -## Updated report - -Please summarize your modifications as an itemized report. - -1. Update ... -2. Add ... - -## Information - -Please provide the following information about your PR: - -- `mpegCoder` version: - -## Additional context - -Add any other context about the problem here. diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md deleted file mode 100644 index 2701a3e..0000000 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ /dev/null @@ -1,33 +0,0 @@ -# Pull request - -## Get started - -- [ ] I have read [Contributing guidelines](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CONTRIBUTING.md). -- [ ] I agree to follow the [Code of Conduct](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CODE_OF_CONDUCT.md). -- [ ] I have confirmed that my pull request (PR) is not duplicated with an existing PR. -- [ ] I have confirmed that my pull request (PR) passes the testing workflow of the project. - -## Description - -Describe what you have done with this PR. List any dependencies that are required for this change. - -If your PR is designed for an issue, please refer to the issue by the following example: - -Fixes # (issue) - -## Updated report - -Please summarize your modifications as an itemized report. - -1. Update ... -2. Add ... - -## Information - -Please provide the following information about your PR: - -- `mpegCoder` version: - -## Additional context - -Add any other context about the problem here. diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.yml b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.yml deleted file mode 100644 index 8b55cb6..0000000 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Pull request -description: Send a pull request (PR) for this project. -title: "[PR]" - -body: - - type: checkboxes - attributes: - label: Get started - options: - - label: >- - I have read [Contributing guidelines](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CONTRIBUTING.md). - required: true - - label: >- - I agree to follow the [Code of Conduct](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CODE_OF_CONDUCT.md). - required: true - - label: >- - I have confirmed that my pull request (PR) is not duplicated with an existing PR. - required: true - - label: >- - I have confirmed that my pull request (PR) passes the testing workflow of the project. - required: true - - - type: textarea - attributes: - label: Description - description: >- - Describe what you have done with this PR. - - - type: textarea - attributes: - label: Updated report - description: >- - Summarize your modifications as itemized report. - value: | - 1. Update ... - 2. Add ... - - - type: input - attributes: - label: mpegCoder version - description: >- - e.g. 3.1.0 - validations: - required: true - - - type: textarea - attributes: - label: Additional context - description: >- - Add any other context about the problem here. diff --git a/.gitignore b/.gitignore index 8c1a3d3..2f05d4c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ # Others include/* lib/* +/dependencies/* .vs/* +.vscode/* *.pdb *.pyd *.ipdb @@ -13,13 +15,9 @@ lib/* unsuccessfulbuild /MpegCoder/x64/ -# Compressed files -*.tar.xz -*.tar.gz -*.tar.bz2 -*.7z -*.zip -*.rar +# Scripts +*.sh +!/apt-requirements.sh # Prerequisites *.d @@ -53,3 +51,127 @@ unsuccessfulbuild *.exe *.out *.app + + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c722a8..781b55b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ 2. Fix the const assignment bug caused by the codec configuration method. +3. Upgrade the dependencies of FFMpeg to the newest versions (issue [#4 :exclamation:](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/issues/4)). + ### V3.1.0 update report: 1. Support `str()` type for all string arguments. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 4aa8000..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,128 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or - advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email - address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -cainmagi@gmail.com. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. - -Community Impact Guidelines were inspired by [Mozilla's code of conduct -enforcement ladder](https://github.com/mozilla/diversity). - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index eddc2b7..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,59 +0,0 @@ -# Contributing to mpegCoder - -Thank you for your interest in contributing to `mpegCoder`! We are accepting pull -requests in any time. - -As a reminder, all contributors are expected to follow our [Code of Conduct][coc]. - -[coc]: https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/master/CODE_OF_CONDUCT.md - -## Contributing to the package - -### Installation - -Please [fork] this project as your own repository, and create a sub-branch based on any branch in this project. The new branch name could be a short description of the implemented new feature. - -After that, clone your repository by - -```shell -git clone -b --single-branch https://github.com//FFmpeg-Encoder-Decoder-for-Python.git mpegCoder -``` - -In some cases, you may need to install some dependencies. Please follow the specific instructions for compling `mpegCoder`. - -### Debugging - -We have not provided any testing scripts now. I am glad to accept the help from anyone who is willing to writing the testing scripts for this project. - -### Sending pull requests - -After you finish your works, please send a new request, and compare your branch with the target branch in `mpegCoder`. You could explain your works concisely in the pull request description. You are not required to add the updating reports in the repository, or add the documentation. I could take over these works based on your description. - -## Contributing to docs - -If you want to contribute to docs, please fork the [`docs`](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/tree/docs) branch, and clone it - -```shell -git clone -b docs --single-branch https://github.com//FFmpeg-Encoder-Decoder-for-Python.git mpegCoder-docs -``` - -You need to install `nodejs` and `yarn` first. We suggest to create an isolated conda environment: - -```shell -conda create -n docs -c conda-forge git python=3.9 nodejs=15.14.0 yarn=1.22.10 -``` - -Then you could initialize the docs project by - -```shell -cd mpegCoder-docs -yarn install -``` - -You could start the local debugging by - -```shell -yarn start -``` - -After you finish your works, you could also send a pull request. diff --git a/MpegCoder.sln b/MpegCoder.sln deleted file mode 100644 index 7215572..0000000 --- a/MpegCoder.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31410.357 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MpegCoder", "MpegCoder\MpegCoder.vcxproj", "{57C5DB39-2AA7-40DD-B7E1-162B3E7F7044}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {57C5DB39-2AA7-40DD-B7E1-162B3E7F7044}.Debug|x64.ActiveCfg = Debug|x64 - {57C5DB39-2AA7-40DD-B7E1-162B3E7F7044}.Debug|x64.Build.0 = Debug|x64 - {57C5DB39-2AA7-40DD-B7E1-162B3E7F7044}.Debug|x86.ActiveCfg = Debug|Win32 - {57C5DB39-2AA7-40DD-B7E1-162B3E7F7044}.Debug|x86.Build.0 = Debug|Win32 - {57C5DB39-2AA7-40DD-B7E1-162B3E7F7044}.Release|x64.ActiveCfg = Release|x64 - {57C5DB39-2AA7-40DD-B7E1-162B3E7F7044}.Release|x64.Build.0 = Release|x64 - {57C5DB39-2AA7-40DD-B7E1-162B3E7F7044}.Release|x86.ActiveCfg = Release|Win32 - {57C5DB39-2AA7-40DD-B7E1-162B3E7F7044}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {C950261D-8B64-4B1B-8275-B7B3F8F58C6E} - EndGlobalSection -EndGlobal diff --git a/MpegCoder/MpegBase.cpp b/MpegCoder/MpegBase.cpp index 55e76f7..c2e44bc 100644 --- a/MpegCoder/MpegBase.cpp +++ b/MpegCoder/MpegBase.cpp @@ -1,4 +1,3 @@ -#include "stdafx.h" #include "MpegBase.h" // Global functions. diff --git a/MpegCoder/MpegCoder.cpp b/MpegCoder/MpegCoder.cpp index 4f9abf6..7d558ff 100644 --- a/MpegCoder/MpegCoder.cpp +++ b/MpegCoder/MpegCoder.cpp @@ -1,21 +1,16 @@ -// MpegCoder.cpp: 定义 DLL 应用程序的导出函数。 -// - -#include "stdafx.h" +// MpegCoder.cpp: Define the exporated methods of the DLL files. #define NO_IMPORT_ARRAY #define PY_ARRAY_UNIQUE_SYMBOL MPEGARRAY_API +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include #include "MpegCoder.h" #include "MpegStreamer.h" int8_t cmpc::__dumpControl = 1; -// 这是已导出类的构造函数。 -// 有关类定义的信息,请参阅 MpegCoder.h - // Constructors. -cmpc::CMpegDecoder::CMpegDecoder(void) : +cmpc::CMpegDecoder::CMpegDecoder(void): videoPath(), width(0), height(0), widthDst(0), heightDst(0), PPixelFormat(STREAM_PIX_FMT), PFormatCtx(nullptr), PCodecCtx(nullptr), PVideoStream(nullptr), PVideoStreamIDX(-1), PVideoFrameCount(0), RGBbuffer(nullptr), PswsCtx(nullptr), @@ -76,7 +71,7 @@ cmpc::CMpegDecoder::~CMpegDecoder() { clear(); } -cmpc::CMpegDecoder::CMpegDecoder(const CMpegDecoder& ref) : +cmpc::CMpegDecoder::CMpegDecoder(const CMpegDecoder &ref): videoPath(ref.videoPath), width(0), height(0), widthDst(ref.widthDst), heightDst(ref.heightDst), PPixelFormat(ref.PPixelFormat), PFormatCtx(nullptr), PCodecCtx(nullptr), PVideoStream(nullptr), PVideoStreamIDX(-1), PVideoFrameCount(0), RGBbuffer(nullptr), PswsCtx(nullptr), @@ -87,7 +82,7 @@ cmpc::CMpegDecoder::CMpegDecoder(const CMpegDecoder& ref) : } } -cmpc::CMpegDecoder& cmpc::CMpegDecoder::operator=(const CMpegDecoder& ref) { +cmpc::CMpegDecoder& cmpc::CMpegDecoder::operator=(const CMpegDecoder &ref) { if (this != &ref) { videoPath.assign(ref.videoPath); width = 0; @@ -116,7 +111,7 @@ cmpc::CMpegDecoder& cmpc::CMpegDecoder::operator=(const CMpegDecoder& ref) { return *this; } -cmpc::CMpegDecoder::CMpegDecoder(CMpegDecoder&& ref) noexcept : +cmpc::CMpegDecoder::CMpegDecoder(CMpegDecoder &&ref) noexcept: videoPath(std::move(ref.videoPath)), width(ref.width), height(ref.height), widthDst(ref.widthDst), heightDst(ref.heightDst), PPixelFormat(ref.PPixelFormat), PFormatCtx(ref.PFormatCtx), PCodecCtx(ref.PCodecCtx), PVideoStream(ref.PVideoStream), @@ -131,7 +126,7 @@ cmpc::CMpegDecoder::CMpegDecoder(CMpegDecoder&& ref) noexcept : ref.PswsCtx = nullptr; } -cmpc::CMpegDecoder& cmpc::CMpegDecoder::operator=(CMpegDecoder&& ref) noexcept { +cmpc::CMpegDecoder& cmpc::CMpegDecoder::operator=(CMpegDecoder &&ref) noexcept { if (this != &ref) { videoPath.assign(std::move(ref.videoPath)); width = ref.width; @@ -176,11 +171,11 @@ void cmpc::CMpegDecoder::setGOPPosition(double inpos) { EndofGOP = false; } -int cmpc::CMpegDecoder::_open_codec_context(int& stream_idx, AVCodecContext*& dec_ctx, \ - AVFormatContext* PFormatCtx, enum AVMediaType type) { // Search the correct decoder, and make the configurations. +int cmpc::CMpegDecoder::_open_codec_context(int &stream_idx, AVCodecContext *&dec_ctx, \ + AVFormatContext *PFormatCtx, enum AVMediaType type) { // Search the correct decoder, and make the configurations. auto ret = av_find_best_stream(PFormatCtx, type, -1, -1, nullptr, 0); if (ret < 0) { - cerr << "Could not find " << av_get_media_type_string(type) << \ + cerr << "Could not find "<< av_get_media_type_string(type) << \ " stream in input file '" << videoPath << "'" << endl; return ret; } @@ -215,7 +210,7 @@ int cmpc::CMpegDecoder::_open_codec_context(int& stream_idx, AVCodecContext*& de } /* Init the decoders, with or without reference counting */ - AVDictionary* opts = nullptr; // The uninitialized argument dictionary. + AVDictionary *opts = nullptr; // The uninitialized argument dictionary. av_dict_set(&opts, "refcounted_frames", refcount ? "1" : "0", 0); if ((ret = avcodec_open2(dec_ctx_, dec, &opts)) < 0) { cerr << "Failed to open " << av_get_media_type_string(type) << " codec" << endl; @@ -243,7 +238,7 @@ bool cmpc::CMpegDecoder::FFmpegSetup() { // Open the video file, and search the /* retrieve stream information */ if (avformat_find_stream_info(PFormatCtx, nullptr) < 0) { - cerr << "Could not find stream information" << endl; + cerr << "Could not find stream information" << endl; return false; } @@ -257,7 +252,7 @@ bool cmpc::CMpegDecoder::FFmpegSetup() { // Open the video file, and search the height = PCodecCtx->height; PPixelFormat = PCodecCtx->pix_fmt; _duration = static_cast(PVideoStream->duration) / static_cast(time_base.den) * static_cast(time_base.num); - _predictFrameNum = av_rescale(static_cast(_duration * 0xFFFF), frame_base.num, frame_base.den) / 0xFFFF; + _predictFrameNum = av_rescale(static_cast(_duration*0xFFFF), frame_base.num, frame_base.den)/0xFFFF; } /* dump input information to stderr */ @@ -276,12 +271,12 @@ bool cmpc::CMpegDecoder::FFmpegSetup() { // Open the video file, and search the if (widthDst > 0 && heightDst > 0) { PswsCtx = sws_getContext(width, height, PPixelFormat, widthDst, heightDst, AVPixelFormat::AV_PIX_FMT_RGB24, SCALE_FLAGS, nullptr, nullptr, nullptr); auto numBytes = av_image_get_buffer_size(AVPixelFormat::AV_PIX_FMT_RGB24, widthDst, heightDst, 1); - RGBbuffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t)); + RGBbuffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); } else { PswsCtx = sws_getContext(width, height, PPixelFormat, width, height, AVPixelFormat::AV_PIX_FMT_RGB24, SCALE_FLAGS, nullptr, nullptr, nullptr); auto numBytes = av_image_get_buffer_size(AVPixelFormat::AV_PIX_FMT_RGB24, width, height, 1); - RGBbuffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t)); + RGBbuffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); } return true; } @@ -295,13 +290,13 @@ void cmpc::CMpegDecoder::dumpFormat() { } } -void cmpc::CMpegDecoder::setParameter(string keyword, void* ptr) { +void cmpc::CMpegDecoder::setParameter(string keyword, void *ptr) { if (keyword.compare("widthDst") == 0) { - auto ref = reinterpret_cast(ptr); + auto ref = reinterpret_cast(ptr); widthDst = *ref; } else if (keyword.compare("heightDst") == 0) { - auto ref = reinterpret_cast(ptr); + auto ref = reinterpret_cast(ptr); heightDst = *ref; } else if (keyword.compare("nthread") == 0) { @@ -372,7 +367,7 @@ PyObject* cmpc::CMpegDecoder::getParameter() { Py_DECREF(val); if (PVideoStream) { key.assign("frameRate"); - auto& frame_rate = PVideoStream->avg_frame_rate; + auto &frame_rate = PVideoStream->avg_frame_rate; val = Py_BuildValue("(ii)", frame_rate.num, frame_rate.den); PyDict_SetItemString(res, key.c_str(), val); Py_DECREF(val); @@ -380,7 +375,7 @@ PyObject* cmpc::CMpegDecoder::getParameter() { return res; } -PyObject* cmpc::CMpegDecoder::getParameter(string keyword) { +PyObject * cmpc::CMpegDecoder::getParameter(string keyword) { if (keyword.compare("videoPath") == 0) { return PyUnicode_DecodeFSDefaultAndSize(videoPath.c_str(), static_cast(videoPath.size())); } @@ -421,7 +416,7 @@ PyObject* cmpc::CMpegDecoder::getParameter(string keyword) { } // The flush packet is a non-NULL packet with size 0 and data NULL -int cmpc::CMpegDecoder::__avcodec_decode_video2(AVCodecContext* avctx, AVFrame* frame, bool& got_frame, AVPacket* pkt) { +int cmpc::CMpegDecoder::__avcodec_decode_video2(AVCodecContext *avctx, AVFrame *frame, bool &got_frame, AVPacket *pkt) { int ret; got_frame = false; @@ -447,10 +442,10 @@ int cmpc::CMpegDecoder::__avcodec_decode_video2(AVCodecContext* avctx, AVFrame* return 0; } -int cmpc::CMpegDecoder::_SaveFrame(PyObject* PyFrameList, AVFrame*& frame, AVFrame*& frameRGB, AVPacket*& pkt, bool& got_frame, int64_t minPTS, bool& processed, int cached) { +int cmpc::CMpegDecoder::_SaveFrame(PyObject *PyFrameList, AVFrame *&frame, AVFrame *&frameRGB, AVPacket *&pkt, bool &got_frame, int64_t minPTS, bool &processed, int cached) { int ret = 0; int decoded = pkt->size; - PyObject* OneFrame = nullptr; + PyObject *OneFrame = nullptr; got_frame = false; @@ -484,12 +479,12 @@ int cmpc::CMpegDecoder::_SaveFrame(PyObject* PyFrameList, AVFrame*& frame, AVFra return -1; } - + PVideoFrameCount++; if (__dumpControl > 0) { std::ostringstream str_data; str_data << "video_frame" << (cached ? "(cached)" : "") << " n:" << PVideoFrameCount << - " coded_n:" << frame->coded_picture_number << endl; + " coded_n:" << frame->coded_picture_number << endl; auto str_data_s = str_data.str(); av_log(nullptr, AV_LOG_INFO, "%s", str_data_s.c_str()); } @@ -498,9 +493,9 @@ int cmpc::CMpegDecoder::_SaveFrame(PyObject* PyFrameList, AVFrame*& frame, AVFra * this is required since rawvideo expects non aligned data */ sws_scale(PswsCtx, frame->data, frame->linesize, 0, height, frameRGB->data, frameRGB->linesize); - + /* write to rawvideo file */ - if (widthDst > 0 && heightDst > 0) + if (widthDst>0 && heightDst>0) OneFrame = _SaveFrame_castToPyFrameArray(frameRGB->data, widthDst, heightDst); else OneFrame = _SaveFrame_castToPyFrameArray(frameRGB->data, width, height); @@ -518,10 +513,10 @@ int cmpc::CMpegDecoder::_SaveFrame(PyObject* PyFrameList, AVFrame*& frame, AVFra return decoded; } -int cmpc::CMpegDecoder::_SaveFrameForGOP(PyObject* PyFrameList, AVFrame*& frame, AVFrame*& frameRGB, AVPacket*& pkt, bool& got_frame, int& GOPstate, bool& processed, int cached) { +int cmpc::CMpegDecoder::_SaveFrameForGOP(PyObject *PyFrameList, AVFrame *&frame, AVFrame *&frameRGB, AVPacket *&pkt, bool &got_frame, int &GOPstate, bool &processed, int cached) { int ret = 0; int decoded = pkt->size; - PyObject* OneFrame = nullptr; + PyObject *OneFrame = nullptr; got_frame = false; @@ -535,7 +530,7 @@ int cmpc::CMpegDecoder::_SaveFrameForGOP(PyObject* PyFrameList, AVFrame*& frame, if (got_frame) { - currentGOPTSM = frame->pts + 1; + currentGOPTSM = frame->pts+1; switch (GOPstate) { case 0: @@ -590,7 +585,7 @@ int cmpc::CMpegDecoder::_SaveFrameForGOP(PyObject* PyFrameList, AVFrame*& frame, sws_scale(PswsCtx, frame->data, frame->linesize, 0, height, frameRGB->data, frameRGB->linesize); /* write to rawvideo file */ - if (widthDst > 0 && heightDst > 0) + if (widthDst>0 && heightDst>0) OneFrame = _SaveFrame_castToPyFrameArray(frameRGB->data, widthDst, heightDst); else OneFrame = _SaveFrame_castToPyFrameArray(frameRGB->data, width, height); @@ -610,23 +605,23 @@ int cmpc::CMpegDecoder::_SaveFrameForGOP(PyObject* PyFrameList, AVFrame*& frame, return decoded; } -PyObject* cmpc::CMpegDecoder::_SaveFrame_castToPyFrameArray(uint8_t* data[], int fWidth, int fHeight) { +PyObject *cmpc::CMpegDecoder::_SaveFrame_castToPyFrameArray(uint8_t *data[], int fWidth, int fHeight) { npy_intp dims[] = { fHeight, fWidth, 3 }; auto newdata = new uint8_t[static_cast(fHeight) * static_cast(fWidth) * 3]; memcpy(newdata, data[0], static_cast(fHeight) * static_cast(fWidth) * 3); - PyObject* PyFrame = PyArray_SimpleNewFromData(3, dims, NPY_UINT8, reinterpret_cast(newdata)); + PyObject *PyFrame = PyArray_SimpleNewFromData(3, dims, NPY_UINT8, reinterpret_cast(newdata)); PyArray_ENABLEFLAGS((PyArrayObject*)PyFrame, NPY_ARRAY_OWNDATA); return PyFrame; } attribute_deprecated -PyObject* cmpc::CMpegDecoder::_SaveFrame_castToPyFrameArrayOld(uint8_t* data[], int fWidth, int fHeight) { +PyObject *cmpc::CMpegDecoder::_SaveFrame_castToPyFrameArrayOld(uint8_t *data[], int fWidth, int fHeight) { npy_intp dims[] = { static_cast(fHeight) * static_cast(fWidth) * 3 }; - PyObject* PyFrame = PyArray_SimpleNew(1, dims, NPY_UINT8); + PyObject *PyFrame = PyArray_SimpleNew(1, dims, NPY_UINT8); if (PyFrame == NULL) { Py_RETURN_NONE; } - auto out_iter = NpyIter_New((PyArrayObject*)PyFrame, NPY_ITER_READWRITE, + auto out_iter = NpyIter_New((PyArrayObject *)PyFrame, NPY_ITER_READWRITE, NPY_CORDER, NPY_NO_CASTING, NULL); if (out_iter == NULL) { Py_DECREF(PyFrame); @@ -645,17 +640,17 @@ PyObject* cmpc::CMpegDecoder::_SaveFrame_castToPyFrameArrayOld(uint8_t* data[], /* The location of the data pointer which the iterator may update */ auto dataptr = NpyIter_GetDataPtrArray(out_iter); //auto out_iter = (PyArrayIterObject *)PyArray_IterNew(PyFrame); - uint8_t* pdata = data[0]; + uint8_t * pdata = data[0]; for (auto i = 0; i < fHeight; i++) { for (auto j = 0; j < fWidth; j++) { - for (auto k = 0; k < 3; k++, pdata++) { - uint8_t* out_dataptr = (uint8_t*)(*dataptr); + for (auto k = 0; k < 3; k++, pdata++ ) { + uint8_t * out_dataptr = (uint8_t *) (*dataptr); *out_dataptr = *pdata; iternext(out_iter); } } } - PyObject* pyshape = Py_BuildValue("[iii]", fHeight, fWidth, 3); + PyObject *pyshape = Py_BuildValue("[iii]", fHeight, fWidth, 3); PyFrame = PyArray_Reshape((PyArrayObject*)PyFrame, pyshape); Py_DECREF(pyshape); NpyIter_Deallocate(out_iter); @@ -664,17 +659,17 @@ PyObject* cmpc::CMpegDecoder::_SaveFrame_castToPyFrameArrayOld(uint8_t* data[], return PyFrame; } -int64_t cmpc::CMpegDecoder::__FrameToPts(int64_t seekFrame) const { +int64_t cmpc::CMpegDecoder::__FrameToPts(int64_t seekFrame) const{ auto time_base = PVideoStream->time_base; auto frame_base = PVideoStream->avg_frame_rate; //cout << "Frame_Base: den=" << frame_base.den << ", num=" << frame_base.num << endl; - auto seekTimeStamp = PVideoStream->start_time + av_rescale(av_rescale(seekFrame, time_base.den, time_base.num), frame_base.den, frame_base.num); + auto seekTimeStamp = PVideoStream->start_time + av_rescale( av_rescale(seekFrame, time_base.den, time_base.num), frame_base.den, frame_base.num ); return seekTimeStamp; } int64_t cmpc::CMpegDecoder::__TimeToPts(double seekTime) const { auto time_base = PVideoStream->time_base; - auto seekTimeStamp = PVideoStream->start_time + av_rescale(static_cast(seekTime * 1000), time_base.den, time_base.num) / 1000; + auto seekTimeStamp = PVideoStream->start_time + av_rescale(static_cast(seekTime*1000), time_base.den, time_base.num)/1000; return seekTimeStamp; } @@ -685,14 +680,14 @@ bool cmpc::CMpegDecoder::ExtractGOP(PyObject* PyFrameList) { if (EndofGOP) return false; - AVFrame* frame = av_frame_alloc(); + AVFrame *frame = av_frame_alloc(); auto pkt = av_packet_alloc(); if (!frame) { cerr << "Could not allocate frame" << endl; ret = AVERROR(ENOMEM); return false; } - AVFrame* frameRGB = av_frame_alloc(); + AVFrame *frameRGB = av_frame_alloc(); if (!frameRGB) { cerr << "Could not allocate frameRGB" << endl; return false; @@ -890,7 +885,7 @@ bool cmpc::CMpegDecoder::ExtractFrame(PyObject* PyFrameList, int64_t framePos, i return true; } -ostream& cmpc::operator<<(ostream& out, cmpc::CMpegDecoder& self_class) { +ostream & cmpc::operator<<(ostream & out, cmpc::CMpegDecoder & self_class) { out << std::setw(1) << "/"; out << std::setfill('*') << std::setw(44) << "" << std::setfill(' ') << endl; out << std::setw(1) << " * Packed FFmpeg Decoder - Y. Jin V" << MPEGCODER_CURRENT_VERSION << endl; @@ -927,7 +922,7 @@ ostream& cmpc::operator<<(ostream& out, cmpc::CMpegDecoder& self_class) { */ // Constructors following 3-5 law. -cmpc::CMpegEncoder::CMpegEncoder(void) : +cmpc::CMpegEncoder::CMpegEncoder(void): videoPath(), codecName(), bitRate(1024), width(100), height(100), widthSrc(0), heightSrc(0), timeBase(_setAVRational(1, 25)), frameRate(_setAVRational(25, 1)), GOPSize(10), MaxBFrame(1), PStreamContex({ 0 }), PFormatCtx(nullptr), Ppacket(nullptr), PswsCtx(nullptr), @@ -960,7 +955,7 @@ cmpc::CMpegEncoder::~CMpegEncoder(void) { clear(); } -cmpc::CMpegEncoder::CMpegEncoder(const CMpegEncoder& ref) : +cmpc::CMpegEncoder::CMpegEncoder(const CMpegEncoder &ref): videoPath(ref.videoPath), codecName(ref.codecName), bitRate(ref.bitRate), width(ref.width), height(ref.height), widthSrc(ref.widthSrc), heightSrc(ref.heightSrc), timeBase(ref.timeBase), frameRate(ref.frameRate), GOPSize(ref.GOPSize), MaxBFrame(ref.MaxBFrame), @@ -972,7 +967,7 @@ cmpc::CMpegEncoder::CMpegEncoder(const CMpegEncoder& ref) : } } -cmpc::CMpegEncoder& cmpc::CMpegEncoder::operator=(const CMpegEncoder& ref) { +cmpc::CMpegEncoder& cmpc::CMpegEncoder::operator=(const CMpegEncoder &ref) { if (this != &ref) { videoPath.assign(ref.videoPath); codecName.assign(ref.codecName); @@ -1001,7 +996,7 @@ cmpc::CMpegEncoder& cmpc::CMpegEncoder::operator=(const CMpegEncoder& ref) { return *this; } -cmpc::CMpegEncoder::CMpegEncoder(CMpegEncoder&& ref) noexcept : +cmpc::CMpegEncoder::CMpegEncoder(CMpegEncoder &&ref) noexcept: videoPath(std::move(ref.videoPath)), codecName(std::move(ref.codecName)), bitRate(ref.bitRate), width(ref.width), height(ref.height), widthSrc(ref.widthSrc), heightSrc(ref.heightSrc), timeBase(ref.timeBase), frameRate(ref.frameRate), GOPSize(ref.GOPSize), MaxBFrame(ref.MaxBFrame), @@ -1016,7 +1011,7 @@ cmpc::CMpegEncoder::CMpegEncoder(CMpegEncoder&& ref) noexcept : ref.__frameRGB = nullptr; } -cmpc::CMpegEncoder& cmpc::CMpegEncoder::operator=(CMpegEncoder&& ref) noexcept { +cmpc::CMpegEncoder& cmpc::CMpegEncoder::operator=(CMpegEncoder &&ref) noexcept { if (this != &ref) { videoPath.assign(std::move(ref.videoPath)); codecName.assign(std::move(ref.codecName)); @@ -1071,16 +1066,16 @@ int64_t cmpc::CMpegEncoder::__TimeToPts(double seekTime) const { return av_rescale(static_cast(seekTime * 1000), timeBase.den, timeBase.num) / 1000; } -void cmpc::CMpegEncoder::__log_packet() { - AVRational* time_base = &PFormatCtx->streams[Ppacket->stream_index]->time_base; +void cmpc::CMpegEncoder::__log_packet(){ + AVRational *time_base = &PFormatCtx->streams[Ppacket->stream_index]->time_base; std::ostringstream str_data; str_data << "pts:" << av_ts2str(Ppacket->pts) << " pts_time:" << av_ts2timestr(Ppacket->pts, time_base) - << " dts:" << av_ts2str(Ppacket->dts) << " dts_time:" << av_ts2timestr(Ppacket->dts, time_base) << endl; + << " dts:" << av_ts2str(Ppacket->dts) << " dts_time:" << av_ts2timestr(Ppacket->dts, time_base) << endl; auto str_data_s = str_data.str(); av_log(nullptr, AV_LOG_INFO, "%s", str_data_s.c_str()); } -int cmpc::CMpegEncoder::__write_frame() { +int cmpc::CMpegEncoder::__write_frame(){ /* rescale output packet timestamp values from codec to stream timebase */ av_packet_rescale_ts(Ppacket, PStreamContex.enc->time_base, PStreamContex.st->time_base); Ppacket->stream_index = PStreamContex.st->index; @@ -1197,7 +1192,7 @@ const cmpc::AVCodec* cmpc::CMpegEncoder::__add_stream() { } if (!RGBbuffer) { auto numBytes = av_image_get_buffer_size(AVPixelFormat::AV_PIX_FMT_RGB24, srcwidth, srcheight, 1); - RGBbuffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t)); + RGBbuffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); } break; @@ -1231,7 +1226,7 @@ cmpc::AVFrame* cmpc::CMpegEncoder::__alloc_picture(enum AVPixelFormat pix_fmt, i bool cmpc::CMpegEncoder::__open_video(const AVCodec* codec, const AVDictionary* opt_arg) { int ret; auto c = PStreamContex.enc; - AVDictionary* opt = nullptr; + AVDictionary *opt = nullptr; av_dict_copy(&opt, opt_arg, 0); /* open the codec */ @@ -1267,7 +1262,7 @@ bool cmpc::CMpegEncoder::__open_video(const AVCodec* codec, const AVDictionary* return true; } -cmpc::AVFrame* cmpc::CMpegEncoder::__get_video_frame(PyArrayObject* PyFrame) { +cmpc::AVFrame *cmpc::CMpegEncoder::__get_video_frame(PyArrayObject* PyFrame) { auto c = PStreamContex.enc; /* check if we want to generate more frames */ @@ -1295,7 +1290,7 @@ cmpc::AVFrame* cmpc::CMpegEncoder::__get_video_frame(PyArrayObject* PyFrame) { return nullptr; } sws_scale(PStreamContex.sws_ctx, - (const uint8_t* const*)PStreamContex.tmp_frame->data, PStreamContex.tmp_frame->linesize, + (const uint8_t * const *)PStreamContex.tmp_frame->data, PStreamContex.tmp_frame->linesize, 0, c->height, PStreamContex.frame->data, PStreamContex.frame->linesize); } else { @@ -1309,13 +1304,13 @@ cmpc::AVFrame* cmpc::CMpegEncoder::__get_video_frame(PyArrayObject* PyFrame) { return PStreamContex.frame; } -bool cmpc::CMpegEncoder::_LoadFrame_castFromPyFrameArray(AVFrame* frame, PyArrayObject* PyFrame) { +bool cmpc::CMpegEncoder::_LoadFrame_castFromPyFrameArray(AVFrame *frame, PyArrayObject* PyFrame) { /* make sure the frame data is writable */ if (!__frameRGB) { cerr << "Could not allocate frameRGB" << endl; return false; } - auto out_dataptr = reinterpret_cast(PyArray_DATA(PyFrame)); + auto out_dataptr = reinterpret_cast(PyArray_DATA(PyFrame)); auto srcwidth = widthSrc > 0 ? widthSrc : width; auto srcheight = heightSrc > 0 ? heightSrc : height; memcpy(RGBbuffer, out_dataptr, static_cast(srcwidth) * static_cast(srcheight) * 3 * sizeof(uint8_t)); @@ -1332,7 +1327,7 @@ bool cmpc::CMpegEncoder::_LoadFrame_castFromPyFrameArray(AVFrame* frame, PyArray * encode one video frame and send it to the muxer * return 1 when encoding is finished, 0 otherwise */ -int cmpc::CMpegEncoder::__avcodec_encode_video2(AVCodecContext* enc_ctx, AVPacket* pkt, AVFrame* frame) { +int cmpc::CMpegEncoder::__avcodec_encode_video2(AVCodecContext *enc_ctx, AVPacket *pkt, AVFrame *frame){ int ret; int wfret = 0; @@ -1344,7 +1339,7 @@ int cmpc::CMpegEncoder::__avcodec_encode_video2(AVCodecContext* enc_ctx, AVPacke av_log(nullptr, AV_LOG_DEBUG, "%s", str_data_s.c_str()); } } - else { + else{ return AVERROR(EAGAIN); } @@ -1377,7 +1372,7 @@ int cmpc::CMpegEncoder::__avcodec_encode_video2(AVCodecContext* enc_ctx, AVPacke return ret; } -int cmpc::CMpegEncoder::__avcodec_encode_video2_flush(AVCodecContext* enc_ctx, AVPacket* pkt) { +int cmpc::CMpegEncoder::__avcodec_encode_video2_flush(AVCodecContext *enc_ctx, AVPacket *pkt) { int ret; int wfret = 0; if (__dumpControl > 1) { @@ -1423,7 +1418,7 @@ int cmpc::CMpegEncoder::__avcodec_encode_video2_flush(AVCodecContext* enc_ctx, A int cmpc::CMpegEncoder::EncodeFrame(PyArrayObject* PyFrame) { int ret; auto c = PStreamContex.enc; - AVFrame* frame = nullptr; + AVFrame *frame = nullptr; if ((!__have_video) || (!__enable_header)) cerr << "Not allowed to use this method before FFmpegSetup()" << endl; if (PyFrame) { @@ -1434,7 +1429,7 @@ int cmpc::CMpegEncoder::EncodeFrame(PyArrayObject* PyFrame) { frame = nullptr; ret = __avcodec_encode_video2_flush(c, Ppacket); } - + if (ret < 0) { cerr << "Error encoding video frame: " << av_err2str(ret) << endl; return ret; @@ -1442,9 +1437,9 @@ int cmpc::CMpegEncoder::EncodeFrame(PyArrayObject* PyFrame) { return frame ? 0 : 1; } -void cmpc::CMpegEncoder::setParameter(string keyword, void* ptr) { +void cmpc::CMpegEncoder::setParameter(string keyword, void *ptr) { if (keyword.compare("decoder") == 0) { - CMpegDecoder* ref = reinterpret_cast(ptr); + CMpegDecoder *ref = reinterpret_cast(ptr); resetPath(ref->videoPath); codecName.assign(ref->_str_codec); if (ref->PCodecCtx) { @@ -1465,7 +1460,7 @@ void cmpc::CMpegEncoder::setParameter(string keyword, void* ptr) { if (ref->widthDst > 0 && ref->heightDst > 0) { width = ref->widthDst; height = ref->heightDst; - } + } else { width = ref->width; height = ref->height; @@ -1645,44 +1640,44 @@ void cmpc::CMpegEncoder::setParameter(string keyword, void* ptr) { } } else if (keyword.compare("videoPath") == 0) { - string* ref = reinterpret_cast(ptr); + string *ref = reinterpret_cast(ptr); resetPath(*ref); } else if (keyword.compare("codecName") == 0) { - string* ref = reinterpret_cast(ptr); + string *ref = reinterpret_cast(ptr); codecName.assign(*ref); } else if (keyword.compare("bitRate") == 0) { - double* ref = reinterpret_cast(ptr); + double *ref = reinterpret_cast(ptr); auto bit_rate = static_cast((*ref) * 1024); bitRate = bit_rate; } else if (keyword.compare("width") == 0) { - int* ref = reinterpret_cast(ptr); + int *ref = reinterpret_cast(ptr); width = *ref; } else if (keyword.compare("height") == 0) { - int* ref = reinterpret_cast(ptr); + int *ref = reinterpret_cast(ptr); height = *ref; } else if (keyword.compare("widthSrc") == 0) { - int* ref = reinterpret_cast(ptr); + int *ref = reinterpret_cast(ptr); widthSrc = *ref; } else if (keyword.compare("heightSrc") == 0) { - int* ref = reinterpret_cast(ptr); + int *ref = reinterpret_cast(ptr); heightSrc = *ref; } else if (keyword.compare("GOPSize") == 0) { - int* ref = reinterpret_cast(ptr); + int *ref = reinterpret_cast(ptr); GOPSize = *ref; } else if (keyword.compare("maxBframe") == 0) { - int* ref = reinterpret_cast(ptr); + int *ref = reinterpret_cast(ptr); MaxBFrame = *ref; } else if (keyword.compare("frameRate") == 0) { - PyObject* ref = reinterpret_cast(ptr); + PyObject *ref = reinterpret_cast(ptr); auto refObj = PyTuple_GetItem(ref, 0); int num = static_cast(PyLong_AsLong(refObj)); refObj = PyTuple_GetItem(ref, 1); @@ -1820,7 +1815,7 @@ bool cmpc::CMpegEncoder::FFmpegSetup() { if (!Ppacket) return false; - AVDictionary* opt = nullptr; + AVDictionary *opt = nullptr; //av_dict_set(&opt, "vcodec", codecName.c_str(), 0); //av_dict_set(&opt, "fflags", "", 0); @@ -1890,19 +1885,19 @@ bool cmpc::CMpegEncoder::FFmpegSetup() { cerr << "Error occurred when opening output file: " << av_err2str(ret) << endl; FFmpegClose(); return false; - } - else { + } + else{ __enable_header = true; } return true; } -void cmpc::CMpegEncoder::FFmpegClose() { +void cmpc::CMpegEncoder::FFmpegClose(){ if (__enable_header && __have_video) { //cout << "Flush Video" << endl; int x; if ((x = EncodeFrame(nullptr)) == 0) { - // cout << "Ret: " << x << endl; + // cout << "Ret: " << x << endl; } if (__dumpControl > 0) { std::ostringstream str_data; @@ -1964,7 +1959,7 @@ void cmpc::CMpegEncoder::dumpFormat() { cerr << "Not loaded video format context now. dumpFormat() is not avaliable." << endl; } -ostream& cmpc::operator<<(ostream& out, cmpc::CMpegEncoder& self_class) { +ostream & cmpc::operator<<(ostream & out, cmpc::CMpegEncoder & self_class) { out << std::setw(1) << "/"; out << std::setfill('*') << std::setw(44) << "" << std::setfill(' ') << endl; out << std::setw(1) << " * Packed FFmpeg Encoder - Y. Jin V" << MPEGCODER_CURRENT_VERSION << endl; @@ -1977,7 +1972,7 @@ ostream& cmpc::operator<<(ostream& out, cmpc::CMpegEncoder& self_class) { out << std::setiosflags(std::ios::left) << std::setw(25) << " * (WidthSrc, HeightSrc): " \ << self_class.widthSrc << ", " << self_class.heightSrc << endl; } - else if (self_class.widthSrc > 0) { + else if(self_class.widthSrc > 0) { out << std::setiosflags(std::ios::left) << std::setw(25) << " * WidthSrc: " \ << self_class.widthSrc << endl; } diff --git a/MpegCoder/MpegCoder.h b/MpegCoder/MpegCoder.h index 2ddf98b..dbba0b9 100644 --- a/MpegCoder/MpegCoder.h +++ b/MpegCoder/MpegCoder.h @@ -11,7 +11,7 @@ #define MPEGCODER_DEBUG -// Exported from MpegCoder.dll +// The following classes are exported to mpegCoder.so namespace cmpc { extern int8_t __dumpControl; @@ -22,17 +22,17 @@ namespace cmpc { public: CMpegDecoder(void); // Constructor. ~CMpegDecoder(void); // 3-5 law. Destructor. - CMpegDecoder(const CMpegDecoder& ref); // Copy constructor. - CMpegDecoder& operator=(const CMpegDecoder& ref); // Copy assignment operator. - CMpegDecoder(CMpegDecoder&& ref) noexcept; // Move constructor. - CMpegDecoder& operator=(CMpegDecoder&& ref) noexcept; // Move assignment operator. + CMpegDecoder(const CMpegDecoder &ref); // Copy constructor. + CMpegDecoder& operator=(const CMpegDecoder &ref); // Copy assignment operator. + CMpegDecoder(CMpegDecoder &&ref) noexcept; // Move constructor. + CMpegDecoder& operator=(CMpegDecoder &&ref) noexcept; // Move assignment operator. friend class CMpegEncoder; // Let the encoder be able to access the member of this class. friend class CMpegServer; // Let the server be able to access the member of this class. - friend ostream& operator<<(ostream& out, CMpegDecoder& self_class); // Show the results. + friend ostream & operator<<(ostream & out, CMpegDecoder & self_class); // Show the results. void clear(void); // Clear all configurations and resources. void meta_protected_clear(void); // Clear the resources, but the configurations are remained. void dumpFormat(); // Show the av_format results. - void setParameter(string keyword, void* ptr); // Set arguments. + void setParameter(string keyword, void *ptr); // Set arguments. PyObject* getParameter(string keyword); // Get the current arguments. PyObject* getParameter(); // Get all key arguments. void resetPath(string inVideoPath); // Reset the path (encoded) of the online video stream. @@ -47,14 +47,14 @@ namespace cmpc { int width, height; // Width, height of the video. int widthDst, heightDst; // Target width, height of ExtractFrame(). enum AVPixelFormat PPixelFormat; // Enum object of the pixel format. - AVFormatContext* PFormatCtx; // Format context of the video. - AVCodecContext* PCodecCtx; // Codec context of the video. - AVStream* PVideoStream; // Video stream. + AVFormatContext *PFormatCtx; // Format context of the video. + AVCodecContext *PCodecCtx; // Codec context of the video. + AVStream *PVideoStream; // Video stream. int PVideoStreamIDX; // The index of the video stream. int PVideoFrameCount; // The counter of the decoded frames. - uint8_t* RGBbuffer; // The buffer of the RGB formatted images. - struct SwsContext* PswsCtx; // The context of the scale transformator. + uint8_t *RGBbuffer; // The buffer of the RGB formatted images. + struct SwsContext *PswsCtx; // The context of the scale transformator. string _str_codec; // Show the name of the current codec. double _duration; // Show the time of the video play. @@ -69,12 +69,12 @@ namespace cmpc { * needs. Look for the use of refcount in this example to see what are the * differences of API usage between them. */ int refcount; // Reference count of the video frame. - int _open_codec_context(int& stream_idx, AVCodecContext*& dec_ctx, AVFormatContext* PFormatCtx, enum AVMediaType type); - int _SaveFrame(PyObject* PyFrameList, AVFrame*& frame, AVFrame*& frameRGB, AVPacket*& pkt, bool& got_frame, int64_t minPTS, bool& processed, int cached); - int _SaveFrameForGOP(PyObject* PyFrameList, AVFrame*& frame, AVFrame*& frameRGB, AVPacket*& pkt, bool& got_frame, int& GOPstate, bool& processed, int cached); - PyObject* _SaveFrame_castToPyFrameArray(uint8_t* data[], int fWidth, int fHeight); - PyObject* _SaveFrame_castToPyFrameArrayOld(uint8_t* data[], int fWidth, int fHeight); - int __avcodec_decode_video2(AVCodecContext* avctx, AVFrame* frame, bool& got_frame, AVPacket* pkt); + int _open_codec_context(int &stream_idx, AVCodecContext *&dec_ctx, AVFormatContext *PFormatCtx, enum AVMediaType type); + int _SaveFrame(PyObject *PyFrameList, AVFrame *&frame, AVFrame *&frameRGB, AVPacket *&pkt, bool &got_frame, int64_t minPTS, bool &processed, int cached); + int _SaveFrameForGOP(PyObject *PyFrameList, AVFrame *&frame, AVFrame *&frameRGB, AVPacket *&pkt, bool &got_frame, int &GOPstate, bool &processed, int cached); + PyObject *_SaveFrame_castToPyFrameArray(uint8_t *data[], int fWidth, int fHeight); + PyObject *_SaveFrame_castToPyFrameArrayOld(uint8_t *data[], int fWidth, int fHeight); + int __avcodec_decode_video2(AVCodecContext *avctx, AVFrame *frame, bool &got_frame, AVPacket *pkt); int64_t __FrameToPts(int64_t seekFrame) const; int64_t __TimeToPts(double seekTime) const; }; @@ -83,11 +83,11 @@ namespace cmpc { public: CMpegEncoder(void); // Constructor. ~CMpegEncoder(void); // 3-5 law. Destructor. - CMpegEncoder(const CMpegEncoder& ref); // Copy constructor. - CMpegEncoder& operator=(const CMpegEncoder& ref); // Copy assignment operator. - CMpegEncoder(CMpegEncoder&& ref) noexcept; // Move constructor. - CMpegEncoder& operator=(CMpegEncoder&& ref) noexcept; // Move assignment operator. - friend ostream& operator<<(ostream& out, CMpegEncoder& self_class); // Show the results. + CMpegEncoder(const CMpegEncoder &ref); // Copy constructor. + CMpegEncoder& operator=(const CMpegEncoder &ref); // Copy assignment operator. + CMpegEncoder(CMpegEncoder &&ref) noexcept; // Move constructor. + CMpegEncoder& operator=(CMpegEncoder &&ref) noexcept; // Move assignment operator. + friend ostream & operator<<(ostream & out, CMpegEncoder & self_class); // Show the results. void clear(void); // Clear all configurations and resources. void resetPath(string inVideoPath); // Reset the path of the output video stream. void dumpFormat(); // Show the av_format results. @@ -95,7 +95,7 @@ namespace cmpc { bool FFmpegSetup(string inVideoPath); // Configure the encoder with extra arguments. void FFmpegClose(); // Close the encoder, and finalize the written of the encoded video. int EncodeFrame(PyArrayObject* PyFrame); // Encode one frame. - void setParameter(string keyword, void* ptr); // Set arguments. + void setParameter(string keyword, void *ptr); // Set arguments. PyObject* getParameter(string keyword); // Get the current arguments. PyObject* getParameter(); // Get all key arguments. private: @@ -107,11 +107,11 @@ namespace cmpc { AVRational timeBase, frameRate; // The time base and the frame rate. int GOPSize, MaxBFrame; // The size of GOPs, and the maximal number of B frames. OutputStream PStreamContex; // The context of the current video parser. - AVFormatContext* PFormatCtx; // Format context of the video. - AVPacket* Ppacket; // AV Packet used for writing frames. - struct SwsContext* PswsCtx; // The context of the scale transformator. - AVFrame* __frameRGB; // A temp AV frame object. Used for converting the data format. - uint8_t* RGBbuffer; // Data buffer. + AVFormatContext *PFormatCtx; // Format context of the video. + AVPacket *Ppacket; // AV Packet used for writing frames. + struct SwsContext *PswsCtx; // The context of the scale transformator. + AVFrame *__frameRGB; // A temp AV frame object. Used for converting the data format. + uint8_t *RGBbuffer; // Data buffer. bool __have_video, __enable_header; int nthread; // The number of threads; @@ -119,15 +119,15 @@ namespace cmpc { AVRational _setAVRational(int num, int den); int64_t __FrameToPts(int64_t seekFrame) const; int64_t __TimeToPts(double seekTime) const; - bool _LoadFrame_castFromPyFrameArray(AVFrame* frame, PyArrayObject* PyFrame); + bool _LoadFrame_castFromPyFrameArray(AVFrame *frame, PyArrayObject* PyFrame); void __log_packet(); int __write_frame(); const AVCodec* __add_stream(); AVFrame* __alloc_picture(enum AVPixelFormat pix_fmt, int width, int height); bool __open_video(const AVCodec* codec, const AVDictionary* opt_arg); - AVFrame* __get_video_frame(PyArrayObject* PyFrame); - int __avcodec_encode_video2(AVCodecContext* enc_ctx, AVPacket* pkt, AVFrame* frame); - int __avcodec_encode_video2_flush(AVCodecContext* enc_ctx, AVPacket* pkt); + AVFrame *__get_video_frame(PyArrayObject* PyFrame); + int __avcodec_encode_video2(AVCodecContext *enc_ctx, AVPacket *pkt, AVFrame *frame); + int __avcodec_encode_video2_flush(AVCodecContext *enc_ctx, AVPacket *pkt); }; ostream& operator<<(ostream& out, CMpegDecoder& self_class); diff --git a/MpegCoder/MpegCoder.vcxproj b/MpegCoder/MpegCoder.vcxproj deleted file mode 100644 index 8aeef01..0000000 --- a/MpegCoder/MpegCoder.vcxproj +++ /dev/null @@ -1,196 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {57C5DB39-2AA7-40DD-B7E1-162B3E7F7044} - Win32Proj - MpegCoder - 10.0 - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - C:\Program Files\Python37\include;../include;$(IncludePath) - C:\Program Files\Python37\libs;../lib;$(LibraryPath) - - - true - C:\Users\cainm\.conda\envs\py310\include;C:\Users\cainm\.conda\envs\py310\lib\site-packages\numpy\core\include;..\include;$(IncludePath) - C:\Users\cainm\.conda\envs\py310\libs;C:\Users\cainm\.conda\envs\py310\lib\site-packages\numpy\core\lib;..\lib;$(LibraryPath) - - - false - C:\Program Files\Python37\include;../include;$(IncludePath) - C:\Program Files\Python37\libs;../lib;$(LibraryPath) - - - false - C:\Users\cainm\.conda\envs\py310\include;C:\Users\cainm\.conda\envs\py310\lib\site-packages\numpy\core\include;..\include;$(IncludePath) - C:\Users\cainm\.conda\envs\py310\libs;C:\Users\cainm\.conda\envs\py310\lib\site-packages\numpy\core\lib;..\lib;$(LibraryPath) - - - - Use - Level3 - Disabled - WIN32;_DEBUG;MpegCoder_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - - - Windows - true - avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;postproc.lib;swresample.lib;swscale.lib;%(AdditionalDependencies) - - - - - Use - Level3 - Disabled - _DEBUG;MpegCoder_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - true - - - Windows - true - python310.lib;python3.lib;npymath.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;%(AdditionalDependencies) - - - echo F | xcopy /y /i "$(OutDir)$(TargetName)$(TargetExt)" "$(OutDir)mpegCoder.pyd" - - - - - Use - Level3 - MaxSpeed - true - true - WIN32;NDEBUG;MpegCoder_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - - - Windows - true - true - true - avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;postproc.lib;swresample.lib;swscale.lib;%(AdditionalDependencies) - - - - - Use - Level3 - MaxSpeed - true - true - NDEBUG;MpegCoder_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - true - - - Windows - true - true - true - python310.lib;python3.lib;npymath.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;%(AdditionalDependencies) - - - echo F | xcopy /y /i "$(OutDir)$(TargetName)$(TargetExt)" "$(OutDir)mpegCoder.pyd" - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - \ No newline at end of file diff --git a/MpegCoder/MpegCoder.vcxproj.filters b/MpegCoder/MpegCoder.vcxproj.filters deleted file mode 100644 index 573b077..0000000 --- a/MpegCoder/MpegCoder.vcxproj.filters +++ /dev/null @@ -1,64 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - - - - - - - - \ No newline at end of file diff --git a/MpegCoder/MpegCoder.vcxproj.user b/MpegCoder/MpegCoder.vcxproj.user deleted file mode 100644 index be25078..0000000 --- a/MpegCoder/MpegCoder.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MpegCoder/MpegPyd.h b/MpegCoder/MpegPyd.h index 4aaa373..4aca321 100644 --- a/MpegCoder/MpegPyd.h +++ b/MpegCoder/MpegPyd.h @@ -2,13 +2,13 @@ #define MPEGPYD_H_INCLUDED #define PY_ARRAY_UNIQUE_SYMBOL MPEGARRAY_API +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include #include #include #include #include -#include #include #include #include "MpegCoder.h" @@ -16,17 +16,18 @@ using std::string; using std::ostringstream; -PyObject *str2PyStr(string Str) { // Convert the output string to the widechar unicode string. - int wlen = MultiByteToWideChar(CP_ACP, NULL, Str.c_str(), int(Str.size()), NULL, 0); - wchar_t* wszString = new wchar_t[static_cast(wlen) + 1]; - MultiByteToWideChar(CP_ACP, NULL, Str.c_str(), int(Str.size()), wszString, wlen); +PyObject *str2PyStr(string Str) { + // Convert the output string to the widechar unicode string. + int wlen = mbstowcs(nullptr, Str.c_str(), 0); + wchar_t* wszString = new wchar_t[wlen + 1]; + mbstowcs(wszString, Str.c_str(), wlen); wszString[wlen] = 0; PyObject* res = PyUnicode_FromWideChar(wszString, wlen); delete[] wszString; return res; } -bool PyStr2str(PyObject* py_str, string& s_str) { // Convert a python str to std::string. +bool PyStr2str(PyObject* py_str, string &s_str) { // Convert a python str to std::string. if (!py_str) { return false; } @@ -71,25 +72,25 @@ bool PyStr2str(PyObject* py_str, string& s_str) { // Convert a python str to st typedef struct _C_MpegDecoder { PyObject_HEAD // == PyObject ob_base; Define the PyObject header. - cmpc::CMpegDecoder* _in_Handle; // Define the implementation of the C Object. + cmpc::CMpegDecoder *_in_Handle; // Define the implementation of the C Object. } C_MpegDecoder; typedef struct _C_MpegEncoder { PyObject_HEAD // == PyObject ob_base; Define the PyObject header. - cmpc::CMpegEncoder* _in_Handle; // Define the implementation of the C Object. + cmpc::CMpegEncoder *_in_Handle; // Define the implementation of the C Object. } C_MpegEncoder; typedef struct _C_MpegClient { PyObject_HEAD // == PyObject ob_base; Define the PyObject header. - cmpc::CMpegClient* _in_Handle; // Define the implementation of the C Object. + cmpc::CMpegClient *_in_Handle; // Define the implementation of the C Object. } C_MpegClient; typedef struct _C_MpegServer { PyObject_HEAD // == PyObject ob_base; Define the PyObject header. - cmpc::CMpegServer* _in_Handle; // Define the implementation of the C Object. + cmpc::CMpegServer* _in_Handle; // Define the implementation of the C Object. } C_MpegServer; static PyMemberDef C_MPDC_DataMembers[] = // Register the members of the python class. @@ -128,11 +129,11 @@ static PyMemberDef C_MPSV_DataMembers[] = // Register the members of the /*static void Example(ClassName* Self, PyObject* pArgs); PyMODINIT_FUNC PyFunc_Example(void);*/ -static PyObject* C_MPC_Global(PyObject* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPC_Global(PyObject* Self, PyObject *args, PyObject *kwargs) { char dumpLevel = -1; cmpc::CharList kwlist_str({ "dumpLevel" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|B", kwlist, &dumpLevel)) { PyErr_SetString(PyExc_TypeError, "Error.GlobalSettings: invalid keyword'"); return nullptr; @@ -216,6 +217,7 @@ Yuchen's Mpeg Coder - Readme V3.2.0 update report: 1. Upgrade FFMpeg to 5.0. 2. Fix the const assignment bug caused by the codec configuration method. + 3. Upgrade the dependencies of FFMpeg to the newest versions (issue #4). V3.1.0 update report: 1. Support str() type for all string arguments. 2. Support http, ftp, sftp streams for MpegServer. @@ -280,13 +282,13 @@ V1.0 update report: /***************************************************************************** * Declare the core methods of the classes. *****************************************************************************/ -static int C_MPDC_init(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { // Construct +static int C_MPDC_init(C_MpegDecoder* Self, PyObject* args, PyObject *kwargs) { // Construct PyObject* vpath = nullptr; cmpc::CharList kwlist_str({ "videoPath" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &vpath)) { - PyErr_SetString(PyExc_TypeError, "Error.Initialize: need 'videoPath(str)'"); + PyErr_SetString(PyExc_TypeError, "Error.Initialize: need 'videoPath(str)'" ); return -1; } string in_vpath; @@ -398,14 +400,14 @@ static PyObject* C_MPSV_Repr(C_MpegServer* Self) { // The __repr__ operator. * C_MPDC_Setup: Configure the decoder by the video. * C_MPDC_ExtractFrame Extract serveral frames. *****************************************************************************/ -static PyObject* C_MPDC_Setup(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPDC_Setup(C_MpegDecoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (bool)C_MPDC_Setup method, the inputs are: * videoPath [str/bytes->str]: the video path to be decoded. */ PyObject* vpath = nullptr; cmpc::CharList kwlist_str({ "videoPath" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &vpath)) { PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'videoPath(str)'"); return nullptr; @@ -430,14 +432,14 @@ static PyObject* C_MPDC_Setup(C_MpegDecoder* Self, PyObject* args, PyObject* kwa Py_RETURN_FALSE; } -static PyObject* C_MPEC_Setup(C_MpegEncoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPEC_Setup(C_MpegEncoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (bool)C_MPEC_Setup method, the inputs are: * videoPath [str/bytes->str]: the video path to be encoded. */ PyObject* vpath = nullptr; cmpc::CharList kwlist_str({ "videoPath" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &vpath)) { PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'videoPath(str)'"); return nullptr; @@ -462,14 +464,14 @@ static PyObject* C_MPEC_Setup(C_MpegEncoder* Self, PyObject* args, PyObject* kwa Py_RETURN_FALSE; } -static PyObject* C_MPCT_Setup(C_MpegClient* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPCT_Setup(C_MpegClient* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (bool)C_MPCT_Setup method, the inputs are: * videoAddress [str/bytes->str]: the video path to be demuxed. */ PyObject* vpath = nullptr; cmpc::CharList kwlist_str({ "videoAddress" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &vpath)) { PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'videoAddress(str)'"); return nullptr; @@ -501,7 +503,7 @@ static PyObject* C_MPSV_Setup(C_MpegServer* Self, PyObject* args, PyObject* kwar PyObject* vpath = nullptr; cmpc::CharList kwlist_str({ "videoAddress" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &vpath)) { PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'videoAddress(str)'"); return nullptr; @@ -526,14 +528,14 @@ static PyObject* C_MPSV_Setup(C_MpegServer* Self, PyObject* args, PyObject* kwar Py_RETURN_FALSE; } -static PyObject* C_MPDC_resetPath(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPDC_resetPath(C_MpegDecoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (bool)C_MPDC_resetPath method, the inputs are: * videoPath [str/bytes->str]: the video path to be decoded. */ PyObject* vpath = nullptr; cmpc::CharList kwlist_str({ "videoPath" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &vpath)) { PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'videoPath(str)'"); return nullptr; @@ -555,7 +557,7 @@ static PyObject* C_MPEC_resetPath(C_MpegEncoder* Self, PyObject* args, PyObject* PyObject* vpath = nullptr; cmpc::CharList kwlist_str({ "videoPath" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &vpath)) { PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'videoPath(str)'"); return nullptr; @@ -570,14 +572,14 @@ static PyObject* C_MPEC_resetPath(C_MpegEncoder* Self, PyObject* args, PyObject* Py_RETURN_NONE; } -static PyObject* C_MPCT_resetPath(C_MpegClient* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPCT_resetPath(C_MpegClient* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (bool)C_MPCT_resetPath method, the inputs are: * videoAddress [str/bytes->str]: the video path to be demuxed. */ PyObject* vpath = nullptr; cmpc::CharList kwlist_str({ "videoAddress" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &vpath)) { PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'videoAddress(str)'"); return nullptr; @@ -599,7 +601,7 @@ static PyObject* C_MPSV_resetPath(C_MpegServer* Self, PyObject* args, PyObject* PyObject* vpath = nullptr; cmpc::CharList kwlist_str({ "videoAddress" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &vpath)) { PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'videoAddress(str)'"); return nullptr; @@ -632,24 +634,24 @@ static PyObject* C_MPCT_Terminate(C_MpegClient* Self) { /* Pay attention to the following two methods : * Why do we remove the Py_IN/DECREF? - * Because no temp variables are created, so we do not need to manage them, + * Because no temp variables are created, so we do not need to manage them, * but just use None as the returned value. */ -static PyObject* FreePyArray(PyArrayObject* PyArray) { - uint8_t* out_dataptr = (uint8_t*)PyArray_DATA(PyArray); - delete[] out_dataptr; +static PyObject* FreePyArray(PyArrayObject *PyArray) { + uint8_t * out_dataptr = (uint8_t *)PyArray_DATA(PyArray); + delete [] out_dataptr; return nullptr; } -void FreePyList(PyObject* PyList) { +void FreePyList(PyObject *PyList) { Py_ssize_t getlen = PyList_Size(PyList); for (Py_ssize_t i = 0; i < getlen; i++) { - PyObject* Item = PyList_GetItem(PyList, i); + PyObject *Item = PyList_GetItem(PyList, i); FreePyArray((PyArrayObject*)Item); } Py_DECREF(PyList); PyGC_Collect(); } -static PyObject* C_MPDC_ExtractFrame(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPDC_ExtractFrame(C_MpegDecoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (int)ExtractFrame method, the inputs are: * framePos [int->int64_t]: the start position of the extracted frames. * frameNum [int->int64_t]: the number of extracted frames. @@ -657,18 +659,18 @@ static PyObject* C_MPDC_ExtractFrame(C_MpegDecoder* Self, PyObject* args, PyObje int64_t framePos = 0, frameNum = 1; cmpc::CharList kwlist_str({ "framePos", "frameNum" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|LL", kwlist, &framePos, &frameNum)) { PyErr_SetString(PyExc_TypeError, "Error.ExtractFrame: need 'framePos(int)/frameNum(int)'"); return nullptr; } - PyObject* PyFrameList = PyList_New(static_cast(0)); + PyObject *PyFrameList = PyList_New(static_cast(0)); //cout << framePos << " - " << frameNum << endl; bool res = Self->_in_Handle->ExtractFrame(PyFrameList, framePos, frameNum, 0, 0); Py_ssize_t getlen = PyList_Size(PyFrameList); res = res && (getlen > 0); if (res) { - PyObject* PyFrameArray = PyArray_FromObject(PyFrameList, NPY_UINT8, 4, 4); + PyObject *PyFrameArray = PyArray_FromObject(PyFrameList, NPY_UINT8, 4, 4); FreePyList(PyFrameList); return PyFrameArray; } @@ -679,7 +681,7 @@ static PyObject* C_MPDC_ExtractFrame(C_MpegDecoder* Self, PyObject* args, PyObje } } -static PyObject* C_MPDC_ExtractFrame_Time(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPDC_ExtractFrame_Time(C_MpegDecoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (int)ExtractFrame method, the inputs are: * timePos [float->double]: the start position (time unit) of the extracted frames. * frameNum [int->int64_t]: the number of extracted frames. @@ -688,18 +690,18 @@ static PyObject* C_MPDC_ExtractFrame_Time(C_MpegDecoder* Self, PyObject* args, P int64_t frameNum = 1; cmpc::CharList kwlist_str({ "timePos", "frameNum" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|dL", kwlist, &timePos, &frameNum)) { PyErr_SetString(PyExc_TypeError, "Error.ExtractFrame_Time: need 'timePos(float)/frameNum(int)'"); return nullptr; } - PyObject* PyFrameList = PyList_New(static_cast(0)); + PyObject *PyFrameList = PyList_New(static_cast(0)); //cout << framePos << " - " << frameNum << endl; bool res = Self->_in_Handle->ExtractFrame(PyFrameList, 0, frameNum, timePos, 1); Py_ssize_t getlen = PyList_Size(PyFrameList); res = res && (getlen > 0); if (res) { - PyObject* PyFrameArray = PyArray_FromObject(PyFrameList, NPY_UINT8, 4, 4); + PyObject *PyFrameArray = PyArray_FromObject(PyFrameList, NPY_UINT8, 4, 4); FreePyList(PyFrameList); return PyFrameArray; } @@ -710,20 +712,20 @@ static PyObject* C_MPDC_ExtractFrame_Time(C_MpegDecoder* Self, PyObject* args, P } } -static PyObject* C_MPEC_EncodeFrame(C_MpegEncoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPEC_EncodeFrame(C_MpegEncoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (bool)EncodeFrame method, the inputs are: * PyArrayFrame [ndarray->PyArrayObject]: the frame to be encoded. */ - PyObject* PyArrayFrame = nullptr; + PyObject *PyArrayFrame = nullptr; cmpc::CharList kwlist_str({ "PyArrayFrame" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &PyArrayFrame)) { PyErr_SetString(PyExc_TypeError, "Error.EncodeFrame: need 'PyArrayFrame(ndarray)'"); return nullptr; } - int res = Self->_in_Handle->EncodeFrame(reinterpret_cast(PyArrayFrame)); - if (res >= 0) + int res = Self->_in_Handle->EncodeFrame(reinterpret_cast(PyArrayFrame)); + if (res>=0) Py_RETURN_TRUE; else Py_RETURN_FALSE; @@ -736,7 +738,7 @@ static PyObject* C_MPSV_ServeFrame(C_MpegServer* Self, PyObject* args, PyObject* PyObject* PyArrayFrame = nullptr; cmpc::CharList kwlist_str({ "PyArrayFrame" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &PyArrayFrame)) { PyErr_SetString(PyExc_TypeError, "Error.EncodeFrame: need 'PyArrayFrame(ndarray)'"); return nullptr; @@ -755,7 +757,7 @@ static PyObject* C_MPSV_ServeFrameBlock(C_MpegServer* Self, PyObject* args, PyOb PyObject* PyArrayFrame = nullptr; cmpc::CharList kwlist_str({ "PyArrayFrame" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &PyArrayFrame)) { PyErr_SetString(PyExc_TypeError, "Error.EncodeFrame: need 'PyArrayFrame(ndarray)'"); return nullptr; @@ -767,7 +769,7 @@ static PyObject* C_MPSV_ServeFrameBlock(C_MpegServer* Self, PyObject* args, PyOb Py_RETURN_FALSE; } -static PyObject* C_MPCT_ExtractFrame(C_MpegClient* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPCT_ExtractFrame(C_MpegClient* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (int)ExtractFrame method, the inputs are: * readSize [int->int64_t]: the number of frames to be readed. This value could not * exceeded the size of the frame buffer. @@ -775,13 +777,13 @@ static PyObject* C_MPCT_ExtractFrame(C_MpegClient* Self, PyObject* args, PyObjec int64_t readSize = 0; cmpc::CharList kwlist_str({ "readSize" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|L", kwlist, &readSize)) { PyErr_SetString(PyExc_TypeError, "Error.ExtractFrame: need 'readSize(int)'"); return nullptr; } - PyObject* res = nullptr; - if (readSize > 0) + PyObject *res = nullptr; + if (readSize>0) res = Self->_in_Handle->ExtractFrame(readSize); else res = Self->_in_Handle->ExtractFrame(); @@ -793,19 +795,19 @@ static PyObject* C_MPCT_ExtractFrame(C_MpegClient* Self, PyObject* args, PyObjec } } -static PyObject* C_MPDC_ExtractGOP(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPDC_ExtractGOP(C_MpegDecoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (int)ExtractGOP method, the inputs are: * framePos [int->int64_t]: the start position of the GOP to be extracted. */ int64_t framePos = -1; cmpc::CharList kwlist_str({ "framePos" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|L", kwlist, &framePos)) { PyErr_SetString(PyExc_TypeError, "Error.ExtractGOP: need 'framePos(int)'"); return nullptr; } - PyObject* PyFrameList = PyList_New(static_cast(0)); + PyObject *PyFrameList = PyList_New(static_cast(0)); //cout << framePos << " - " << frameNum << endl; if (!(framePos < 0)) Self->_in_Handle->setGOPPosition(framePos); @@ -813,7 +815,7 @@ static PyObject* C_MPDC_ExtractGOP(C_MpegDecoder* Self, PyObject* args, PyObject Py_ssize_t getlen = PyList_Size(PyFrameList); res = res && (getlen > 0); if (res) { - PyObject* PyFrameArray = PyArray_FromObject(PyFrameList, NPY_UINT8, 4, 4); + PyObject *PyFrameArray = PyArray_FromObject(PyFrameList, NPY_UINT8, 4, 4); FreePyList(PyFrameList); return PyFrameArray; } @@ -824,19 +826,19 @@ static PyObject* C_MPDC_ExtractGOP(C_MpegDecoder* Self, PyObject* args, PyObject } } -static PyObject* C_MPDC_ExtractGOP_Time(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPDC_ExtractGOP_Time(C_MpegDecoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (int)ExtractGOP_Time method, the inputs are: * timePos [float->double]: the start position (time unit) of the GOP to be extracted. */ double timePos = -1; cmpc::CharList kwlist_str({ "timePos" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|d", kwlist, &timePos)) { PyErr_SetString(PyExc_TypeError, "Error.ExtractGOP_Time: need 'timePos(float)'"); return nullptr; } - PyObject* PyFrameList = PyList_New(static_cast(0)); + PyObject *PyFrameList = PyList_New(static_cast(0)); //cout << framePos << " - " << frameNum << endl; if (!(timePos < 0)) Self->_in_Handle->setGOPPosition(timePos); @@ -844,7 +846,7 @@ static PyObject* C_MPDC_ExtractGOP_Time(C_MpegDecoder* Self, PyObject* args, PyO Py_ssize_t getlen = PyList_Size(PyFrameList); res = res && (getlen > 0); if (res) { - PyObject* PyFrameArray = PyArray_FromObject(PyFrameList, NPY_UINT8, 4, 4); + PyObject *PyFrameArray = PyArray_FromObject(PyFrameList, NPY_UINT8, 4, 4); FreePyList(PyFrameList); return PyFrameArray; } @@ -855,7 +857,7 @@ static PyObject* C_MPDC_ExtractGOP_Time(C_MpegDecoder* Self, PyObject* args, PyO } } -static PyObject* C_MPDC_setGOPPosition(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPDC_setGOPPosition(C_MpegDecoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (void)setGOPPosition method, the inputs are: * framePos [int->int64_t]: the start position of the GOP to be extracted. * timePos [float->double]: the start position (time unit) of the GOP to be extracted. @@ -864,7 +866,7 @@ static PyObject* C_MPDC_setGOPPosition(C_MpegDecoder* Self, PyObject* args, PyOb double timePos = -1; cmpc::CharList kwlist_str({ "framePos", "timePos" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Ld", kwlist, &framePos, &timePos)) { PyErr_SetString(PyExc_TypeError, "Error.setGOPPosition: need 'framePos(int)'/'timePos(float)'"); return nullptr; @@ -876,7 +878,7 @@ static PyObject* C_MPDC_setGOPPosition(C_MpegDecoder* Self, PyObject* args, PyOb Py_RETURN_NONE; } -static PyObject* C_MPDC_getParam(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPDC_getParam(C_MpegDecoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (bool)C_MPDC_getParam function, the inputs are: * paramName [str/bytes->str]: The name of the parameter to be gotten, could be. * videoPath: [str] Path of the current video. @@ -891,9 +893,9 @@ static PyObject* C_MPDC_getParam(C_MpegDecoder* Self, PyObject* args, PyObject* PyObject* param = nullptr; cmpc::CharList kwlist_str({ "paramName" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, ¶m)) { - PyErr_SetString(PyExc_TypeError, "Error.getParameter: need 'paramName(str)'"); + PyErr_SetString(PyExc_TypeError, "Error.getParameter: need 'paramName(str)'" ); return nullptr; } string in_param; @@ -930,7 +932,7 @@ static PyObject* C_MPEC_getParam(C_MpegEncoder* Self, PyObject* args, PyObject* PyObject* param = nullptr; cmpc::CharList kwlist_str({ "paramName" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, ¶m)) { PyErr_SetString(PyExc_TypeError, "Error.getParameter: need 'paramName(str)'"); return nullptr; @@ -953,7 +955,7 @@ static PyObject* C_MPEC_getParam(C_MpegEncoder* Self, PyObject* args, PyObject* return res; } -static PyObject* C_MPCT_getParam(C_MpegClient* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPCT_getParam(C_MpegClient* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (bool)C_MPCT_getParam method, the inputs are: * parameter [str/bytes->str]: The name of the parameter to be gotten, could be. * videoAddress: [str] The address of the current video. @@ -968,7 +970,7 @@ static PyObject* C_MPCT_getParam(C_MpegClient* Self, PyObject* args, PyObject* k PyObject* param = nullptr; cmpc::CharList kwlist_str({ "paramName" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, ¶m)) { PyErr_SetString(PyExc_TypeError, "Error.getParameter: need 'paramName(str)'"); return nullptr; @@ -1010,7 +1012,7 @@ static PyObject* C_MPSV_getParam(C_MpegServer* Self, PyObject* args, PyObject* k PyObject* param = nullptr; cmpc::CharList kwlist_str({ "paramName" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, ¶m)) { PyErr_SetString(PyExc_TypeError, "Error.getParameter: need 'paramName(str)'"); return nullptr; @@ -1033,7 +1035,7 @@ static PyObject* C_MPSV_getParam(C_MpegServer* Self, PyObject* args, PyObject* k return res; } -static PyObject* C_MPDC_setParam(C_MpegDecoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPDC_setParam(C_MpegDecoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (void)C_MPDC_setParam method, the inputs are: * widthDst/heightDst: [int] The width / height of the decoded frames. * nthread: [int] The number of decoder threads. @@ -1043,9 +1045,9 @@ static PyObject* C_MPDC_setParam(C_MpegDecoder* Self, PyObject* args, PyObject* int nthread = 0; cmpc::CharList kwlist_str({ "widthDst", "heightDst", "nthread" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iii", kwlist, &widthDst, &heightDst, &nthread)) { - PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'params'"); + PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'params'" ); return nullptr; } if (widthDst > 0) { @@ -1060,7 +1062,7 @@ static PyObject* C_MPDC_setParam(C_MpegDecoder* Self, PyObject* args, PyObject* Py_RETURN_NONE; } -static PyObject* C_MPEC_setParam(C_MpegEncoder* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPEC_setParam(C_MpegEncoder* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (bool)C_MPEC_setParam method, the inputs are: * decoder: [MpegDecoder / MpegClient]: The parameters to be configured. * configDict: [dict] A collection of key params. @@ -1086,10 +1088,10 @@ static PyObject* C_MPEC_setParam(C_MpegEncoder* Self, PyObject* args, PyObject* int heightSrc = 0; int GOPSize = 0; int MaxBframe = -1; - PyObject* frameRate = nullptr; + PyObject *frameRate = nullptr; cmpc::CharList kwlist_str({ "decoder", "configDict", "videoPath", "codecName", "nthread", "bitRate", "width", "height", "widthSrc", "heightSrc", "GOPSize", "maxBframe", "frameRate" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOOidiiiiiiO", kwlist, &decoder, &configDict, &videoPath, &codecName, &nthread, &bitRate, &width, &height, &widthSrc, &heightSrc, &GOPSize, &MaxBframe, &frameRate)) { PyErr_SetString(PyExc_TypeError, "Error.setParameter: need 'params'"); return nullptr; @@ -1100,8 +1102,7 @@ static PyObject* C_MPEC_setParam(C_MpegEncoder* Self, PyObject* args, PyObject* if (temp_str.compare("mpegCoder.MpegDecoder") == 0) { auto decoderPtr = reinterpret_cast(decoder); Self->_in_Handle->setParameter("decoder", decoderPtr->_in_Handle); - } - else if (temp_str.compare("mpegCoder.MpegClient") == 0) { + } else if (temp_str.compare("mpegCoder.MpegClient") == 0) { auto decoderPtr = reinterpret_cast(decoder); Self->_in_Handle->setParameter("client", decoderPtr->_in_Handle); } @@ -1136,25 +1137,25 @@ static PyObject* C_MPEC_setParam(C_MpegEncoder* Self, PyObject* args, PyObject* if (nthread > 0) { Self->_in_Handle->setParameter("nthread", &nthread); } - if (bitRate > 0) { + if (bitRate>0) { Self->_in_Handle->setParameter("bitRate", &bitRate); } - if (width > 0) { + if (width>0) { Self->_in_Handle->setParameter("width", &width); } - if (height > 0) { + if (height>0) { Self->_in_Handle->setParameter("height", &height); } - if (widthSrc > 0) { + if (widthSrc>0) { Self->_in_Handle->setParameter("widthSrc", &widthSrc); } - if (heightSrc > 0) { + if (heightSrc>0) { Self->_in_Handle->setParameter("heightSrc", &heightSrc); } - if (GOPSize > 0) { + if (GOPSize>0) { Self->_in_Handle->setParameter("GOPSize", &GOPSize); } - if (MaxBframe >= 0) { + if (MaxBframe>=0) { Self->_in_Handle->setParameter("maxBframe", &MaxBframe); } if (frameRate) { @@ -1169,7 +1170,7 @@ static PyObject* C_MPEC_setParam(C_MpegEncoder* Self, PyObject* args, PyObject* Py_RETURN_NONE; } -static PyObject* C_MPCT_setParam(C_MpegClient* Self, PyObject* args, PyObject* kwargs) { +static PyObject* C_MPCT_setParam(C_MpegClient* Self, PyObject *args, PyObject *kwargs) { /* Wrapped (void)C_MPCT_setParam method, the inputs are: * widthDst/heightDst: [int] The width / height of the decoded frames. * cacheSize/readSize: [int] The size of the cache, and the reading size. @@ -1181,24 +1182,24 @@ static PyObject* C_MPCT_setParam(C_MpegClient* Self, PyObject* args, PyObject* k int nthread = 0; int64_t cacheSize = 0; int64_t readSize = 0; - PyObject* frameRate = nullptr; + PyObject *frameRate = nullptr; cmpc::CharList kwlist_str({ "widthDst", "heightDst", "cacheSize", "readSize", "dstFrameRate", "nthread" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iiLLOi", kwlist, &widthDst, &heightDst, &cacheSize, &readSize, &frameRate, &nthread)) { PyErr_SetString(PyExc_TypeError, "Error.FFmpegSetup: need 'params'"); return nullptr; } - if (widthDst > 0) { + if (widthDst>0) { Self->_in_Handle->setParameter("widthDst", &widthDst); } - if (heightDst > 0) { + if (heightDst>0) { Self->_in_Handle->setParameter("heightDst", &heightDst); } - if (cacheSize > 0) { + if (cacheSize>0) { Self->_in_Handle->setParameter("cacheSize", &cacheSize); } - if (readSize > 0) { + if (readSize>0) { Self->_in_Handle->setParameter("readSize", &readSize); } if (frameRate) { @@ -1246,7 +1247,7 @@ static PyObject* C_MPSV_setParam(C_MpegServer* Self, PyObject* args, PyObject* k PyObject* frameRate = nullptr; cmpc::CharList kwlist_str({ "decoder", "configDict", "videoAddress", "codecName", "nthread", "bitRate", "width", "height", "widthSrc", "heightSrc", "GOPSize", "maxBframe", "frameRate", "frameAhead" }); auto kwlist_ptr = kwlist_str.c_str(); - auto kwlist = (char**)(kwlist_ptr.get()); + auto kwlist = (char **)(kwlist_ptr.get()); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOOidiiiiiiOi", kwlist, &decoder, &configDict, &videoAddress, &codecName, &nthread, &bitRate, &width, &height, &widthSrc, &heightSrc, &GOPSize, &MaxBframe, &frameRate, &frameAhead)) { PyErr_SetString(PyExc_TypeError, "Error.setParameter: need 'params'"); return nullptr; diff --git a/MpegCoder/MpegStreamer.cpp b/MpegCoder/MpegStreamer.cpp index 5be484e..deabb5c 100644 --- a/MpegCoder/MpegStreamer.cpp +++ b/MpegCoder/MpegStreamer.cpp @@ -1,12 +1,11 @@ -#include "stdafx.h" - -#define NO_IMPORT_ARRAY +#define NO_IMPORT_ARRAY #define PY_ARRAY_UNIQUE_SYMBOL MPEGARRAY_API +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include #include "MpegCoder.h" #include "MpegStreamer.h" -cmpc::CMpegClient::CMpegClient(void) : +cmpc::CMpegClient::CMpegClient(void): videoPath(), width(0), height(0), widthDst(0), heightDst(0), PPixelFormat(AVPixelFormat::AV_PIX_FMT_NONE), PFormatCtx(nullptr), PCodecCtx(nullptr), PVideoStream(nullptr), frame(nullptr), PVideoStreamIDX(0), PVideoFrameCount(0), @@ -17,7 +16,7 @@ cmpc::CMpegClient::CMpegClient(void) : cmpc::CMpegClient::~CMpegClient(void) { clear(); } -cmpc::CMpegClient::CMpegClient(CMpegClient&& ref) noexcept : +cmpc::CMpegClient::CMpegClient(CMpegClient &&ref) noexcept: videoPath(std::move(ref.videoPath)), width(ref.width), height(ref.height), widthDst(ref.widthDst), heightDst(ref.heightDst), PPixelFormat(ref.PPixelFormat), PFormatCtx(ref.PFormatCtx), PCodecCtx(ref.PCodecCtx), @@ -34,7 +33,7 @@ cmpc::CMpegClient::CMpegClient(CMpegClient&& ref) noexcept : ref.frame = nullptr; ref.PswsCtx = nullptr; } -cmpc::CMpegClient& cmpc::CMpegClient::operator=(CMpegClient&& ref) noexcept { +cmpc::CMpegClient& cmpc::CMpegClient::operator=(CMpegClient &&ref) noexcept { if (this != &ref) { videoPath = std::move(ref.videoPath); width = ref.width; @@ -134,8 +133,8 @@ void cmpc::CMpegClient::clear(void) { refcount = 1; } -int cmpc::CMpegClient::_open_codec_context(int& stream_idx, AVCodecContext*& dec_ctx, \ - AVFormatContext* PFormatCtx, enum cmpc::AVMediaType type) { // Search the correct decoder, and make the configurations. +int cmpc::CMpegClient::_open_codec_context(int &stream_idx, AVCodecContext *&dec_ctx, \ + AVFormatContext *PFormatCtx, enum cmpc::AVMediaType type) { // Search the correct decoder, and make the configurations. int ret; //search video stream @@ -300,7 +299,7 @@ cmpc::AVRational cmpc::CMpegClient::_setAVRational(int num, int den) { return res; } -int cmpc::CMpegClient::__save_frame(AVFrame*& frame, AVPacket*& pkt, bool& got_frame, int cached) { +int cmpc::CMpegClient::__save_frame(AVFrame *&frame, AVPacket *&pkt, bool &got_frame, int cached) { int ret = 0; int decoded = pkt->size; @@ -441,7 +440,7 @@ void cmpc::CMpegClient::__client_holder() { read_check.unlock(); } -int cmpc::CMpegClient::__avcodec_decode_video2(AVCodecContext* avctx, AVFrame* frame, bool& got_frame, AVPacket* pkt) { +int cmpc::CMpegClient::__avcodec_decode_video2(AVCodecContext *avctx, AVFrame *frame, bool &got_frame, AVPacket *pkt) { int ret; got_frame = false; @@ -472,7 +471,7 @@ PyObject* cmpc::CMpegClient::ExtractFrame() { } PyObject* cmpc::CMpegClient::ExtractFrame(int64_t readsize) { - if (readsize == 0 || readsize > cache_size) { + if (readsize==0 || readsize > cache_size) { cerr << "Read size of frames is out of range." << endl; return nullptr; } @@ -488,25 +487,25 @@ PyObject* cmpc::CMpegClient::ExtractFrame(int64_t readsize) { return res; } -void cmpc::CMpegClient::setParameter(string keyword, void* ptr) { +void cmpc::CMpegClient::setParameter(string keyword, void *ptr) { if (keyword.compare("widthDst") == 0) { - auto ref = reinterpret_cast(ptr); + auto ref = reinterpret_cast(ptr); widthDst = *ref; } else if (keyword.compare("heightDst") == 0) { - auto ref = reinterpret_cast(ptr); + auto ref = reinterpret_cast(ptr); heightDst = *ref; } else if (keyword.compare("cacheSize") == 0) { - auto ref = reinterpret_cast(ptr); + auto ref = reinterpret_cast(ptr); cache_size = *ref; } else if (keyword.compare("readSize") == 0) { - auto ref = reinterpret_cast(ptr); + auto ref = reinterpret_cast(ptr); read_size = *ref; } else if (keyword.compare("dstFrameRate") == 0) { - PyObject* ref = reinterpret_cast(ptr); + PyObject *ref = reinterpret_cast(ptr); auto refObj = PyTuple_GetItem(ref, 0); int num = static_cast(PyLong_AsLong(refObj)); refObj = PyTuple_GetItem(ref, 1); @@ -522,7 +521,7 @@ void cmpc::CMpegClient::setParameter(string keyword, void* ptr) { } } -PyObject* cmpc::CMpegClient::getParameter(string keyword) { +PyObject * cmpc::CMpegClient::getParameter(string keyword) { if (keyword.compare("videoAddress") == 0) { return PyUnicode_DecodeFSDefaultAndSize(videoPath.c_str(), static_cast(videoPath.size())); } @@ -666,7 +665,7 @@ void cmpc::CMpegClient::terminate() { av_frame_free(&frame); } } -ostream& cmpc::operator<<(ostream& out, cmpc::CMpegClient& self_class) { +ostream & cmpc::operator<<(ostream & out, cmpc::CMpegClient & self_class) { double dstFrameRate; out << std::setw(1) << "/"; out << std::setfill('*') << std::setw(44) << "" << std::setfill(' ') << endl; @@ -722,7 +721,7 @@ ostream& cmpc::operator<<(ostream& out, cmpc::CMpegClient& self_class) { return out; } -cmpc::BufferList::BufferList(void) : +cmpc::BufferList::BufferList(void): _Buffer_pos(0), _Buffer_rpos(-1), _Buffer_size(0), __Read_size(0), next_pts(0), interval_pts(0), dst_width(0), dst_height(0), src_width(0), src_height(0), _Buffer_capacity(0), @@ -743,7 +742,7 @@ cmpc::BufferList::~BufferList(void) { av_frame_free(&frameRGB); } } -cmpc::BufferList::BufferList(const BufferList& ref) : +cmpc::BufferList::BufferList(const BufferList &ref): _Buffer_pos(ref._Buffer_pos), _Buffer_rpos(ref._Buffer_rpos), _Buffer_size(ref._Buffer_size), __Read_size(ref.__Read_size), next_pts(ref.next_pts), interval_pts(ref.interval_pts), dst_width(ref.dst_width), dst_height(ref.dst_height), @@ -753,18 +752,18 @@ cmpc::BufferList::BufferList(const BufferList& ref) : cerr << "Could Allocate Temp Frame (RGB)" << endl; return; } - _Buffer_List = new uint8_t * [_Buffer_size]; + _Buffer_List = new uint8_t*[_Buffer_size]; memset(_Buffer_List, 0, _Buffer_size * sizeof(uint8_t*)); if (_Buffer_capacity > 0) { for (auto i = 0; i < _Buffer_size; i++) { if (ref._Buffer_List[i] != nullptr) { - _Buffer_List[i] = (uint8_t*)av_malloc(_Buffer_capacity * sizeof(uint8_t)); + _Buffer_List[i] = (uint8_t *)av_malloc(_Buffer_capacity * sizeof(uint8_t)); memcpy(_Buffer_List[i], ref._Buffer_List[i], _Buffer_capacity * sizeof(uint8_t)); } } } } -cmpc::BufferList& cmpc::BufferList::operator=(const BufferList& ref) { +cmpc::BufferList& cmpc::BufferList::operator=(const BufferList &ref) { if (this != &ref) { _Buffer_pos = ref._Buffer_pos; _Buffer_rpos = ref._Buffer_rpos; @@ -781,12 +780,12 @@ cmpc::BufferList& cmpc::BufferList::operator=(const BufferList& ref) { cerr << "Could Allocate Temp Frame (RGB)" << endl; return *this; } - _Buffer_List = new uint8_t * [_Buffer_size]; + _Buffer_List = new uint8_t*[_Buffer_size]; memset(_Buffer_List, 0, _Buffer_size * sizeof(uint8_t*)); if (_Buffer_capacity > 0) { for (auto i = 0; i < _Buffer_size; i++) { if (ref._Buffer_List[i] != nullptr) { - _Buffer_List[i] = (uint8_t*)av_malloc(_Buffer_capacity * sizeof(uint8_t)); + _Buffer_List[i] = (uint8_t *)av_malloc(_Buffer_capacity * sizeof(uint8_t)); memcpy(_Buffer_List[i], ref._Buffer_List[i], _Buffer_capacity * sizeof(uint8_t)); } } @@ -794,7 +793,7 @@ cmpc::BufferList& cmpc::BufferList::operator=(const BufferList& ref) { } return *this; } -cmpc::BufferList::BufferList(BufferList&& ref) noexcept : +cmpc::BufferList::BufferList(BufferList &&ref) noexcept: _Buffer_pos(ref._Buffer_pos), _Buffer_rpos(ref._Buffer_rpos), _Buffer_size(ref._Buffer_size), __Read_size(ref.__Read_size), next_pts(ref.next_pts), interval_pts(ref.interval_pts), dst_width(ref.dst_width), dst_height(ref.dst_height), @@ -803,7 +802,7 @@ cmpc::BufferList::BufferList(BufferList&& ref) noexcept : ref._Buffer_List = nullptr; ref.frameRGB = nullptr; } -cmpc::BufferList& cmpc::BufferList::operator=(BufferList&& ref) noexcept { +cmpc::BufferList& cmpc::BufferList::operator=(BufferList &&ref) noexcept { if (this != &ref) { _Buffer_pos = ref._Buffer_pos; _Buffer_rpos = ref._Buffer_rpos; @@ -880,12 +879,12 @@ bool cmpc::BufferList::reset_memory() { } } if (!_Buffer_List) { - _Buffer_List = new uint8_t * [_Buffer_size]; + _Buffer_List = new uint8_t*[_Buffer_size]; memset(_Buffer_List, 0, _Buffer_size * sizeof(uint8_t*)); } for (auto i = 0; i < _Buffer_size; i++) { if (!_Buffer_List[i]) { - _Buffer_List[i] = (uint8_t*)av_malloc(_Buffer_capacity * sizeof(uint8_t)); + _Buffer_List[i] = (uint8_t *)av_malloc(_Buffer_capacity * sizeof(uint8_t)); } memset(_Buffer_List[i], 0, _Buffer_capacity * sizeof(uint8_t)); } @@ -899,7 +898,7 @@ void cmpc::BufferList::freeze_write(int64_t read_size) { _Buffer_rpos = read_pos; __Read_size = read_size; } -bool cmpc::BufferList::write(SwsContext* PswsCtx, AVFrame* frame) { +bool cmpc::BufferList::write(SwsContext *PswsCtx, AVFrame *frame) { if (frame->pts < next_pts) { if (frame->pts > (next_pts - 2 * interval_pts)) { return false; @@ -924,7 +923,7 @@ bool cmpc::BufferList::write(SwsContext* PswsCtx, AVFrame* frame) { _Buffer_pos -= _Buffer_size; return true; } -PyObject* cmpc::BufferList::read() { +PyObject * cmpc::BufferList::read() { if (_Buffer_rpos < 0) { return nullptr; } @@ -934,9 +933,9 @@ PyObject* cmpc::BufferList::read() { auto p = newdata; for (auto i = _Buffer_rpos; i != _Buffer_rend; i = (i + 1) % _Buffer_size) { memcpy(p, _Buffer_List[i], _Buffer_capacity * sizeof(uint8_t)); - p += _Buffer_capacity; + p += _Buffer_capacity; } - PyObject* PyFrame = PyArray_SimpleNewFromData(4, dims, NPY_UINT8, reinterpret_cast(newdata)); + PyObject *PyFrame = PyArray_SimpleNewFromData(4, dims, NPY_UINT8, reinterpret_cast(newdata)); PyArray_ENABLEFLAGS((PyArrayObject*)PyFrame, NPY_ARRAY_OWNDATA); _Buffer_rpos = -1; __Read_size = 0; @@ -1020,7 +1019,7 @@ cmpc::CMpegServer::~CMpegServer(void) { } -cmpc::CMpegServer::CMpegServer(const CMpegServer& ref) : +cmpc::CMpegServer::CMpegServer(const CMpegServer& ref): videoPath(ref.videoPath), __formatName(ref.__formatName), codecName(ref.codecName), bitRate(ref.bitRate), __pts_ahead(ref.__pts_ahead), __start_time(0), __cur_time(0), width(ref.width), height(ref.height), widthSrc(ref.widthSrc), heightSrc(ref.heightSrc), @@ -1076,7 +1075,7 @@ cmpc::CMpegServer::CMpegServer(CMpegServer&& ref) noexcept : timeBase(ref.timeBase), frameRate(ref.frameRate), time_base_q(ref.time_base_q), GOPSize(ref.GOPSize), MaxBFrame(ref.MaxBFrame), PStreamContex(std::move(ref.PStreamContex)), PFormatCtx(ref.PFormatCtx), Ppacket(ref.Ppacket), PswsCtx(ref.PswsCtx), - __frameRGB(ref.__frameRGB), RGBbuffer(ref.RGBbuffer), + __frameRGB(ref.__frameRGB), RGBbuffer(ref.RGBbuffer), __have_video(ref.__have_video), __enable_header(ref.__enable_header), nthread(ref.nthread) { ref.PFormatCtx = nullptr; ref.PStreamContex = { 0 }; @@ -1165,7 +1164,7 @@ int64_t cmpc::CMpegServer::__TimeToPts(double seekTime) const { } bool cmpc::CMpegServer::__setup_check() const { - if ((!videoPath.empty()) && (!__formatName.empty()) && frameRate.den > 0 && frameRate.num > 0) { + if ((! videoPath.empty()) && (! __formatName.empty()) && frameRate.den > 0 && frameRate.num > 0) { return true; } else { @@ -1188,8 +1187,8 @@ int cmpc::CMpegServer::__write_frame() { Ppacket->stream_index = PStreamContex.st->index; // Update the time cursor according to the packet index. - AVRational& time_base = PFormatCtx->streams[Ppacket->stream_index]->time_base; - + AVRational &time_base = PFormatCtx->streams[Ppacket->stream_index]->time_base; + auto cur_time = av_rescale_q(Ppacket->pts, time_base, time_base_q); if (cur_time > __cur_time) { __cur_time = cur_time; @@ -2009,7 +2008,7 @@ bool cmpc::CMpegServer::FFmpegSetup() { if (__formatName.compare("rtsp") == 0) { format_name.assign("rtsp"); } - else if (__formatName.compare("rtmp") == 0) { + else if(__formatName.compare("rtmp") == 0) { format_name.assign("flv"); } else if (__formatName.compare("http") == 0) { diff --git a/MpegCoder/MpegStreamer.h b/MpegCoder/MpegStreamer.h index f809171..b9a8a32 100644 --- a/MpegCoder/MpegStreamer.h +++ b/MpegCoder/MpegStreamer.h @@ -20,18 +20,18 @@ namespace cmpc { public: BufferList(void); ~BufferList(void); - BufferList(const BufferList& ref); - BufferList& operator=(const BufferList& ref); - BufferList(BufferList&& ref) noexcept; - BufferList& operator=(BufferList&& ref) noexcept; + BufferList(const BufferList &ref); + BufferList& operator=(const BufferList &ref); + BufferList(BufferList &&ref) noexcept; + BufferList& operator=(BufferList &&ref) noexcept; void clear(void); const int64_t size() const; - void set(int64_t set_size, int width, int height, int widthDst = 0, int heightDst = 0); + void set(int64_t set_size, int width, int height, int widthDst=0, int heightDst=0); void set_timer(AVRational targetFrameRate, AVRational timeBase); bool reset_memory(); void freeze_write(int64_t read_size); - bool write(SwsContext* PswsCtx, AVFrame* frame); - PyObject* read(); + bool write(SwsContext *PswsCtx, AVFrame *frame); + PyObject *read(); private: int64_t _Buffer_pos; // Writring cursor of the source buffer,pointing to the index of the currently written frame. int64_t _Buffer_rpos; // Reading cursor of the source buffer,pointing to the index of the currently read frame. @@ -42,25 +42,25 @@ namespace cmpc { int dst_width, dst_height; int src_width, src_height; int _Buffer_capacity; - AVFrame* frameRGB; - uint8_t** _Buffer_List; // Source buffer, the size of this buffer is determined by the number of required frames. + AVFrame *frameRGB; + uint8_t **_Buffer_List; // Source buffer, the size of this buffer is determined by the number of required frames. }; class CMpegClient { public: CMpegClient(void); // Constructor. ~CMpegClient(void); // 3-5 law. Destructor. - CMpegClient(const CMpegClient& ref) = delete; // Delete the copy constructor. - CMpegClient& operator=(const CMpegClient& ref) = delete; // Delete the copy assignment operator. - CMpegClient(CMpegClient&& ref) noexcept; // Move constructor. - CMpegClient& operator=(CMpegClient&& ref) noexcept; // Move assignment operator. + CMpegClient(const CMpegClient &ref) = delete; // Delete the copy constructor. + CMpegClient& operator=(const CMpegClient &ref) = delete; // Delete the copy assignment operator. + CMpegClient(CMpegClient &&ref) noexcept; // Move constructor. + CMpegClient& operator=(CMpegClient &&ref) noexcept; // Move assignment operator. friend class CMpegEncoder; // Let the encoder be able to access the member of this class. friend class CMpegServer; // Let the server be able to access the member of this class. - friend ostream& operator<<(ostream& out, CMpegClient& self_class); // Show the results. + friend ostream & operator<<(ostream & out, CMpegClient & self_class); // Show the results. void clear(void); // Clear all configurations and resources. void meta_protected_clear(void); // Clear the resources, but the configurations are remained. void dumpFormat(); // Show the av_format results. - void setParameter(string keyword, void* ptr); // Set arguments. + void setParameter(string keyword, void *ptr); // Set arguments. PyObject* getParameter(string keyword); // Get the current arguments. PyObject* getParameter(); // Get all key arguments. void resetPath(string inVideoPath); // Reset the path (URL) of the online video stream. @@ -68,23 +68,23 @@ namespace cmpc { bool FFmpegSetup(string inVideoPath); // Configure the decoder with extra arguments. bool start(); // Start the listening to the online stream. void terminate(); // Terminate the listener. - PyObject* ExtractFrame(int64_t readsize); // Extract frames with the given number. - PyObject* ExtractFrame(); // Extract frames. The number is configured in the class properties. + PyObject * ExtractFrame(int64_t readsize); // Extract frames with the given number. + PyObject * ExtractFrame(); // Extract frames. The number is configured in the class properties. private: string videoPath; // The path (URL) of the online video stream. int width, height; // Width, height of the video. int widthDst, heightDst; // Target width, height of ExtractFrame(). enum AVPixelFormat PPixelFormat; // Enum object of the pixel format. - AVFormatContext* PFormatCtx; // Format context of the video. - AVCodecContext* PCodecCtx; // Codec context of the video. - AVStream* PVideoStream; // Video stream. + AVFormatContext *PFormatCtx; // Format context of the video. + AVCodecContext *PCodecCtx; // Codec context of the video. + AVStream *PVideoStream; // Video stream. - AVFrame* frame; + AVFrame *frame; int PVideoStreamIDX; // The index of the video stream. int PVideoFrameCount; // The counter of the decoded frames. BufferList buffer; // The buffer of the RGB formatted images. - struct SwsContext* PswsCtx; // The context of the scale transformator. + struct SwsContext *PswsCtx; // The context of the scale transformator. int64_t cache_size, read_size; AVRational frameRate; @@ -104,11 +104,11 @@ namespace cmpc { * differences of API usage between them. */ int refcount; // Reference count of the video frame. bool __setup_check() const; - int _open_codec_context(int& stream_idx, AVCodecContext*& dec_ctx, AVFormatContext* PFormatCtx, enum AVMediaType type); + int _open_codec_context(int &stream_idx, AVCodecContext *&dec_ctx, AVFormatContext *PFormatCtx, enum AVMediaType type); void __client_holder(); AVRational _setAVRational(int num, int den); - int __save_frame(AVFrame*& frame, AVPacket*& pkt, bool& got_frame, int cached); - int __avcodec_decode_video2(AVCodecContext* avctx, AVFrame* frame, bool& got_frame, AVPacket* pkt); + int __save_frame(AVFrame *&frame, AVPacket *&pkt, bool &got_frame, int cached); + int __avcodec_decode_video2(AVCodecContext *avctx, AVFrame *frame, bool &got_frame, AVPacket *pkt); }; class CMpegServer { diff --git a/MpegCoder/dllmain.cpp b/MpegCoder/dllmain.cpp index 0f676a8..adafbd8 100644 --- a/MpegCoder/dllmain.cpp +++ b/MpegCoder/dllmain.cpp @@ -1,5 +1,4 @@ // dllmain.cpp : The entry of the dll program. -#include "stdafx.h" #include "MpegPyd.h" /***************************************************************************** @@ -47,21 +46,3 @@ PyInit_mpegCoder(void) { // The external module name is: --CppClass PyModule_AddObject(pReturn, "MpegServer", (PyObject*)&C_MPSV_ClassInfo); return pReturn; } - -/* -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} -*/ diff --git a/MpegCoder/snprintf.cpp b/MpegCoder/snprintf.cpp deleted file mode 100644 index 8142cf8..0000000 --- a/MpegCoder/snprintf.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * C99-compatible snprintf() and vsnprintf() implementations - * Copyright (c) 2012 Ronald S. Bultje - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include "stdafx.h" - -extern "C" -{ - #include - #include - #include - #include -} - -#include "compat/va_copy.h" -#include "libavutil/error.h" -#include "compat/msvcrt/snprintf.h" - -#if defined(__MINGW32__) -#define EOVERFLOW EFBIG -#endif - -extern "C" -{ - int avpriv_snprintf(char *s, size_t n, const char *fmt, ...) { - va_list ap; - int ret; - - va_start(ap, fmt); - ret = avpriv_vsnprintf(s, n, fmt, ap); - va_end(ap); - - return ret; - } - - int avpriv_vsnprintf(char *s, size_t n, const char *fmt, va_list ap) { - int ret; - va_list ap_copy; - - if (n == 0) - return _vscprintf(fmt, ap); - else if (n > INT_MAX) - return AVERROR(EOVERFLOW); - - /* we use n - 1 here because if the buffer is not big enough, the MS - * runtime libraries don't add a terminating zero at the end. MSDN - * recommends to provide _snprintf/_vsnprintf() a buffer size that - * is one less than the actual buffer, and zero it before calling - * _snprintf/_vsnprintf() to workaround this problem. - * See http://msdn.microsoft.com/en-us/library/1kt27hek(v=vs.80).aspx */ - memset(s, 0, n); - va_copy(ap_copy, ap); - ret = _vsnprintf_s(s, n - 1, INT_MAX, fmt, ap_copy); - va_end(ap_copy); - if (ret == -1) - ret = _vscprintf(fmt, ap); - - return ret; - } -} \ No newline at end of file diff --git a/MpegCoder/stdafx.cpp b/MpegCoder/stdafx.cpp deleted file mode 100644 index fa90b1c..0000000 --- a/MpegCoder/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : 只包括标准包含文件的源文件 -// $safeprojectname$.pch 将作为预编译标头 -// stdafx.obj 将包含预编译类型信息 - -#include "stdafx.h" - -// TODO: 在 STDAFX.H 中引用任何所需的附加头文件, -//而不是在此文件中引用 diff --git a/MpegCoder/stdafx.h b/MpegCoder/stdafx.h deleted file mode 100644 index 4b4e4a8..0000000 --- a/MpegCoder/stdafx.h +++ /dev/null @@ -1,19 +0,0 @@ -// stdafx.h : 标准系统包含文件的包含文件, -// 或是经常使用但不常更改的 -// 特定于项目的包含文件 -// - -#pragma once - -#include "targetver.h" - -#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料 -// Numpy header: -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -// Windows header: -#define _CRT_SECURE_NO_WARNINGS -#include - - - -// TODO: 在此处引用程序需要的其他头文件 diff --git a/MpegCoder/targetver.h b/MpegCoder/targetver.h deleted file mode 100644 index 91042b9..0000000 --- a/MpegCoder/targetver.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。 - -// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将 -// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。 - -#include diff --git a/README.md b/README.md index 7d4b1a0..3366484 100644 --- a/README.md +++ b/README.md @@ -8,49 +8,87 @@ import mpegCoder | Branch | Description | | :-------------: | :-----------: | -| `master` :link: | The source project of `mpegCoder`, Windows version. | -| [`master-linux` :link:][git-linux] | The source project of `mpegCoder`, Linux version. | +| [`master` :link:][git-master] | The source project of `mpegCoder`, Windows version. | +| `master-linux` :link: | The source project of `mpegCoder`, Linux version. | | [`example-client-check` :link:][exp1] | A testing project of the online video stream demuxing. | | [`example-client-player` :link:][exp2] | A testing project of the simple online video stream player. | -## Source project of `mpegCoder` (Windows) +## Source project of `mpegCoder` (Linux) The following instructions are used for building the project on Windows with Visual Studio 2019. 1. Clone the `master` branch which only contains the codes of `mpegCoder`: ```bash - git clone --single-branch -b master https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python.git + git clone --single-branch -b master-linux https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python.git ``` -2. Download the FFMpeg dependencies, including `include` and `lib`. Users could download dependencies manually by checking [the release page :link:](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/releases/tag/deps-3.0.0). However, we recommend users to use the following script to get the dependencies quickly: +2. Install the pre-requisite packages. The following script could be used by ubuntu or debian. If users are using other Linux distribution, they should install `gcc` and `g++` by themselves. - ```bash - python webtools.py + ```shell + chmod +rwx ./apt-requirements.sh + ./apt-requirements.sh ``` - This script requires users to install `urllib3`. The `tqdm` is also recommended to be installed. + We strongly suggest that users should also install the python dependencies (optional): + + ```shell + python -m pip install -r requirements.txt + ``` + +3. Get the shared version of the Linux FFMpeg. We support three different approaches for this step: + * Build the shared libs of FFMpeg from the source codes by yourself. We provide [a compiling script :page_with_curl:](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/blob/deps/install-ffmpeg-4_4.sh) in the deps branch. You could download and build it by the following commands: + + ```shell + mkdir -p /apps + chmod +rwx /apps + curl -O https://raw.githubusercontent.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/deps/install-ffmpeg-5_0.sh + chmod +rwx install-ffmpeg-5_0.sh + ./install-ffmpeg-5_0.sh --all --nvcuda + ``` + + After running this script, the FFMpeg with most of the dependencies would be complied along with the shared libraries. Then you could replace the FFMpeg path in the `setup.py` by + + ```python + FFMPEG_DIR = '/apps/build/ffmpeg-5.0' + ``` -3. The following configurations should be set for `All` (both debug and release) and `x64`. Open the project by `MpegCoder.sln`. Then configure the following paths of the include directories and the library directories. In both configurations, the first item is required to be modified according to your python path, the second item is required to be modified according to your numpy path. + * Download the pre-built dependencies. These dependencies are built by myself. You could download the archive [here :package:](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/releases/download/deps-3.2.0/dep-linux-ffmpeg_5_0.tar.xz). The files need to be extracted to `./dependencies`: - | Path | Screenshot | - | :----- | :----------: | - | `includes` | ![Configure includes](./display/config-include.png) | - | `libs` | ![Configure libs](./display/config-include.png) | + ```shell + cd FFmpeg-Encoder-Decoder-for-Python + mkdir -p dependencies + wget -O- https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/releases/download/deps-3.2.0/dep-linux-ffmpeg_5_0.tar.xz | tar xJ -C "./dependencies" + ``` -4. Modify the linker configs. We only need to change the item `python3x.lib` according to the python version you have. - ![Configure linker](./display/config-linker.png) + * The dependencies could be also downloaded by the automatic script, you just need to run -5. Run the `Release`, `x64` build. The built file should be saved as `x64\Release\mpegCoder.pyd`. + ```shell + python webtools.py + ``` + + This script requires users to install `urllib3`. The `tqdm` is also recommended to be installed. + +4. Build `mpegCoder` by running the following script. The built file would be stored in `./build`. If you has not fetched the dependencies in the step 2, running the `setup.py` may trigger an event for fetching the online dependencies. + + ```shell + python setup.py build + ``` + +5. Rename the built module as `mpegCoder.so`, then you could import it in the same directory. If you have built FFMpeg by our script, you do not need any other dependencies when importing the libs. However, if not, you may need to download [the lib dependencies :package:](https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/releases/download/deps-3.2.0/so-linux-ffmpeg_5_0.tar.xz) and add the `lib` folder to your `LD_LIBRARY_PATH`: + + ```shell + mkdir -p /apps/ffmpeg-5.0 + cd /apps/ffmpeg-5.0 + wget -O- https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/releases/download/deps-3.2.0/so-linux-ffmpeg_5_0.tar.xz | tar xJ -C "." + echo "export LD_LIBRARY_PATH=/apps/ffmpeg-5.0/lib:\$LD_LIBRARY_PATH" >> ~/.bashrc + export LD_LIBRARY_PATH=/apps/ffmpeg-5.0/lib:$LD_LIBRARY_PATH + ``` -6. The `mpegCoder.pyd` should be used together with the FFMpeg shared libraries, including: +6. Running `mpegCoder` requires `GLIBC>=2.29`. This requirement is not satisfied in some cases. However, if you have built FFMpeg by our script, the requirement would be fulfilled (i.e. you could skip this step). If users are using our pre-built dependencies, users may need to solve this problem by ```shell - avcodec-59.dll - avformat-59.dll - avutil-57.dll - swresample-4.dll - swscale-6.dll + ln -sf /apps/ffmpeg-5.0/lib-fix/libm-2.31.so /lib/x86_64-linux-gnu/libm.so.6 ``` ## Update reports @@ -69,6 +107,6 @@ Current FFMpeg version is `5.0`. | `libswresample` | `4.3.100.0` | | `libswscale` | `6.4.100.0` | -[git-linux]:https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/tree/master-linux "master (Linux)" +[git-master]:https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python "master (windows)" [exp1]:https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/tree/example-client-check "check the client" [exp2]:https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/tree/example-client-player "client with player" diff --git a/apt-requirements.sh b/apt-requirements.sh new file mode 100755 index 0000000..16f0e71 --- /dev/null +++ b/apt-requirements.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Make bashline configurations. +set -e +RESET='\033[0m' +COLOR='\033[1;32m' +COLOR_ERR='\033[1;31m' + +function msg { + echo -e "${COLOR}$(date): $1${RESET}" +} + +function msg_err { + echo -e "${COLOR}$(date): $1${RESET}" +} + +function fail { + msg_err "Error : $?" + exit 1 +} + +function mcd { + mkdir -p "$1" || fail + cd "$1" || fail +} + +msg "Install gcc, g++ and other dependencies." +apt-get update -qq || fail +apt-get -y install gcc g++ wget tar xz-utils || fail diff --git a/display/config-include.png b/display/config-include.png deleted file mode 100644 index dccb3ad..0000000 Binary files a/display/config-include.png and /dev/null differ diff --git a/display/config-libs.png b/display/config-libs.png deleted file mode 100644 index 546530d..0000000 Binary files a/display/config-libs.png and /dev/null differ diff --git a/display/config-linker.png b/display/config-linker.png deleted file mode 100644 index 47426dc..0000000 Binary files a/display/config-linker.png and /dev/null differ diff --git a/find_libpython/__init__.py b/find_libpython/__init__.py new file mode 100644 index 0000000..5143094 --- /dev/null +++ b/find_libpython/__init__.py @@ -0,0 +1,360 @@ +""" +Locate libpython associated with this Python executable. +""" + +# License +# +# Copyright 2018, Takafumi Arakaki +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +from __future__ import print_function, absolute_import + +from logging import getLogger +import ctypes.util +import functools +import os +import sys +import sysconfig + +from find_libpython._version import version as __version__ # noqa: F401 + +logger = getLogger("find_libpython") + +is_windows = os.name == "nt" +is_apple = sys.platform == "darwin" +is_msys = sysconfig.get_platform().startswith("msys") +is_mingw = sysconfig.get_platform().startswith("mingw") + +SHLIB_SUFFIX = sysconfig.get_config_var("SHLIB_SUFFIX") +if SHLIB_SUFFIX is None: + if is_windows: + SHLIB_SUFFIX = ".dll" + else: + SHLIB_SUFFIX = ".so" +if is_apple: + # sysconfig.get_config_var("SHLIB_SUFFIX") can be ".so" in macOS. + # Let's not use the value from sysconfig. + SHLIB_SUFFIX = ".dylib" + + +def library_name(name, suffix=SHLIB_SUFFIX, is_windows=is_windows): + """ + Convert a file basename `name` to a library name (no "lib" and ".so" etc.) + + >>> library_name("libpython3.7m.so") # doctest: +SKIP + 'python3.7m' + >>> library_name("libpython3.7m.so", suffix=".so", is_windows=False) + 'python3.7m' + >>> library_name("libpython3.7m.dylib", suffix=".dylib", is_windows=False) + 'python3.7m' + >>> library_name("python37.dll", suffix=".dll", is_windows=True) + 'python37' + """ + if not is_windows and name.startswith("lib"): + name = name[len("lib") :] + if suffix and name.endswith(suffix): + name = name[: -len(suffix)] + return name + + +def append_truthy(list, item): + if item: + list.append(item) + + +def uniquifying(items): + """ + Yield items while excluding the duplicates and preserving the order. + + >>> list(uniquifying([1, 2, 1, 2, 3])) + [1, 2, 3] + """ + seen = set() + for x in items: + if x not in seen: + yield x + seen.add(x) + + +def uniquified(func): + """ Wrap iterator returned from `func` by `uniquifying`. """ + + @functools.wraps(func) + def wrapper(*args, **kwds): + return uniquifying(func(*args, **kwds)) + + return wrapper + + +@uniquified +def candidate_names(suffix=SHLIB_SUFFIX): + """ + Iterate over candidate file names of libpython. + + Yields + ------ + name : str + Candidate name libpython. + """ + LDLIBRARY = sysconfig.get_config_var("LDLIBRARY") + if LDLIBRARY and os.path.splitext(LDLIBRARY)[1] == suffix: + yield LDLIBRARY + + LIBRARY = sysconfig.get_config_var("LIBRARY") + if LIBRARY and os.path.splitext(LIBRARY)[1] == suffix: + yield LIBRARY + + DLLLIBRARY = sysconfig.get_config_var("DLLLIBRARY") + if DLLLIBRARY: + yield DLLLIBRARY + + if is_mingw: + dlprefix = "lib" + elif is_windows or is_msys: + dlprefix = "" + else: + dlprefix = "lib" + + sysdata = dict( + v=sys.version_info, + # VERSION is X.Y in Linux/macOS and XY in Windows: + VERSION=( + sysconfig.get_config_var("VERSION") + or "{v.major}.{v.minor}".format(v=sys.version_info) + ), + ABIFLAGS=( + sysconfig.get_config_var("ABIFLAGS") + or sysconfig.get_config_var("abiflags") + or "" + ), + ) + + for stem in [ + "python{VERSION}{ABIFLAGS}".format(**sysdata), + "python{VERSION}".format(**sysdata), + "python{v.major}".format(**sysdata), + "python", + ]: + yield dlprefix + stem + suffix + + +@uniquified +def candidate_paths(suffix=SHLIB_SUFFIX): + """ + Iterate over candidate paths of libpython. + + Yields + ------ + path : str or None + Candidate path to libpython. The path may not be a fullpath + and may not exist. + """ + + # List candidates for directories in which libpython may exist + lib_dirs = [] + append_truthy(lib_dirs, sysconfig.get_config_var("LIBPL")) + append_truthy(lib_dirs, sysconfig.get_config_var("srcdir")) + append_truthy(lib_dirs, sysconfig.get_config_var("LIBDIR")) + + # LIBPL seems to be the right config_var to use. It is the one + # used in python-config when shared library is not enabled: + # https://github.com/python/cpython/blob/v3.7.0/Misc/python-config.in#L55-L57 + # + # But we try other places just in case. + + if is_windows or is_msys or is_mingw: + lib_dirs.append(os.path.join(os.path.dirname(sys.executable))) + else: + lib_dirs.append( + os.path.join(os.path.dirname(os.path.dirname(sys.executable)), "lib") + ) + + # For macOS: + append_truthy(lib_dirs, sysconfig.get_config_var("PYTHONFRAMEWORKPREFIX")) + + lib_dirs.append(sys.exec_prefix) + lib_dirs.append(os.path.join(sys.exec_prefix, "lib")) + + lib_basenames = list(candidate_names(suffix=suffix)) + + for directory in lib_dirs: + for basename in lib_basenames: + yield os.path.join(directory, basename) + + # In macOS and Windows, ctypes.util.find_library returns a full path: + for basename in lib_basenames: + yield ctypes.util.find_library(library_name(basename)) + + +# Possibly useful links: +# * https://packages.ubuntu.com/bionic/amd64/libpython3.6/filelist +# * https://github.com/Valloric/ycmd/issues/518 +# * https://github.com/Valloric/ycmd/pull/519 + + +def normalize_path(path, suffix=SHLIB_SUFFIX, is_apple=is_apple): + """ + Normalize shared library `path` to a real path. + + If `path` is not a full path, `None` is returned. If `path` does + not exists, append `SHLIB_SUFFIX` and check if it exists. + Finally, the path is canonicalized by following the symlinks. + + Parameters + ---------- + path : str ot None + A candidate path to a shared library. + """ + if not path: + return None + if not os.path.isabs(path): + return None + if os.path.exists(path): + return os.path.realpath(path) + if os.path.exists(path + suffix): + return os.path.realpath(path + suffix) + if is_apple: + return normalize_path(_remove_suffix_apple(path), suffix=".so", is_apple=False) + return None + + +def _remove_suffix_apple(path): + """ + Strip off .so or .dylib. + + >>> _remove_suffix_apple("libpython.so") + 'libpython' + >>> _remove_suffix_apple("libpython.dylib") + 'libpython' + >>> _remove_suffix_apple("libpython3.7") + 'libpython3.7' + """ + if path.endswith(".dylib"): + return path[: -len(".dylib")] + if path.endswith(".so"): + return path[: -len(".so")] + return path + + +@uniquified +def finding_libpython(): + """ + Iterate over existing libpython paths. + + The first item is likely to be the best one. + + Yields + ------ + path : str + Existing path to a libpython. + """ + logger.debug("is_windows = %s", is_windows) + logger.debug("is_apple = %s", is_apple) + logger.debug("is_mingw = %s", is_mingw) + logger.debug("is_msys = %s", is_msys) + for path in candidate_paths(): + logger.debug("Candidate: %s", path) + normalized = normalize_path(path) + if normalized: + logger.debug("Found: %s", normalized) + yield normalized + else: + logger.debug("Not found.") + + +def find_libpython(): + """ + Return a path (`str`) to libpython or `None` if not found. + + Parameters + ---------- + path : str or None + Existing path to the (supposedly) correct libpython. + """ + for path in finding_libpython(): + return os.path.realpath(path) + + +def print_all(items): + for x in items: + print(x) + + +def cli_find_libpython(cli_op, verbose): + import logging + + # Importing `logging` module here so that using `logging.debug` + # instead of `logger.debug` outside of this function becomes an + # error. + + if verbose: + logging.basicConfig(format="%(levelname)s %(message)s", level=logging.DEBUG) + + if cli_op == "list-all": + print_all(finding_libpython()) + elif cli_op == "candidate-names": + print_all(candidate_names()) + elif cli_op == "candidate-paths": + print_all(p for p in candidate_paths() if p and os.path.isabs(p)) + else: + path = find_libpython() + if path is None: + return 1 + print(path, end="") + + +def main(args=None): + import argparse + + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--verbose", "-v", action="store_true", help="Print debugging information." + ) + + parser.add_argument( + "--version", action="version", version="find_libpython {}".format(__version__) + ) + + group = parser.add_mutually_exclusive_group() + group.add_argument( + "--list-all", + action="store_const", + dest="cli_op", + const="list-all", + help="Print list of all paths found.", + ) + group.add_argument( + "--candidate-names", + action="store_const", + dest="cli_op", + const="candidate-names", + help="Print list of candidate names of libpython.", + ) + group.add_argument( + "--candidate-paths", + action="store_const", + dest="cli_op", + const="candidate-paths", + help="Print list of candidate paths of libpython.", + ) + + ns = parser.parse_args(args) + parser.exit(cli_find_libpython(**vars(ns))) diff --git a/find_libpython/__main__.py b/find_libpython/__main__.py new file mode 100644 index 0000000..bd24103 --- /dev/null +++ b/find_libpython/__main__.py @@ -0,0 +1,5 @@ +from find_libpython import main + + +if __name__ == "__main__": + main() diff --git a/find_libpython/_version.py b/find_libpython/_version.py new file mode 100644 index 0000000..9ade197 --- /dev/null +++ b/find_libpython/_version.py @@ -0,0 +1,5 @@ +# coding: utf-8 +# file generated by setuptools_scm +# don't change, don't track in version control +version = '0.2.0' +version_tuple = (0, 2, 0) diff --git a/mpegCoder-linux.code-workspace b/mpegCoder-linux.code-workspace new file mode 100644 index 0000000..3e7001e --- /dev/null +++ b/mpegCoder-linux.code-workspace @@ -0,0 +1,19 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "python.linting.flake8Args": [ + "--ignore", "E501" + ], + "python.linting.pycodestyleArgs": [ + "--ignore", "E501" + ], + "python.linting.pylintArgs": [ + "-d", "C0301" + ], + "cSpell.enabled": true + } +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c4a2f8c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +urllib3>=1.26.6 +tqdm>=4.50.0 +setuptools>=50.3.2 +numpy>=1.19.5 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..bcaa55d --- /dev/null +++ b/setup.py @@ -0,0 +1,103 @@ +#!python +# -*- coding: UTF-8 -*- +''' +################################################################ +# Compiliation file for mpegCoder +# @ FFMpeg encoder and decoder. +# Yuchen Jin @ cainmagi@gmail.com +# Requirements: (Pay attention to version) +# python 3.3+ +# urllib3 1.26.2+ +# This script is used for compiling the core module of the +# mpegCoder. +################################################################ +''' + +import os +import re +import sysconfig +try: + from setuptools import setup, Extension +except ImportError: + from distutils.core import setup, Extension + +import find_libpython +import numpy as np + +try: + import webtools + HAS_WEBTOOLS=True +except ImportError: + HAS_WEBTOOLS=False + +BASE_SRC_DIR = 'MpegCoder' +FFMPEG_DIR = './dependencies' +PYTHON_INC_DIR = sysconfig.get_path('include') # /usr/include/python3.x +NUMPY_DIR = os.path.join(os.path.dirname(np.__file__), 'core') # '/usr/local/lib/python3.x/dist-packages/numpy/core' + +PYTHON_LIB_PATH = find_libpython.find_libpython() +PYTHON_LIB_DIR = os.path.dirname(PYTHON_LIB_PATH) # '/usr/lib/python3.x/config-3.xm-x86_64-linux-gnu' +PYTHON_LIB_NAME = re.search(R'(?:lib|)(python3\.(?:.+?))\..*?', os.path.basename(PYTHON_LIB_PATH)).groups(1)[0] +TARGET='mpegCoder' + +with open('README.md', 'r') as fh: + LONG_DESCRIPTION = fh.read() + +if (not os.path.isdir(os.path.join(FFMPEG_DIR, 'include'))) or (not os.path.isdir(os.path.join(FFMPEG_DIR, 'lib'))): + if HAS_WEBTOOLS: + print('The FFMpeg dependencies are not found. Fetch the files online...') + webtools.download_tarball('cainmagi', 'FFmpeg-Encoder-Decoder-for-Python', 'deps-3.2.0', 'dep-linux-ffmpeg_5_0.tar.xz', path=os.path.join('.', 'dependencies'), mode='auto', verbose=True, token='') + else: + raise FileNotFoundError('The required dependencies ("include" and "lib" directories) are not found in FFMPEG_DIR path ({0})'.format(FFMPEG_DIR)) + +module_mpegCoder = Extension( + name = TARGET, + language = 'c++', + define_macros = [('MAJOR_VERSION', '3'), + ('MINOR_VERSION', '2'), + ('BUILD_VERSION', '0')], + extra_compile_args = ['-std=c++11','-pthread'], + include_dirs = [PYTHON_INC_DIR, np.get_include(), '{0}/include'.format(FFMPEG_DIR), BASE_SRC_DIR], + #libraries = [PYTHON_LIB_NAME, 'avcodec', 'avdevice', 'avfilter', 'avformat', 'avutil', 'postproc', 'swresample', 'swscale', 'npymath'], + libraries = [PYTHON_LIB_NAME, 'avcodec', 'avformat', 'avutil', 'swresample', 'swscale', 'npymath'], + library_dirs = [PYTHON_LIB_DIR, '{0}/lib'.format(NUMPY_DIR), '{0}/lib'.format(FFMPEG_DIR)], + sources = [ + '{0}/MpegBase.cpp'.format(BASE_SRC_DIR), + '{0}/MpegCoder.cpp'.format(BASE_SRC_DIR), + '{0}/MpegStreamer.cpp'.format(BASE_SRC_DIR), + '{0}/dllmain.cpp'.format(BASE_SRC_DIR) + ] +) + +setup( + name = 'mpegCoder', + version = '3.2.0', + description = 'A FFmpeg module which could provide a class for encoding, decoding, or streaming a video in any format.', + author = 'Yuchen Jin', + author_email = 'cainmagi@gmail.com', + url = 'https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python', + project_urls={ + 'Tracker': 'https://github.com/cainmagi/FFmpeg-Encoder-Decoder-for-Python/issues', + }, + long_description=LONG_DESCRIPTION, + long_description_content_type='text/markdown', + classifiers=[ + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3 :: Only', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', + 'Operating System :: POSIX :: Linux', + 'Topic :: Software Development :: Libraries :: Python Modules' + ], + keywords=[ + 'python', 'h264', 'video', 'rtsp', 'ffmpeg', 'rtmp', 'encoder', 'numpy', 'python3', 'python3-library', 'ffmpeg-wrapper', 'video-stream', 'python-c-api', 'rtsp-push', 'rtmp-push', 'rtsp-player', 'rtmp-player', 'ffmpeg-encoder' + ], + python_requires='>=3.6,<3.11', + license='GPLv3', + ext_modules = [module_mpegCoder] +) + diff --git a/webtools.py b/webtools.py index 13b351d..5952091 100644 --- a/webtools.py +++ b/webtools.py @@ -302,4 +302,4 @@ def download_tarball(user, repo, tag, asset, path='.', mode='auto', token=None, # token = get_token(token='') print('Get ffmpeg dependencies...') - download_tarball('cainmagi', 'FFmpeg-Encoder-Decoder-for-Python', 'deps-3.2.0', 'dep-win-ffmpeg_5_0.tar.xz', path='.', mode='auto', verbose=True, token='') + download_tarball('cainmagi', 'FFmpeg-Encoder-Decoder-for-Python', 'deps-3.0.0', 'dep-linux-ffmpeg_4_4.tar.xz', path=os.path.join('.', 'dependencies'), mode='auto', verbose=True, token='')