Add initial cmake support for building the rocdecode library

This commit is contained in:
Aryan
2023-07-26 17:47:47 -04:00
bovenliggende 5b305a56ae
commit 1ba367988d
17 gewijzigde bestanden met toevoegingen van 1119 en 24 verwijderingen
+3
Bestand weergeven
@@ -0,0 +1,3 @@
build/
samples/*/build
.vscode/
+65
Bestand weergeven
@@ -0,0 +1,65 @@
################################################################################
# Copyright (c) 2023 Advanced Micro Devices, Inc.
#
# 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.
#
################################################################################
cmake_minimum_required (VERSION 3.0)
project(rocdecode)
set(VERSION "0.2.0")
set(CMAKE_INSTALL_LIBDIR "lib" CACHE STRING "Library install directory")
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE STRING "Include install directory")
set(CMAKE_CXX_STANDARD 17)
set(ROCM_PATH /opt/rocm CACHE PATH "Default ROCm installation path")
# avoid setting the default installation path to /usr/local
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX ${ROCM_PATH} CACHE PATH "rocDecode default installation path" FORCE)
endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH})
set(CMAKE_CXX_COMPILER ${ROCM_PATH}/llvm/bin/clang++)
set(DEFAULT_AMDGPU_TARGETS "gfx803;gfx900;gfx906;gfx908;gfx90a;gfx940;gfx1030;gfx1031;gfx1032")
set(AMDGPU_TARGETS "${DEFAULT_AMDGPU_TARGETS}" CACHE STRING "List of specific machine types for library to target")
find_package(HIP QUIET)
find_package(Libva QUIET)
if(HIP_FOUND AND Libva_FOUND)
list(APPEND SOURCES ${PROJECT_SOURCE_DIR} src/rocdecode_api.cpp src/rocdecoder.cpp)
add_library(${PROJECT_NAME} SHARED ${SOURCES})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17")
target_link_libraries(${PROJECT_NAME} Libva::va Libva::va_drm hip::device)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES api/rocdecode.h utils/videoDemuxer.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
else()
if (NOT HIP_FOUND)
message(FATAL_ERROR "-- ERROR!: HIP Not Found! - please install ROCm and HIP!")
endif()
if (NOT Libva_FOUND)
message(FATAL_ERROR "-- ERROR!: libva-dev Not Found - please install libva-dev!")
endif()
message("-- ERROR!: ${PROJECT_NAME} excluded! please install all the dependencies and try again!")
endif()
+29
Bestand weergeven
@@ -1,2 +1,31 @@
# rocDecode
rocDecode is a high performance video decode SDK for AMD hardware
## Prerequisites:
* One of the supported GPUs by ROCm: [AMD Radeon™ Graphics](https://docs.amd.com/bundle/Hardware_and_Software_Reference_Guide/page/Hardware_and_Software_Support.html)
* Linux distribution
+ **Ubuntu** - `20.04` / `22.04`
* Install [ROCm5.5 or later](https://docs.amd.com)
+ **Note** - both graphics and rocm use-cases must be installed (i.e., sudo amdgpu-install --usecase=graphics,rocm).
* CMake 3.0 or later
* libva-dev 2.7 or later
* [FFMPEG n4.4.2 or later](https://github.com/FFmpeg/FFmpeg/releases/tag/n4.4.2)
* **Note** [vcnDECODE-setup.py](vcnDECODE-setup.py) script can be used for installing all the dependencies
## Build instructions:
Please follow the instructions below to build and install the vcndecode library.
```
cd rocDecode
mkdir build; cd build
cmake ..
make -j8
sudo make install
```
## Samples:
The tool provides a few samples to decode videos [here](samples/). Please refer to the individual folders to build and run the samples.
## Docker:
Docker files to build vcnDECODE containers are available [here](docker/)
+163
Bestand weergeven
@@ -0,0 +1,163 @@
################################################################################
# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
################################################################################
# - Try to find ffmpeg libraries (libavcodec, libavformat and libavutil)
# Once done this will define
#
# FFMPEG_FOUND - system has ffmpeg or libav
# FFMPEG_INCLUDE_DIR - the ffmpeg include directory
# FFMPEG_LIBRARIES - Link these to use ffmpeg
################################################################################
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
FFmpeg
FOUND_VAR FFMPEG_FOUND
REQUIRED_VARS
FFMPEG_LIBRARIES
FFMPEG_INCLUDE_DIR
AVCODEC_INCLUDE_DIR
AVCODEC_LIBRARY
AVFORMAT_INCLUDE_DIR
AVFORMAT_LIBRARY
AVUTIL_INCLUDE_DIR
AVUTIL_LIBRARY
SWSCALE_INCLUDE_DIR
SWSCALE_LIBRARY
VERSION_VAR FFMPEG_VERSION
)
if(FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR)
set(FFMPEG_FOUND TRUE)
else()
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules(_FFMPEG_AVCODEC libavcodec)
pkg_check_modules(_FFMPEG_AVFORMAT libavformat)
pkg_check_modules(_FFMPEG_AVUTIL libavutil)
endif()
# AVCODEC
find_path(AVCODEC_INCLUDE_DIR
NAMES libavcodec/avcodec.h
PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS}
/usr/local/include
/usr/include
/opt/local/include
/sw/include
PATH_SUFFIXES ffmpeg libav
)
mark_as_advanced(AVCODEC_INCLUDE_DIR)
find_library(AVCODEC_LIBRARY
NAMES avcodec
PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS}
/usr/local/lib
/usr/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(AVCODEC_LIBRARY)
# AVFORMAT
find_path(AVFORMAT_INCLUDE_DIR
NAMES libavformat/avformat.h
PATHS ${_FFMPEG_AVFORMAT_INCLUDE_DIRS}
/usr/local/include
/usr/include
/opt/local/include
/sw/include
PATH_SUFFIXES ffmpeg libav
)
mark_as_advanced(AVFORMAT_INCLUDE_DIR)
find_library(AVFORMAT_LIBRARY
NAMES avformat
PATHS ${_FFMPEG_AVFORMAT_LIBRARY_DIRS}
/usr/local/lib
/usr/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(AVFORMAT_LIBRARY)
# AVUTIL
find_path(AVUTIL_INCLUDE_DIR
NAMES libavutil/avutil.h
PATHS ${_FFMPEG_AVUTIL_INCLUDE_DIRS}
/usr/local/include
/usr/include
/opt/local/include
/sw/include
PATH_SUFFIXES ffmpeg libav
)
mark_as_advanced(AVUTIL_INCLUDE_DIR)
find_library(AVUTIL_LIBRARY
NAMES avutil
PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS}
/usr/local/lib
/usr/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(AVUTIL_LIBRARY)
# SWSCALE
find_path(SWSCALE_INCLUDE_DIR
NAMES libswscale/swscale.h
PATHS ${_FFMPEG_SWSCALE_INCLUDE_DIRS}
/usr/local/include
/usr/include
/opt/local/include
/sw/include
PATH_SUFFIXES ffmpeg libav sw
)
mark_as_advanced(SWSCALE_INCLUDE_DIR)
find_library(SWSCALE_LIBRARY
NAMES swscale
PATHS ${_FFMPEG_SWSCALE_LIBRARY_DIRS}
/usr/local/lib
/usr/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(SWSCALE_LIBRARY)
if(AVCODEC_LIBRARY AND AVFORMAT_LIBRARY)
set(FFMPEG_FOUND TRUE)
endif()
if(_FFMPEG_AVCODEC_VERSION VERSION_LESS 58.18.100 OR _FFMPEG_AVFORMAT_VERSION VERSION_LESS 58.12.100 OR _FFMPEG_AVUTIL_VERSION VERSION_LESS 56.14.100)
if(FFMPEG_FOUND)
message("-- ${White}FFMPEG required min version - 4.0.4 Found:${FFMPEG_VERSION}")
message("-- ${White}AVCODEC required min version - 58.18.100 Found:${_FFMPEG_AVCODEC_VERSION}${ColourReset}")
message("-- ${White}AVFORMAT required min version - 58.12.100 Found:${_FFMPEG_AVFORMAT_VERSION}${ColourReset}")
message("-- ${White}AVUTIL required min version - 56.14.100 Found:${_FFMPEG_AVUTIL_VERSION}${ColourReset}")
endif()
set(FFMPEG_FOUND FALSE)
message( "-- ${Yellow}NOTE: FindFFmpeg failed to find -- FFMPEG${ColourReset}" )
endif()
if(FFMPEG_FOUND)
set(FFMPEG_INCLUDE_DIR ${AVFORMAT_INCLUDE_DIR} CACHE INTERNAL "")
set(FFMPEG_LIBRARIES
${AVCODEC_LIBRARY}
${AVFORMAT_LIBRARY}
${AVUTIL_LIBRARY}
${SWSCALE_LIBRARY}
CACHE INTERNAL ""
)
endif()
if(FFMPEG_FOUND)
if(NOT FFMPEG_FIND_QUIETLY)
message("-- ${White}Using FFMPEG -- Libraries:${FFMPEG_LIBRARIES} Includes:${FFMPEG_INCLUDE_DIR}${ColourReset}")
endif()
else()
if(FFMPEG_FIND_REQUIRED)
message(FATAL_ERROR "{Red}FindFFmpeg -- libavcodec or libavformat or libavutil NOT FOUND${ColourReset}")
endif()
endif()
endif()
+34
Bestand weergeven
@@ -0,0 +1,34 @@
################################################################################
#
# MIT License
#
# Copyright (c) 2022 Advanced Micro Devices, Inc.
#
# 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.
#
find_package(PkgConfig)
pkg_check_modules(Libdrm libdrm)
if(Libdrm_FOUND)
if(NOT TARGET Libdrm::drm)
add_library(Libdrm::drm UNKNOWN IMPORTED)
set_target_properties(Libdrm::drm PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Libdrm_INCLUDE_DIRS}"
IMPORTED_LOCATION "${Libdrm_LINK_LIBRARIES}")
endif()
endif()
+47
Bestand weergeven
@@ -0,0 +1,47 @@
################################################################################
#
# MIT License
#
# Copyright (c) 2022 Advanced Micro Devices, Inc.
#
# 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.
#
find_package(Libdrm REQUIRED)
find_library(LIBVA_LIBRARY NAMES va)
find_library(LIBVA_DRM_LIBRARY NAMES va-drm)
find_path(LIBVA_INCLUDE_DIR NAMES va/va.h)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libva DEFAULT_MSG LIBVA_INCLUDE_DIR LIBVA_LIBRARY LIBVA_DRM_LIBRARY)
mark_as_advanced(LIBVA_INCLUDE_DIR LIBVA_LIBRARY LIBVA_DRM_LIBRARY)
if(Libva_FOUND)
if(NOT TARGET Libva::va)
add_library(Libva::va UNKNOWN IMPORTED)
set_target_properties(Libva::va PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBVA_INCLUDE_DIR}"
IMPORTED_LOCATION "${LIBVA_LIBRARY}")
endif()
if(NOT TARGET Libva::va_drm)
add_library(Libva::va_drm UNKNOWN IMPORTED)
target_link_libraries(Libva::va_drm INTERFACE Libdrm::drm)
set_target_properties(Libva::va_drm PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBVA_INCLUDE_DIR}"
IMPORTED_LOCATION "${LIBVA_DRM_LIBRARY}")
endif()
endif()
+13
Bestand weergeven
@@ -0,0 +1,13 @@
# rocDecoder Docker
## Build - dockerfiles
```
sudo docker build -f {DOCKER_FILE_NAME}.dockerfile -t {DOCKER_IMAGE_NAME} .
```
## Run - docker
```
sudo docker run -it --device=/dev/kfd --device=/dev/dri --cap-add=SYS_RAWIO --device=/dev/mem --group-add video --network host --env DISPLAY=unix$DISPLAY --privileged --volume $XAUTH:/root/.Xauthority --volume /tmp/.X11-unix/:/tmp/.X11-unix {DOCKER_IMAGE_NAME}
```
@@ -0,0 +1,28 @@
FROM ubuntu:20.04
# install base dependencies
RUN apt-get update -y
#RUN apt-get dist-upgrade -y
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install gcc g++ cmake pkg-config git apt-utils sudo vainfo dialog
RUN DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386
# install ROCm
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install initramfs-tools libnuma-dev wget keyboard-configuration && \
wget https://repo.radeon.com/amdgpu-install/5.5/ubuntu/focal/amdgpu-install_5.5.50500-1_all.deb && \
sudo apt-get install ./amdgpu-install_5.5.50500-1_all.deb && \
sudo amdgpu-install -y --usecase=graphics,rocm
# install FFMPEG, and other dependencies
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install autoconf automake build-essential cmake git-core libass-dev libfreetype6-dev libsdl2-dev libtool libva-dev \
libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo wget zlib1g-dev \
nasm yasm libx264-dev libx265-dev libnuma-dev libfdk-aac-dev unzip && \
wget https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n4.4.2.zip && unzip n4.4.2.zip && cd FFmpeg-n4.4.2/ && sudo ldconfig && \
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/" && \
./configure --enable-shared --disable-static && \
make -j8 && sudo make install && cd
ENV LD_LIBRARY_PATH="/usr/local/lib:/usr/local/lib64/:/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"
WORKDIR /workspace
@@ -0,0 +1,27 @@
FROM ubuntu:22.04
# install base dependencies
RUN apt-get update -y
#RUN apt-get dist-upgrade -y
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install gcc g++ cmake pkg-config git apt-utils sudo vainfo dialog libstdc++-12-dev
RUN DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386
# install ROCm
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install initramfs-tools libnuma-dev wget keyboard-configuration && \
wget https://repo.radeon.com/amdgpu-install/5.5/ubuntu/jammy/amdgpu-install_5.5.50500-1_all.deb && \
sudo apt-get install ./amdgpu-install_5.5.50500-1_all.deb && \
sudo amdgpu-install -y --usecase=graphics,rocm
# install FFMPEG, and other dependencies
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install autoconf automake build-essential cmake git-core libass-dev libfreetype6-dev libsdl2-dev libtool libva-dev \
libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo wget zlib1g-dev \
nasm yasm libx264-dev libx265-dev libnuma-dev libfdk-aac-dev unzip && \
wget https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n4.4.2.zip && unzip n4.4.2.zip && cd FFmpeg-n4.4.2/ && sudo ldconfig && \
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/" && \
./configure --enable-shared --disable-static && \
make -j8 && sudo make install && cd
ENV LD_LIBRARY_PATH="/usr/local/lib:/usr/local/lib64/:/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"
WORKDIR /workspace
+215
Bestand weergeven
@@ -0,0 +1,215 @@
# Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
#
# 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.
import os
import sys
import argparse
import platform
if sys.version_info[0] < 3:
import commands
else:
import subprocess
__version__ = "1.0"
__status__ = "Shipping"
# Arguments
parser = argparse.ArgumentParser()
parser.add_argument('--directory', type=str, default='~/rocDecode-deps',
help='Setup home directory - optional (default:~/)')
parser.add_argument('--ffmpeg', type=str, default='yes',
help='FFMPEG V4.4.2 Installation (default:yes) [options:yes/no]')
parser.add_argument('--reinstall', type=str, default='no',
help='Remove previous setup and reinstall - optional (default:no) [options:yes/no]')
args = parser.parse_args()
setupDir = args.directory
ffmpegInstall = args.ffmpeg
reinstall = args.reinstall
if ffmpegInstall not in ('no', 'yes'):
print(
"ERROR: FFMPEG Install Option Not Supported - [Supported Options: no or yes]")
exit()
# get platfrom info
platfromInfo = platform.platform()
# sudo requirement check
sudoLocation = ''
userName = ''
if sys.version_info[0] < 3:
status, sudoLocation = commands.getstatusoutput("which sudo")
if sudoLocation != '/usr/bin/sudo':
status, userName = commands.getstatusoutput("whoami")
else:
status, sudoLocation = subprocess.getstatusoutput("which sudo")
if sudoLocation != '/usr/bin/sudo':
status, userName = subprocess.getstatusoutput("whoami")
# Setup Directory for Deps
if setupDir == '~/rocDecode-deps':
setupDir_deps = setupDir
else:
setupDir_deps = setupDir+'/rocDecode-deps'
# setup directory path
deps_dir = os.path.expanduser(setupDir_deps)
deps_dir = os.path.abspath(deps_dir)
# setup for Linux
linuxSystemInstall = ''
linuxCMake = 'cmake'
linuxSystemInstall_check = ''
linuxFlag = ''
if "centos" in platfromInfo or "redhat" in platfromInfo:
linuxSystemInstall = 'yum -y'
linuxSystemInstall_check = '--nogpgcheck'
if "centos-7" in platfromInfo or "redhat-7" in platfromInfo:
linuxCMake = 'cmake3'
os.system(linuxSystemInstall+' install cmake3')
elif "Ubuntu" in platfromInfo or os.path.exists('/usr/bin/apt-get'):
linuxSystemInstall = 'apt-get -y'
linuxSystemInstall_check = '--allow-unauthenticated'
linuxFlag = '-S'
if not "Ubuntu" in platfromInfo:
platfromInfo = platfromInfo+'-Ubuntu'
elif os.path.exists('/usr/bin/zypper'):
linuxSystemInstall = 'zypper -n'
linuxSystemInstall_check = '--no-gpg-checks'
platfromInfo = platfromInfo+'-SLES'
else:
print("\nrocDecode Setup on "+platfromInfo+" is unsupported\n")
print("\nrocDecode Setup Supported on: Ubuntu 20/22; CentOS 7/8; RedHat 7/8; & SLES 15-SP2\n")
exit()
# rocDecode Setup
print("\nrocDecode Setup on: "+platfromInfo+"\n")
if userName == 'root':
os.system(linuxSystemInstall+' update')
os.system(linuxSystemInstall+' install sudo')
# Delete previous install
if os.path.exists(deps_dir) and reinstall == 'yes':
os.system('sudo -v')
os.system('sudo rm -rf '+deps_dir)
print("\nrocDecode Setup: Removing Previous Install -- "+deps_dir+"\n")
# Re-Install
if os.path.exists(deps_dir):
print("\nrocDecode Setup: Re-Installing Libraries from -- "+deps_dir+"\n")
if ffmpegInstall == 'yes':
# FFMPEG
if os.path.exists(deps_dir+'/FFmpeg-n4.4.2'):
os.system('sudo -v')
os.system('(cd '+deps_dir+'/FFmpeg-n4.4.2; sudo ' +
linuxFlag+' make install -j8)')
print("\nrocDecode Dependencies Re-Installed with rocDecode-setup.py V-"+__version__+"\n")
exit()
# Clean Install
else:
print("\nrocDecode Dependencies Installation with rocDecode-setup.py V-"+__version__+"\n")
os.system('mkdir '+deps_dir)
# Create Build folder
os.system('(cd '+deps_dir+'; mkdir build )')
# install pre-reqs
os.system('sudo -v')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' ' +
linuxSystemInstall_check+' install gcc cmake git wget unzip pkg-config inxi vainfo')
# Get Installation Source
if ffmpegInstall == 'yes':
os.system(
'(cd '+deps_dir+'; wget https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n4.4.2.zip && unzip n4.4.2.zip )')
# Install ffmpeg
if ffmpegInstall == 'yes':
if "Ubuntu" in platfromInfo:
os.system('sudo -v')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install autoconf automake build-essential git-core libass-dev libfreetype6-dev')
os.system('sudo -v')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install libsdl2-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev')
os.system('sudo -v')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo zlib1g-dev')
os.system('sudo -v')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install nasm yasm libx264-dev libx265-dev libnuma-dev libfdk-aac-dev')
else:
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install autoconf automake bzip2 bzip2-devel freetype-devel')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install gcc-c++ libtool make pkgconfig zlib-devel')
# Nasm
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install nasm')
if "centos-7" in platfromInfo or "redhat-7" in platfromInfo:
# Yasm
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install http://repo.okay.com.mx/centos/7/x86_64/release/okay-release-1-1.noarch.rpm')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' --enablerepo=extras install epel-release')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install yasm')
# libx264 & libx265
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install libx264-devel libx265-devel')
# libfdk_aac
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install https://forensics.cert.org/cert-forensics-tools-release-el7.rpm')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' --enablerepo=forensics install fdk-aac')
# libASS
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install libass-devel')
elif "centos-8" in platfromInfo or "redhat-8" in platfromInfo:
# el8 x86_64 packages
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-8.noarch.rpm')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/SDL2-2.0.10-2.el8.x86_64.rpm')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install ffmpeg ffmpeg-devel')
elif "SLES" in platfromInfo:
# FFMPEG-4 packages
os.system(
'sudo zypper ar -cfp 90 \'https://ftp.gwdg.de/pub/linux/misc/packman/suse/openSUSE_Leap_$releasever/Essentials\' packman-essentials')
os.system('sudo '+linuxFlag+' '+linuxSystemInstall+' '+linuxSystemInstall_check +
' install ffmpeg-4')
# FFMPEG 4 from source -- for Ubuntu, CentOS 7, & RedHat 7
if "Ubuntu" in platfromInfo or "centos-7" in platfromInfo or "redhat-7" in platfromInfo:
os.system('sudo -v')
os.system(
'(cd '+deps_dir+'/FFmpeg-n4.4.2; sudo '+linuxFlag+' ldconfig )')
os.system('(cd '+deps_dir+'/FFmpeg-n4.4.2; export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/"; ./configure --enable-shared --disable-static)')
os.system('(cd '+deps_dir+'/FFmpeg-n4.4.2; make -j8 )')
os.system('sudo -v')
os.system('(cd '+deps_dir+'/FFmpeg-n4.4.2; sudo ' +
linuxFlag+' make install )')
print("\nrocDecode Dependencies Installed with rocDecode-setup.py V-"+__version__+"\n")
@@ -0,0 +1,54 @@
################################################################################
# Copyright (c) 2023 Advanced Micro Devices, Inc.
#
# 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.
#
################################################################################
cmake_minimum_required (VERSION 3.0)
project(videodecode)
set(CMAKE_CXX_STANDARD 17)
set(ROCM_PATH /opt/rocm CACHE PATH "default ROCm installation path")
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../cmake)
list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH})
set(CMAKE_CXX_COMPILER ${ROCM_PATH}/llvm/bin/clang++)
set(DEFAULT_AMDGPU_TARGETS "gfx803;gfx900;gfx906;gfx908;gfx90a;gfx940;gfx1030;gfx1031;gfx1032")
set(AMDGPU_TARGETS "${DEFAULT_AMDGPU_TARGETS}" CACHE STRING "List of specific machine types for library to target")
find_package(HIP QUIET)
find_package(FFmpeg QUIET)
find_package(Libva QUIET)
if(HIP_FOUND AND FFMPEG_FOUND AND Libva_FOUND)
include_directories (${ROCM_PATH}/include/rocdecode)
list(APPEND SOURCES ${PROJECT_SOURCE_DIR} videodecode.cpp)
add_executable(${PROJECT_NAME} ${SOURCES})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17")
target_link_libraries(${PROJECT_NAME} ${AVUTIL_LIBRARY} ${AVCODEC_LIBRARY} ${AVFORMAT_LIBRARY} Libva::va Libva::va_drm hip::device rocdecode)
else()
if (NOT HIP_FOUND)
message(FATAL_ERROR "-- ERROR!: HIP Not Found! - please install ROCm and HIP!")
endif()
if (NOT FFMPEG_FOUND)
message(FATAL_ERROR "-- ERROR!: FFMPEG Not Found! - please insatll FFMPEG!")
endif()
if (NOT Libva_FOUND)
message(FATAL_ERROR "-- ERROR!: libva-dev Not Found - please install libva-dev!")
endif()
message("-- ERROR!: ${PROJECT_NAME} excluded! please install all the dependencies and try again!")
endif()
+11
Bestand weergeven
@@ -0,0 +1,11 @@
# Video Decode Sample
This sample illustrates the FFMPEG demuxer to get the individual frames which are then decoded on AMD hardware using VAAPI. This sample supports both YUV420 8-bit and 10-bit streams.
## Build and run the sample:
```
mkdir build
cd build
cmake ..
make -j
./videodecode -i <input video file - required> -o <optional; output path to save decoded YUV frames> -d <GPU device ID, 0 for the first device, 1 for the second device, etc>
```
+146
Bestand weergeven
@@ -0,0 +1,146 @@
/*
Copyright (c) 2023 - 2023 Advanced Micro Devices, Inc. All rights reserved.
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.
*/
#include <iostream>
#include <unistd.h>
#include <vector>
#include <string>
#include <chrono>
#include <sys/stat.h>
#include <libgen.h>
#include <filesystem>
#include "videoDemuxer.hpp"
#include "rocdecode.h"
void ShowHelpAndExit(const char *option = NULL) {
std::cout << "Options:" << std::endl
<< "-i Input File Path - required" << std::endl
<< "-o Output File Path - dumps output if requested; optional" << std::endl
<< "-d GPU device ID (0 for the first device, 1 for the second, etc.); optional; default: 0" << std::endl;
exit(0);
}
int main(int argc, char **argv) {
std::string inputFilePath, outputFilePath;
int dumpOutputFrames = 0;
int isOutputRGB = 0;
int deviceId = 0;
// Parse command-line arguments
if(argc < 1) {
ShowHelpAndExit();
}
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-h")) {
ShowHelpAndExit();
}
if (!strcmp(argv[i], "-i")) {
if (++i == argc) {
ShowHelpAndExit("-i");
}
inputFilePath = argv[i];
continue;
}
if (!strcmp(argv[i], "-o")) {
if (++i == argc) {
ShowHelpAndExit("-o");
}
outputFilePath = argv[i];
dumpOutputFrames = 1;
continue;
}
if (!strcmp(argv[i], "-d")) {
if (++i == argc) {
ShowHelpAndExit("-d");
}
deviceId = atoi(argv[i]);
continue;
}
ShowHelpAndExit(argv[i]);
}
VideoDemuxer demuxer(inputFilePath.c_str());
//VideoDecode viddec(deviceId);
std::string deviceName, gcnArchName, drmNode;
int pciBusID, pciDomainID, pciDeviceID;
/*viddec.getDeviceinfo(deviceName, gcnArchName, pciBusID, pciDomainID, pciDeviceID, drmNode);
std::cout << "info: Using GPU device " << deviceId << ": (drm node: " << drmNode << ") " << deviceName << "[" << gcnArchName << "] on PCI bus " <<
std::setfill('0') << std::setw(2) << std::right << std::hex << pciBusID << ":" << std::setfill('0') << std::setw(2) <<
std::right << std::hex << pciDomainID << "." << pciDeviceID << std::dec << std::endl;
std::cout << "info: decoding started, please wait!" << std::endl;*/
int nVideoBytes = 0, nFrameReturned = 0, nFrame = 0;
uint8_t *pVideo = nullptr;
uint8_t *pFrame = nullptr;
int64_t pts = 0;
//outputImageInfo *pImageInfo;
bool bDecodeOutSemiPlanar = false;
uint32_t width, height;
//vcnImageFormat_t subsampling;
double totalDecTime = 0;
do {
auto startTime = std::chrono::high_resolution_clock::now();
demuxer.demux(&pVideo, &nVideoBytes, &pts);
//nFrameReturned = viddec.decode(pVideo, nVideoBytes, pts);
auto endTime = std::chrono::high_resolution_clock::now();
auto timePerFrame = std::chrono::duration<double, std::milli>(endTime - startTime).count();
totalDecTime += timePerFrame;
/*if (!nFrame && !viddec.getOutputImageInfo(&pImageInfo)){
std::cerr << "Error: Failed to get Output Image Info!" << std::endl;
break;
}*/
if (dumpOutputFrames) {
for (int i = 0; i < nFrameReturned; i++) {
/*pFrame = viddec.getFrame(&pts);
viddec.saveImage(outputFilePath, pFrame, pImageInfo, false);
// release frame
viddec.releaseFrame(pts);*/
}
}
nFrame += nFrameReturned;
} while (nVideoBytes);
// Flush last frames from the decoder if any
do {
// send null packet to decoder to flush out
pVideo = nullptr; nVideoBytes = 0;
int64_t pts = 0;
//nFrameReturned = viddec.decode(pVideo, nVideoBytes, pts);
} while (nFrameReturned);
/*std::cout << "info: Video codec format: " << viddec.getCodecFmtName(viddec.getVcnVideoCodecId()) << std::endl;
std::cout << "info: Video size: [ " << pImageInfo->nOutputWidth << ", " << pImageInfo->nOutputHeight << " ]" << std::endl;
std::cout << "info: Video pix format: " << viddec.getPixFmtName(pImageInfo->chromaFormat) << std::endl;
std::cout << "info: Video Bit depth: " << pImageInfo->nBitDepth << std::endl;
std::cout << "info: Total frame decoded: " << nFrame << std::endl;
if (!dumpOutputFrames) {
std::cout << "info: avg decoding time per frame (ms): " << totalDecTime / nFrame << std::endl;
std::cout << "info: avg FPS: " << (nFrame / totalDecTime) * 1000 << std::endl;
}*/
return 0;
}
+21
Bestand weergeven
@@ -0,0 +1,21 @@
/*
Copyright (c) 2023 - 2023 Advanced Micro Devices, Inc. All rights reserved.
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.
*/
@@ -30,5 +30,4 @@ THE SOFTWARE.
#include <sstream>
#include <string.h>
#include "../api/rocdecode.h"
#include "../utils/ffmpeg_demux.h"
#include <map>
-23
Bestand weergeven
@@ -1,23 +0,0 @@
/*
Copyright (c) 2023 - 2023 Advanced Micro Devices, Inc. All rights reserved.
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.
*/
#pragma once
+263
Bestand weergeven
@@ -0,0 +1,263 @@
/*
Copyright (c) 2023 - 2023 Advanced Micro Devices, Inc. All rights reserved.
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.
*/
#pragma once
#include <iostream>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/pixdesc.h>
#include <libavutil/hwcontext.h>
#include <libavutil/hwcontext_vaapi.h>
#include <va/va.h>
#include <va/va_drmcommon.h>
}
// Video Demuxer Interface class
class VideoDemuxer {
public:
class StreamProvider {
public:
virtual ~StreamProvider() {}
virtual int getData(uint8_t *pBuf, int nBuf) = 0;
};
VideoDemuxer(const char *inputFilePath) : VideoDemuxer(createFmtContextUtil(inputFilePath)) {}
VideoDemuxer(StreamProvider *pStreamProvider) : VideoDemuxer(createFmtContextUtil(pStreamProvider)) {av_io_ctx_ = av_fmt_input_ctx_->pb;}
~VideoDemuxer();
bool demux(uint8_t **ppVideo, int *pnVideoBytes, int64_t *pts = nullptr);
private:
VideoDemuxer(AVFormatContext *av_fmt_input_ctx_);
AVFormatContext *createFmtContextUtil(StreamProvider *pStreamProvider);
AVFormatContext *createFmtContextUtil(const char *inputFilePath);
static int readPacket(void *pData, uint8_t *pBuf, int nBuf);
AVFormatContext *av_fmt_input_ctx_ = nullptr;
AVIOContext *av_io_ctx_ = nullptr;
AVPacket* packet_ = nullptr;
AVPacket* packetFiltered_ = nullptr;
AVBSFContext *av_bsf_ctx_ = nullptr;
AVCodecID av_videoCodecID_;
uint8_t *pDataWithHeader = nullptr;
int av_stream_ = 0;
bool isH264_ = false;
bool isHEVC_ = false;
bool isMPEG4_ = false;
int64_t defaultTimeScale = 1000;
double timeBase = 0.0;
unsigned int frameCnt = 0;
};
VideoDemuxer::~VideoDemuxer() {
if (!av_fmt_input_ctx_) {
return;
}
if (packet_) {
av_packet_free(&packet_);
}
if (packetFiltered_) {
av_packet_free(&packetFiltered_);
}
if (av_bsf_ctx_) {
av_bsf_free(&av_bsf_ctx_);
}
avformat_close_input(&av_fmt_input_ctx_);
if (av_io_ctx_) {
av_freep(&av_io_ctx_->buffer);
av_freep(&av_io_ctx_);
}
if (pDataWithHeader) {
av_free(pDataWithHeader);
}
}
bool VideoDemuxer::demux(uint8_t **ppVideo, int *pnVideoBytes, int64_t *pts) {
if (!av_fmt_input_ctx_) {
return false;
}
*pnVideoBytes = 0;
if (packet_->data) {
av_packet_unref(packet_);
}
int ret = 0;
while ((ret = av_read_frame(av_fmt_input_ctx_, packet_)) >= 0 && packet_->stream_index != av_stream_) {
av_packet_unref(packet_);
}
if (ret < 0) {
return false;
}
if (isH264_ || isHEVC_) {
if (packetFiltered_->data) {
av_packet_unref(packetFiltered_);
}
if (av_bsf_send_packet(av_bsf_ctx_, packet_) != 0) {
std::cerr << "ERROR: av_bsf_send_packet failed!" << std::endl;
return false;
}
if (av_bsf_receive_packet(av_bsf_ctx_, packetFiltered_) != 0) {
std::cerr << "ERROR: av_bsf_receive_packet failed!" << std::endl;
return false;
}
*ppVideo = packetFiltered_->data;
*pnVideoBytes = packetFiltered_->size;
if (pts)
*pts = (int64_t) (packetFiltered_->pts * defaultTimeScale * timeBase);
} else {
if (isMPEG4_ && (frameCnt == 0)) {
int extDataSize = av_fmt_input_ctx_->streams[av_stream_]->codecpar->extradata_size;
if (extDataSize > 0) {
pDataWithHeader = (uint8_t *)av_malloc(extDataSize + packet_->size - 3 * sizeof(uint8_t));
if (!pDataWithHeader) {
std::cerr << "ERROR: av_malloc failed!" << std::endl;
return false;
}
memcpy(pDataWithHeader, av_fmt_input_ctx_->streams[av_stream_]->codecpar->extradata, extDataSize);
memcpy(pDataWithHeader + extDataSize, packet_->data + 3, packet_->size - 3 * sizeof(uint8_t));
*ppVideo = pDataWithHeader;
*pnVideoBytes = extDataSize + packet_->size - 3 * sizeof(uint8_t);
}
} else {
*ppVideo = packet_->data;
*pnVideoBytes = packet_->size;
}
if (pts)
*pts = (int64_t)(packet_->pts * defaultTimeScale * timeBase);
}
frameCnt++;
return true;
}
VideoDemuxer::VideoDemuxer(AVFormatContext *av_fmt_input_ctx_) : av_fmt_input_ctx_(av_fmt_input_ctx_) {
if (!av_fmt_input_ctx_) {
std::cerr << "ERROR: av_fmt_input_ctx_ is not vaild!" << std::endl;
return;
}
packet_ = av_packet_alloc();
packetFiltered_ = av_packet_alloc();
if (!packet_ || !packetFiltered_) {
std::cerr << "ERROR: av_packet_alloc failed!" << std::endl;
return;
}
if (avformat_find_stream_info(av_fmt_input_ctx_, nullptr) < 0) {
std::cerr << "ERROR: avformat_find_stream_info failed!" << std::endl;
return;
}
av_stream_ = av_find_best_stream(av_fmt_input_ctx_, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
if (av_stream_ < 0) {
std::cerr << "ERROR: av_find_best_stream failed!" << std::endl;
av_packet_free(&packet_);
av_packet_free(&packetFiltered_);
return;
}
av_videoCodecID_ = av_fmt_input_ctx_->streams[av_stream_]->codecpar->codec_id;
AVRational rTimeBase = av_fmt_input_ctx_->streams[av_stream_]->time_base;
timeBase = av_q2d(rTimeBase);
isH264_ = av_videoCodecID_ == AV_CODEC_ID_H264 && (!strcmp(av_fmt_input_ctx_->iformat->long_name, "QuickTime / MOV")
|| !strcmp(av_fmt_input_ctx_->iformat->long_name, "FLV (Flash Video)")
|| !strcmp(av_fmt_input_ctx_->iformat->long_name, "Matroska / WebM"));
isHEVC_ = av_videoCodecID_ == AV_CODEC_ID_HEVC && (!strcmp(av_fmt_input_ctx_->iformat->long_name, "QuickTime / MOV")
|| !strcmp(av_fmt_input_ctx_->iformat->long_name, "FLV (Flash Video)")
|| !strcmp(av_fmt_input_ctx_->iformat->long_name, "Matroska / WebM"));
isMPEG4_ = av_videoCodecID_ == AV_CODEC_ID_MPEG4 && (!strcmp(av_fmt_input_ctx_->iformat->long_name, "QuickTime / MOV")
|| !strcmp(av_fmt_input_ctx_->iformat->long_name, "FLV (Flash Video)")
|| !strcmp(av_fmt_input_ctx_->iformat->long_name, "Matroska / WebM"));
if (isH264_) {
const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");
if (!bsf) {
std::cerr << "ERROR: av_bsf_get_by_name() failed" << std::endl;
av_packet_free(&packet_);
av_packet_free(&packetFiltered_);
return;
}
if (av_bsf_alloc(bsf, &av_bsf_ctx_) != 0) {
std::cerr << "ERROR: av_bsf_alloc failed!" << std::endl;
return;
}
avcodec_parameters_copy(av_bsf_ctx_->par_in, av_fmt_input_ctx_->streams[av_stream_]->codecpar);
if (av_bsf_init(av_bsf_ctx_) < 0) {
std::cerr << "ERROR: av_bsf_init failed!" << std::endl;
return;
}
}
if (isHEVC_) {
const AVBitStreamFilter *bsf = av_bsf_get_by_name("hevc_mp4toannexb");
if (!bsf) {
std::cerr << "ERROR: av_bsf_get_by_name() failed" << std::endl;
av_packet_free(&packet_);
av_packet_free(&packetFiltered_);
return;
}
if (av_bsf_alloc(bsf, &av_bsf_ctx_) != 0 ) {
std::cerr << "ERROR: av_bsf_alloc failed!" << std::endl;
return;
}
avcodec_parameters_copy(av_bsf_ctx_->par_in, av_fmt_input_ctx_->streams[av_stream_]->codecpar);
if (av_bsf_init(av_bsf_ctx_) < 0) {
std::cerr << "ERROR: av_bsf_init failed!" << std::endl;
return;
}
}
}
AVFormatContext *VideoDemuxer::createFmtContextUtil(StreamProvider *pStreamProvider) {
AVFormatContext *ctx = nullptr;
if (!(ctx = avformat_alloc_context())) {
std::cerr << "ERROR: avformat_alloc_context failed" << std::endl;
return nullptr;
}
uint8_t *avioc_buffer = nullptr;
int avioc_buffer_size = 8 * 1024 * 1024;
avioc_buffer = (uint8_t *)av_malloc(avioc_buffer_size);
if (!avioc_buffer) {
std::cerr << "ERROR: av_malloc failed!" << std::endl;;
return nullptr;
}
av_io_ctx_ = avio_alloc_context(avioc_buffer, avioc_buffer_size,
0, pStreamProvider, &readPacket, nullptr, nullptr);
if (!av_io_ctx_) {
std::cerr << "ERROR: avio_alloc_context failed!" << std::endl;
return nullptr;
}
ctx->pb = av_io_ctx_;
if (avformat_open_input(&ctx, nullptr, nullptr, nullptr) != 0) {
std::cerr << "ERROR: avformat_open_input failed!" << std::endl;
return nullptr;
}
return ctx;
}
AVFormatContext *VideoDemuxer::createFmtContextUtil(const char *inputFilePath) {
avformat_network_init();
av_log_set_level(AV_LOG_QUIET);
AVFormatContext *ctx = nullptr;
if (avformat_open_input(&ctx, inputFilePath, nullptr, nullptr) != 0 ) {
std::cerr << "ERROR: avformat_open_input failed!" << std::endl;
return nullptr;
}
return ctx;
}
int VideoDemuxer::readPacket(void *pData, uint8_t *pBuf, int nBuf) {
return ((StreamProvider *)pData)->getData(pBuf, nBuf);
}