-
Notifications
You must be signed in to change notification settings - Fork 755
[Cherry-Pick][Others] support arm env #8084
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release/2.6
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,8 +27,8 @@ | |
| from .utils.video_utils import VideoReaderWrapper | ||
|
|
||
|
|
||
| def read_video_decord(video_path, save_to_disk): | ||
| """get reader and meta by decord""" | ||
| def read_video_paddlecodec(video_path, save_to_disk): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Bug Ernie 这条读取链路同样沿用了 建议修复方式:这里直接保留原始 |
||
| """get reader and meta by paddlecodec""" | ||
| # video_path = get_downloadable(video_path, save_to_disk=save_to_disk) | ||
| if isinstance(video_path, VideoReaderWrapper): | ||
| video_reader = video_path | ||
|
|
@@ -113,7 +113,7 @@ def get_frame_indices( | |
| return frame_indices | ||
|
|
||
|
|
||
| def read_frames_decord( | ||
| def read_frames_paddlecodec( | ||
| video_path, | ||
| video_reader, | ||
| video_meta, | ||
|
|
@@ -126,7 +126,7 @@ def read_frames_decord( | |
| frame_indices=None, | ||
| tol=10, | ||
| ): | ||
| """get frames by decord""" | ||
| """get frames by paddlecodec""" | ||
|
|
||
| if frame_indices is None: | ||
| frame_indices = get_frame_indices( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,10 @@ | |
| import os | ||
| from tempfile import NamedTemporaryFile as ntf | ||
|
|
||
| import decord | ||
| import numpy as np | ||
| import paddle | ||
|
|
||
| from fastdeploy.utils import get_logger | ||
|
|
||
| try: | ||
| # moviepy 1.0 | ||
|
|
@@ -27,6 +30,8 @@ | |
| # moviepy 2.0 | ||
| import moviepy as mp | ||
|
|
||
| logger = get_logger("video_utils") | ||
|
|
||
|
|
||
| def is_gif(data: bytes) -> bool: | ||
| """ | ||
|
|
@@ -35,19 +40,24 @@ def is_gif(data: bytes) -> bool: | |
| return data[:6] in (b"GIF87a", b"GIF89a") | ||
|
|
||
|
|
||
| class VideoReaderWrapper(decord.VideoReader): | ||
| """ | ||
| Solving memory leak bug | ||
| class _NumpyFrame: | ||
| """Wrapper so that frame[idx].asnumpy() keeps working with paddlecodec.""" | ||
|
|
||
| def __init__(self, array): | ||
| self._array = array | ||
|
|
||
| def asnumpy(self): | ||
| return self._array | ||
|
|
||
| https://github.com/dmlc/decord/issues/208 | ||
| """ | ||
|
|
||
| class VideoReaderWrapper: | ||
| """paddlecodec VideoDecoder wrapper with GIF support.""" | ||
|
|
||
| def __init__(self, video_path, *args, **kwargs): | ||
| with ntf(delete=True, suffix=".gif") as gif_file: | ||
| gif_input = None | ||
| self.original_file = None | ||
| if isinstance(video_path, str): | ||
| self.original_file = video_path | ||
| if video_path.lower().endswith(".gif"): | ||
| gif_input = video_path | ||
| elif isinstance(video_path, bytes): | ||
|
|
@@ -70,14 +80,58 @@ def __init__(self, video_path, *args, **kwargs): | |
| video_path = mp4_file.name | ||
| self.original_file = video_path | ||
|
|
||
| super().__init__(video_path, *args, **kwargs) | ||
| self.seek(0) | ||
| with paddle.use_compat_guard(enable=True, scope={"torchcodec"}): | ||
| try: | ||
| import sys | ||
|
|
||
| from torchcodec.decoders import VideoDecoder | ||
|
|
||
| sys.modules["torchcodec"] = None | ||
This comment was marked as outdated.
Sorry, something went wrong. |
||
| except (ImportError, RuntimeError) as e: | ||
| logger.error( | ||
| f"Failed to load 'torchcodec' backend via Paddle proxy.\n" | ||
| f" - Common Causes:\n" | ||
| f" 1. Conflict with official 'torch' or 'torchcodec' packages.\n" | ||
| f" 2. Missing FFmpeg libraries or System library mismatch (CXXABI).\n" | ||
| f" - Recommended Fix Steps:\n" | ||
| f" 1. Install dependencies: `conda install ffmpeg -c conda-forge` or `apt-get update && apt-get install ffmpeg` \n" | ||
| f" 2. Uninstall conflicts: `pip uninstall torchcodec paddlecodec -y`\n" | ||
| f" 3. Reinstall packages: `pip install paddlecodec --force-reinstall`\n" | ||
| f" - If you encounter 'CXXABI' or 'libstdc++' errors, your system libraries might be outdated.\n" | ||
| f" Try prioritizing Conda libraries by running: `LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH python your_script.py`\n" | ||
| f" - Original Error: {e}" | ||
| ) | ||
| raise | ||
| PADDLECODEC_NUM_THREADS = int(os.environ.get("PADDLECODEC_NUM_THREADS", 0)) | ||
| self._decoder = VideoDecoder( | ||
| video_path, | ||
| seek_mode="exact", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Bug Ernie 专用 wrapper 也传入了 建议修复方式:和共享 |
||
| num_ffmpeg_threads=PADDLECODEC_NUM_THREADS, | ||
| device=kwargs.get("device", "cpu"), | ||
| dimension_order="NHWC", | ||
| ) | ||
|
|
||
| def __len__(self): | ||
| return self._decoder.metadata.num_frames | ||
|
|
||
| def __getitem__(self, key): | ||
| frames = super().__getitem__(key) | ||
| self.seek(0) | ||
| return frames | ||
| if isinstance(key, (int, np.integer)): | ||
| frame = self._decoder.get_frames_at(indices=[int(key)]).data[0] | ||
| return _NumpyFrame(frame.numpy()) | ||
| if isinstance(key, slice): | ||
| indices = list(range(*key.indices(len(self)))) | ||
| else: | ||
| indices = list(key) if not isinstance(key, list) else key | ||
| frames = self._decoder.get_frames_at(indices=indices).data | ||
| return _NumpyFrame(frames.numpy()) | ||
|
|
||
| def get_avg_fps(self): | ||
| return self._decoder.metadata.average_fps | ||
|
|
||
| def __del__(self): | ||
| if self.original_file and os.path.exists(self.original_file): | ||
| os.remove(self.original_file) | ||
| original_file = getattr(self, "original_file", None) | ||
| if original_file and os.path.exists(original_file): | ||
| try: | ||
| os.remove(original_file) | ||
| except OSError: | ||
| pass | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,7 +12,7 @@ | |
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """Shared video utilities: VideoReaderWrapper, read_video_decord, and sample_frames.""" | ||
| """Shared video utilities: VideoReaderWrapper, read_video_paddlecodec, and sample_frames.""" | ||
|
|
||
| import io | ||
| import math | ||
|
|
@@ -21,13 +21,16 @@ | |
| from typing import Optional, Union | ||
|
|
||
| import numpy as np | ||
| import paddle | ||
|
|
||
| from fastdeploy.input.image_processors.common import ceil_by_factor, floor_by_factor | ||
| from fastdeploy.utils import data_processor_logger | ||
| from fastdeploy.utils import data_processor_logger, get_logger | ||
|
|
||
| logger = get_logger("video_utils") | ||
|
|
||
| __all__ = [ | ||
| "VideoReaderWrapper", | ||
| "read_video_decord", | ||
| "read_video_paddlecodec", | ||
This comment was marked as outdated.
Sorry, something went wrong. |
||
| "sample_frames", | ||
| "sample_frames_qwen", | ||
| "sample_frames_paddleocr", | ||
|
|
@@ -44,15 +47,20 @@ def _is_gif(data: bytes) -> bool: | |
| return data[:6] in (b"GIF87a", b"GIF89a") | ||
|
|
||
|
|
||
| class VideoReaderWrapper: | ||
| """decord.VideoReader wrapper that fixes a memory leak and adds GIF support. | ||
| class _NumpyFrame: | ||
| """Wrapper so that frame[idx].asnumpy() keeps working with paddlecodec.""" | ||
|
|
||
| Reference: https://github.com/dmlc/decord/issues/208 | ||
| """ | ||
| def __init__(self, array): | ||
| self._array = array | ||
|
|
||
| def asnumpy(self): | ||
| return self._array | ||
|
|
||
| def __init__(self, video_path, *args, **kwargs): | ||
| import decord | ||
|
|
||
| class VideoReaderWrapper: | ||
| """paddlecodec VideoDecoder wrapper with GIF support.""" | ||
|
|
||
| def __init__(self, video_path, *args, **kwargs): | ||
| try: | ||
| # moviepy 1.0 | ||
| import moviepy.editor as mp | ||
|
|
@@ -91,22 +99,53 @@ def __init__(self, video_path, *args, **kwargs): | |
| video_path = mp4_path | ||
| self.original_file = video_path # temp mp4, cleaned up in __del__ | ||
|
|
||
| self._reader = decord.VideoReader(video_path, *args, **kwargs) | ||
| self._reader.seek(0) | ||
| with paddle.use_compat_guard(enable=True, scope={"torchcodec"}): | ||
| try: | ||
| import sys | ||
|
|
||
| from torchcodec.decoders import VideoDecoder | ||
|
|
||
| sys.modules["torchcodec"] = None | ||
This comment was marked as outdated.
Sorry, something went wrong. |
||
| except (ImportError, RuntimeError) as e: | ||
| logger.error( | ||
| f"Failed to load 'torchcodec' backend via Paddle proxy.\n" | ||
| f" - Common Causes:\n" | ||
| f" 1. Conflict with official 'torch' or 'torchcodec' packages.\n" | ||
| f" 2. Missing FFmpeg libraries or System library mismatch (CXXABI).\n" | ||
| f" - Recommended Fix Steps:\n" | ||
| f" 1. Install dependencies: `conda install ffmpeg -c conda-forge` or `apt-get update && apt-get install ffmpeg` \n" | ||
| f" 2. Uninstall conflicts: `pip uninstall torchcodec paddlecodec -y`\n" | ||
| f" 3. Reinstall packages: `pip install paddlecodec --force-reinstall`\n" | ||
| f" - If you encounter 'CXXABI' or 'libstdc++' errors, your system libraries might be outdated.\n" | ||
| f" Try prioritizing Conda libraries by running: `LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH python your_script.py`\n" | ||
| f" - Original Error: {e}" | ||
| ) | ||
| raise | ||
| PADDLECODEC_NUM_THREADS = int(os.environ.get("PADDLECODEC_NUM_THREADS", 0)) | ||
| self._decoder = VideoDecoder( | ||
| video_path, | ||
| seek_mode="exact", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Bug 建议修复方式:要么去掉 |
||
| num_ffmpeg_threads=PADDLECODEC_NUM_THREADS, | ||
| device=kwargs.get("device", "cpu"), | ||
| dimension_order="NHWC", | ||
| ) | ||
|
|
||
| def __len__(self): | ||
| return len(self._reader) | ||
| return self._decoder.metadata.num_frames | ||
|
|
||
| def __getitem__(self, key): | ||
| frames = self._reader[key] | ||
| self._reader.seek(0) | ||
| return frames | ||
| if isinstance(key, (int, np.integer)): | ||
| frame = self._decoder.get_frames_at(indices=[int(key)]).data[0] | ||
| return _NumpyFrame(frame.numpy()) | ||
| if isinstance(key, slice): | ||
| indices = list(range(*key.indices(len(self)))) | ||
| else: | ||
| indices = list(key) if not isinstance(key, list) else key | ||
| frames = self._decoder.get_frames_at(indices=indices).data | ||
| return _NumpyFrame(frames.numpy()) | ||
|
|
||
| def get_avg_fps(self): | ||
| return self._reader.get_avg_fps() | ||
|
|
||
| def seek(self, pos): | ||
| return self._reader.seek(pos) | ||
| return self._decoder.metadata.average_fps | ||
|
|
||
| def __del__(self): | ||
| original_file = getattr(self, "original_file", None) | ||
|
|
@@ -118,11 +157,11 @@ def __del__(self): | |
|
|
||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # read_video_decord | ||
| # read_video_paddlecodec | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
|
|
||
| def read_video_decord(video_path, save_to_disk: bool = False): | ||
| def read_video_paddlecodec(video_path, save_to_disk: bool = False): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Bug 这个函数保留了旧的 建议修复方式:不要在这里把普通 |
||
| """Load a video file and return (video_reader, video_meta, video_path). | ||
|
|
||
| video_meta contains keys: "fps", "duration", "num_of_frame". | ||
|
|
||
This comment was marked as outdated.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.