Remove raspicam lib as opencv already does the job
This commit is contained in:
parent
68416a8a9a
commit
a7cc3e6de4
254
Input/Externals/raspicam-master/CMakeLists.txt
vendored
254
Input/Externals/raspicam-master/CMakeLists.txt
vendored
@ -1,254 +0,0 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
# Basic Configuration
|
||||
# ----------------------------------------------------------------------------
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
endif (POLICY CMP0048)
|
||||
|
||||
PROJECT(raspicam)
|
||||
set(PROJECT_VERSION "0.1.2")
|
||||
string(REGEX MATCHALL "[0-9]" PROJECT_VERSION_PARTS "${PROJECT_VERSION}")
|
||||
list(GET PROJECT_VERSION_PARTS 0 PROJECT_VERSION_MAJOR)
|
||||
list(GET PROJECT_VERSION_PARTS 1 PROJECT_VERSION_MINOR)
|
||||
list(GET PROJECT_VERSION_PARTS 2 PROJECT_VERSION_PATCH)
|
||||
set(PROJECT_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||
|
||||
#------------------------------------------------------
|
||||
# Build type
|
||||
#------------------------------------------------------
|
||||
|
||||
IF(NOT CMAKE_BUILD_TYPE )
|
||||
SET( CMAKE_BUILD_TYPE "Release" )
|
||||
ENDIF()
|
||||
|
||||
#------------------------------------------------------
|
||||
# Lib Names and Dirs
|
||||
#------------------------------------------------------
|
||||
|
||||
# Postfix of so's:
|
||||
set(PROJECT_DLLVERSION)
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_INSTALL_PREFIX}/lib/cmake/ /usr/lib/cmake)
|
||||
|
||||
OPTION(BUILD_SHARED_LIBS "Set to OFF to build static libraries" ON)
|
||||
OPTION(BUILD_UTILS "Acitvates/Deactivates building utils libraries" ON)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Find Dependencies
|
||||
# ----------------------------------------------------------------------------
|
||||
#Add include to dependencies dir
|
||||
include_directories(${PROJECT_SOURCE_DIR}/dependencies ${PROJECT_SOURCE_DIR}/dependencies/mmal ${PROJECT_SOURCE_DIR}/dependencies/vcos)
|
||||
#find the mmal libraries(I use conditional because I normally comile in pc)
|
||||
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES arm*)
|
||||
FIND_LIBRARY(mmalcore_LIBS NAMES mmal_core PATHS /opt/vc/lib)
|
||||
FIND_LIBRARY(mmalutil_LIBS NAMES mmal_util PATHS /opt/vc/lib)
|
||||
FIND_LIBRARY(mmal_LIBS NAMES mmal PATHS /opt/vc/lib)
|
||||
IF( (NOT mmal_LIBS ) OR (NOT mmalutil_LIBS) OR (NOT mmalcore_LIBS) )
|
||||
MESSAGE(FATAL_ERROR "Could not find mmal libraries")
|
||||
ENDIF()
|
||||
set(REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} ${mmalcore_LIBS} ${mmalutil_LIBS} ${mmal_LIBS} )
|
||||
ENDIF()
|
||||
|
||||
#If opencv installed, creates the libraspicam_cv library module
|
||||
FIND_PACKAGE(OpenCV)
|
||||
IF(OpenCV_FOUND)
|
||||
include_directories(${OpenCV_INCLUDE_DIRS})
|
||||
SET(LIB_COMPONENTS ${LIB_COMPONENTS} ${PROJECT_NAME}_cv)
|
||||
SET(PROJECT_CV_CREATED_FLAG "YES")
|
||||
ENDIF()
|
||||
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# PROJECT CONFIGURATION
|
||||
# force some variables that could be defined in the command line to be written to cache
|
||||
# ----------------------------------------------------------------------------
|
||||
OPTION(INSTALL_DOC "Set to ON to build/install Documentation" OFF)
|
||||
IF (INSTALL_DOC)
|
||||
FIND_PACKAGE(Doxygen REQUIRED)
|
||||
MESSAGE( STATUS "INSTALL_DOC: ${INSTALL_DOC} ")
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/generateDoc.cmake")
|
||||
GENERATE_DOCUMENTATION(${PROJECT_SOURCE_DIR}/dox.in)
|
||||
ENDIF()
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Uninstall target, for "make uninstall"
|
||||
# ----------------------------------------------------------------------------
|
||||
CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
|
||||
ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# create configuration file from .in file (If you use windows take care with paths)
|
||||
# ----------------------------------------------------------------------------
|
||||
CONFIGURE_FILE("${PROJECT_SOURCE_DIR}/config.cmake.in" "${PROJECT_BINARY_DIR}/Find${PROJECT_NAME}.cmake")
|
||||
CONFIGURE_FILE("${PROJECT_SOURCE_DIR}/config.cmake.in" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake")
|
||||
INSTALL(FILES "${PROJECT_BINARY_DIR}/Find${PROJECT_NAME}.cmake" DESTINATION lib/cmake/ )
|
||||
INSTALL(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" DESTINATION lib/cmake/ )
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Program Optimization and debug (Extracted from OpenCV)
|
||||
# ----------------------------------------------------------------------------
|
||||
set(WARNINGS_ARE_ERRORS OFF CACHE BOOL "Treat warnings as errors")
|
||||
set(WHOLE_PROGRAM_OPTIMIZATION OFF CACHE BOOL "Flags for whole program optimization.")
|
||||
set(EXTRA_C_FLAGS "")
|
||||
set(EXTRA_C_FLAGS_RELEASE "")
|
||||
set(EXTRA_C_FLAGS_DEBUG "")
|
||||
set(EXTRA_EXE_LINKER_FLAGS "")
|
||||
set(EXTRA_EXE_LINKER_FLAGS_RELEASE "")
|
||||
set(EXTRA_EXE_LINKER_FLAGS_DEBUG "")
|
||||
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX OR MINGW)
|
||||
set(ENABLE_PROFILING OFF CACHE BOOL "Enable profiling in the GCC compiler (Add flags: -g -pg)")
|
||||
set(USE_OMIT_FRAME_POINTER ON CACHE BOOL "Enable -fomit-frame-pointer for GCC")
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES arm*) # We can use only -O2 because the -O3 causes gcc crash
|
||||
set(USE_O2 ON CACHE BOOL "Enable -O2 for GCC")
|
||||
set(USE_FAST_MATH ON CACHE BOOL "Enable -ffast-math for GCC")
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES powerpc*)
|
||||
set(USE_O3 ON CACHE BOOL "Enable -O3 for GCC")
|
||||
set(USE_POWERPC ON CACHE BOOL "Enable PowerPC for GCC")
|
||||
endif ()
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES amd64* OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES x86_64*)
|
||||
set(USE_O3 ON CACHE BOOL "Enable -O3 for GCC")
|
||||
set(USE_FAST_MATH ON CACHE BOOL "Enable -ffast-math for GCC")
|
||||
set(USE_MMX ON CACHE BOOL "Enable MMX for GCC")
|
||||
set(USE_SSE ON CACHE BOOL "Enable SSE for GCC")
|
||||
set(USE_SSE2 ON CACHE BOOL "Enable SSE2 for GCC")
|
||||
set(USE_SSE3 ON CACHE BOOL "Enable SSE3 for GCC")
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES i686* OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES x86)
|
||||
set(USE_O3 ON CACHE BOOL "Enable -O3 for GCC")
|
||||
set(USE_FAST_MATH ON CACHE BOOL "Enable -ffast-math for GCC")
|
||||
set(USE_MMX ON CACHE BOOL "Enable MMX for GCC")
|
||||
set(USE_SSE OFF CACHE BOOL "Enable SSE for GCC")
|
||||
set(USE_SSE2 OFF CACHE BOOL "Enable SSE2 for GCC")
|
||||
set(USE_SSE3 OFF CACHE BOOL "Enable SSE3 for GCC")
|
||||
endif ()
|
||||
|
||||
set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -Wall")
|
||||
|
||||
if(WARNINGS_ARE_ERRORS)
|
||||
set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -Werror")
|
||||
endif()
|
||||
|
||||
# The -Wno-long-long is required in 64bit systems when including sytem headers.
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES x86_64* OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES amd64*)
|
||||
set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -Wno-long-long")
|
||||
endif()
|
||||
|
||||
# Whole program optimization
|
||||
if(WHOLE_PROGRAM_OPTIMIZATION)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -fwhole-program --combine")
|
||||
endif()
|
||||
|
||||
# Other optimizations
|
||||
if(USE_OMIT_FRAME_POINTER)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -fomit-frame-pointer")
|
||||
endif()
|
||||
if(USE_O2)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -O2")
|
||||
endif()
|
||||
if(USE_O3)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -O3")
|
||||
endif()
|
||||
if(USE_FAST_MATH)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -ffast-math")
|
||||
endif()
|
||||
if(USE_POWERPC)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -mcpu=G3 -mtune=G5")
|
||||
endif()
|
||||
if(USE_MMX)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -mmmx")
|
||||
endif()
|
||||
if(USE_SSE)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -msse")
|
||||
endif()
|
||||
if(USE_SSE2)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -msse2")
|
||||
endif()
|
||||
if(USE_SSE3 AND NOT MINGW) # SSE3 should be disabled under MingW because it generates compiler errors
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -msse3")
|
||||
endif()
|
||||
|
||||
if(ENABLE_PROFILING)
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -pg -g")
|
||||
else()
|
||||
if(NOT APPLE)
|
||||
set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -ffunction-sections")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Parallel mode
|
||||
if(ENABLE_OPENMP)
|
||||
set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -fopenmp")
|
||||
set(LINKER_LIBS ${LINKER_LIBS} gomp)
|
||||
endif()
|
||||
|
||||
set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -DNDEBUG")
|
||||
set(EXTRA_C_FLAGS_DEBUG "-g3 -O0 -DDEBUG -D_DEBUG -W -Wextra -Wno-return-type")
|
||||
|
||||
MESSAGE( STATUS "-------------------------------------------------------------------------------" )
|
||||
message( STATUS "GNU COMPILER")
|
||||
MESSAGE( STATUS "-------------------------------------------------------------------------------" )
|
||||
|
||||
ENDIF ()
|
||||
|
||||
IF(${CMAKE_SYSTEM_PROCESSOR} MATCHES armv6l ) ##BEAGLE BOARD
|
||||
SET(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -ftree-vectorize")
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic -Wall -Wno-variadic-macros -std=c++0x -Wl,--no-as-needed")#for using condition variables
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_C_FLAGS} ")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -lpthread")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${EXTRA_C_FLAGS_DEBUG} -lpthread")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EXTRA_EXE_LINKER_FLAGS}")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${EXTRA_EXE_LINKER_FLAGS_RELEASE}")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${EXTRA_EXE_LINKER_FLAGS_DEBUG}")
|
||||
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------
|
||||
# DIRS
|
||||
#------------------------------------------------
|
||||
ADD_SUBDIRECTORY(src)
|
||||
IF(BUILD_UTILS)
|
||||
ADD_SUBDIRECTORY(utils)
|
||||
ENDIF()
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# display status message for important variables
|
||||
# ----------------------------------------------------------------------------
|
||||
message( STATUS )
|
||||
MESSAGE( STATUS "-------------------------------------------------------------------------------" )
|
||||
message( STATUS "General configuration for ${PROJECT_NAME} ${PROJECT_VERSION}")
|
||||
MESSAGE( STATUS "-------------------------------------------------------------------------------" )
|
||||
message( STATUS )
|
||||
message(" Built as dynamic libs?:" ${BUILD_SHARED_LIBS})
|
||||
message(" Compiler:" "${CMAKE_COMPILER}" "${CMAKE_CXX_COMPILER}")
|
||||
message( STATUS "C++ flags (Release): ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
message( STATUS "C++ flags (Debug): ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
message( STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
|
||||
message( STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
|
||||
|
||||
MESSAGE( STATUS )
|
||||
MESSAGE( STATUS "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}" )
|
||||
MESSAGE( STATUS "BUILD_SHARED_LIBS = ${BUILD_SHARED_LIBS}" )
|
||||
MESSAGE( STATUS "BUILD_UTILS = ${BUILD_UTILS}" )
|
||||
|
||||
MESSAGE( STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}" )
|
||||
MESSAGE( STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}" )
|
||||
MESSAGE( STATUS "CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}" )
|
||||
|
||||
MESSAGE( STATUS )
|
||||
MESSAGE( STATUS "CREATE OPENCV MODULE=${OpenCV_FOUND}")
|
||||
MESSAGE( STATUS "CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
|
||||
MESSAGE( STATUS "REQUIRED_LIBRARIES=${REQUIRED_LIBRARIES}")
|
||||
MESSAGE( STATUS )
|
||||
MESSAGE( STATUS )
|
||||
MESSAGE( STATUS "Change a value with: cmake -D<Variable>=<Value>" )
|
||||
MESSAGE( STATUS )
|
33
Input/Externals/raspicam-master/Changelog
vendored
33
Input/Externals/raspicam-master/Changelog
vendored
@ -1,33 +0,0 @@
|
||||
0.1.3
|
||||
- Native support for BGR and RGB in opencv classes. No need to do conversion anymore.
|
||||
0.1.2
|
||||
- Solved deadlock error in grab
|
||||
0.1.1
|
||||
- Moved to c++11 mutex and condition_variables. Bug fixed that caused random dead lock condition in grab()
|
||||
0.1.0
|
||||
- Bug fixed in release for RapiCam and RaspiCam_Cv
|
||||
0.0.7
|
||||
- Added classes RaspiCam_Still and RaspiCam_Still_Cv for still camera mode
|
||||
0.0.6
|
||||
- Bug ins cv camera corrected
|
||||
0.0.5
|
||||
- getImageBuffeSize change by getImageBufferSize (sorry)
|
||||
- Change in capture format. Now, it is able to capture in RGB at high speed.
|
||||
- The second parameter of retrieve is now useless. Format must be specified in Raspicam::(set/get)Format before opening the camera and can not be change during operation.
|
||||
- RaspiCam_Cv captures in BGR, which is obtained by converting from RGB. Therefore, performance drops to half repect to the RaspiCam in RGB mode when using 1280x960.
|
||||
0.0.4
|
||||
- Added shutter speed camera control
|
||||
- OpenCv set/get params are now scaled to [0,100]
|
||||
- Added more command line options in test programs
|
||||
0.0.3
|
||||
- Fixed error in color conversion (rgb and bgr were swapped)
|
||||
- Added command line options in raspicam_test to adjust exposure
|
||||
- Changes in RaspiCam_Cv so that exposure can be adjusted. Very simply.
|
||||
0.0.2
|
||||
- Decoupled opening from the start of capture in RaspiCam if desired. RapiCam::open and RaspiCam::startCapture
|
||||
- Added function RaspiCam::getId and RaspiCam_Cv::getId
|
||||
- Added a new way to convert yuv2rgb which is a bit faster.Thanks to Stefan Gufman (gruffypuffy at gmail dot com)
|
||||
- Added command line option -test_speed to utils programs (do not save images to memory)
|
||||
- Removed useless code in private_impl
|
||||
0.0.1
|
||||
Initial libary
|
210
Input/Externals/raspicam-master/README
vendored
210
Input/Externals/raspicam-master/README
vendored
@ -1,210 +0,0 @@
|
||||
|
||||
This library allows to use the Raspberry Pi Camera.
|
||||
|
||||
* Main features:
|
||||
- Provides class RaspiCam for easy and full control of the camera
|
||||
- Provides class RaspiCam_Cv for easy control of the camera with OpenCV.
|
||||
- Provides class RaspiCam_Still and RaspiCam_Still_Cv for controlling the camera in still mode
|
||||
- Easy compilation/installation using cmake.
|
||||
- No need to install development file of userland. Implementation is hidden.
|
||||
- Many examples
|
||||
|
||||
* ChangeLog
|
||||
0.1.3
|
||||
- Native support for BGR and RGB in opencv classes. No need to do conversion anymore.
|
||||
0.1.2
|
||||
- Solved deadlock error in grab
|
||||
0.1.1
|
||||
- Moved to c++11 mutex and condition_variables. Bug fixed that caused random dead lock condition in grab()
|
||||
0.1.0
|
||||
- Bug fixed in release for RapiCam and RaspiCam_Cv
|
||||
0.0.7
|
||||
- Added classes RaspiCam_Still and RaspiCam_Still_Cv for still camera mode
|
||||
0.0.6
|
||||
- Bug ins cv camera corrected
|
||||
0.0.5
|
||||
- getImageBuffeSize change by getImageBufferSize (sorry)
|
||||
- Change in capture format. Now, it is able to capture in RGB at high speed.
|
||||
- The second parameter of retrieve is now useless. Format must be specified in Raspicam::(set/get)Format before opening the camera and can not be change during operation.
|
||||
- RaspiCam_Cv captures in BGR, which is obtained by converting from RGB. Therefore, performance drops to half repect to the RaspiCam in RGB mode when using 1280x960.
|
||||
0.0.4
|
||||
- Added shutter speed camera control
|
||||
- OpenCv set/get params are now scaled to [0,100]
|
||||
- Added more command line options in test programs
|
||||
0.0.3
|
||||
- Fixed error in color conversion (rgb and bgr were swapped)
|
||||
- Added command line options in raspicam_test to adjust exposure
|
||||
- Changes in RaspiCam_Cv so that exposure can be adjusted. Very simply.
|
||||
0.0.2
|
||||
- Decoupled opening from the start of capture in RaspiCam if desired. RapiCam::open and RaspiCam::startCapture
|
||||
- Added function RaspiCam::getId and RaspiCam_Cv::getId
|
||||
- Added a new way to convert yuv2rgb which is a bit faster.Thanks to Stefan Gufman (gruffypuffy at gmail dot com)
|
||||
- Added command line option -test_speed to utils programs (do not save images to memory)
|
||||
- Removed useless code in private_impl
|
||||
|
||||
0.0.1
|
||||
Initial libary
|
||||
|
||||
|
||||
* Compiling
|
||||
|
||||
Download the file to your raspberry. Then, uncompress the file and compile
|
||||
|
||||
tar xvzf raspicamxx.tgz
|
||||
cd raspicamxx
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
|
||||
At this point you'll see something like
|
||||
-- CREATE OPENCV MODULE=1
|
||||
-- CMAKE_INSTALL_PREFIX=/usr/local
|
||||
-- REQUIRED_LIBRARIES=/opt/vc/lib/libmmal_core.so;/opt/vc/lib/libmmal_util.so;/opt/vc/lib/libmmal.so
|
||||
-- Change a value with: cmake -D<Variable>=<Value>
|
||||
--
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /home/pi/raspicam/trunk/build
|
||||
|
||||
If OpenCV development files are installed in your system, then you see
|
||||
-- CREATE OPENCV MODULE=1
|
||||
otherwise this option will be 0 and the opencv module of the library will not be compiled.
|
||||
|
||||
Finally compile and install
|
||||
make
|
||||
sudo make install
|
||||
|
||||
|
||||
After that, you have the programs raspicam_test and raspicam_cv_test (if opencv was enabled).
|
||||
Run the first program to check that compilation is ok.
|
||||
|
||||
You can check that the library has installed the header files under /usr/local/lib/raspicam , and the libraries in
|
||||
/usr/local/lib/libraspicam.so and /usr/local/lib/libraspicam_cv.so (if opencv support enabled)
|
||||
|
||||
* Using it in your projects
|
||||
|
||||
We provide a simple example to use the library. Create a directory for our own project.
|
||||
|
||||
First create a file with the name simpletest_raspicam.cpp and add the following code
|
||||
|
||||
/**
|
||||
*/
|
||||
#include <ctime>
|
||||
#include <unistd.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <raspicam/raspicam.h>
|
||||
using namespace std;
|
||||
|
||||
int main ( int argc,char **argv ) {
|
||||
raspicam::RaspiCam Camera; //Cmaera object
|
||||
//Open camera
|
||||
cout<<"Opening Camera..."<<endl;
|
||||
if ( !Camera.open()) {cerr<<"Error opening camera"<<endl;return -1;}
|
||||
//wait a while until camera stabilizes
|
||||
cout<<"Sleeping for 3 secs"<<endl;
|
||||
sleep(3);
|
||||
//capture
|
||||
Camera.grab();
|
||||
//allocate memory
|
||||
unsigned char *data=new unsigned char[ Camera.getImageTypeSize ( raspicam::RASPICAM_FORMAT_RGB )];
|
||||
//extract the image in rgb format
|
||||
Camera.retrieve ( data,raspicam::RASPICAM_FORMAT_RGB );//get camera image
|
||||
//save
|
||||
std::ofstream outFile ( "raspicam_image.ppm",std::ios::binary );
|
||||
outFile<<"P6\n"<<Camera.getWidth() <<" "<<Camera.getHeight() <<" 255\n";
|
||||
outFile.write ( ( char* ) data, Camera.getImageTypeSize ( raspicam::RASPICAM_FORMAT_RGB ) );
|
||||
cout<<"Image saved at raspicam_image.ppm"<<endl;
|
||||
//free resrources
|
||||
delete data;
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
|
||||
Now, create a file named CMakeLists.txt and add:
|
||||
#####################################
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
project (raspicam_test)
|
||||
set (CMAKE_MODULE_PATH "/usr/local/lib/cmake/${CMAKE_MODULE_PATH}")
|
||||
find_package(raspicam REQUIRED)
|
||||
add_executable (simpletest_raspicam simpletest_raspicam.cpp)
|
||||
target_link_libraries (simpletest_raspicam ${raspicam_LIBS})
|
||||
#####################################
|
||||
|
||||
Finally, create,compile and execute
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
./simpletest_raspicam
|
||||
|
||||
A more complete sample project is provided in SourceForge.
|
||||
|
||||
* OpenCV Interface
|
||||
|
||||
If the OpenCV is found when compiling the library, the libraspicam_cv.so module is created and the RaspiCam_Cv class available.
|
||||
Take a look at the examples in utils to see how to use the class. In addition, we show here how you can use the RaspiCam_Cv in your own project using cmake.
|
||||
|
||||
|
||||
First create a file with the name simpletest_raspicam_cv.cpp and add the following code
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <raspicam/raspicam_cv.h>
|
||||
using namespace std;
|
||||
|
||||
int main ( int argc,char **argv ) {
|
||||
|
||||
time_t timer_begin,timer_end;
|
||||
raspicam::RaspiCam_Cv Camera;
|
||||
cv::Mat image;
|
||||
int nCount=100;
|
||||
//set camera params
|
||||
Camera.set( CV_CAP_PROP_FORMAT, CV_8UC1 );
|
||||
//Open camera
|
||||
cout<<"Opening Camera..."<<endl;
|
||||
if (!Camera.open()) {cerr<<"Error opening the camera"<<endl;return -1;}
|
||||
//Start capture
|
||||
cout<<"Capturing "<<nCount<<" frames ...."<<endl;
|
||||
time ( &timer_begin );
|
||||
for ( int i=0; i<nCount; i++ ) {
|
||||
Camera.grab();
|
||||
Camera.retrieve ( image);
|
||||
if ( i%5==0 ) cout<<"\r captured "<<i<<" images"<<std::flush;
|
||||
}
|
||||
cout<<"Stop camera..."<<endl;
|
||||
Camera.release();
|
||||
//show time statistics
|
||||
time ( &timer_end ); /* get current time; same as: timer = time(NULL) */
|
||||
double secondsElapsed = difftime ( timer_end,timer_begin );
|
||||
cout<< secondsElapsed<<" seconds for "<< nCount<<" frames : FPS = "<< ( float ) ( ( float ) ( nCount ) /secondsElapsed ) <<endl;
|
||||
//save image
|
||||
cv::imwrite("raspicam_cv_image.jpg",image);
|
||||
cout<<"Image saved at raspicam_cv_image.jpg"<<endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Now, create a file named CMakeLists.txt and add:
|
||||
#####################################
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
project (raspicam_test)
|
||||
set (CMAKE_MODULE_PATH "/usr/local/lib/cmake/${CMAKE_MODULE_PATH}")
|
||||
find_package(raspicam REQUIRED)
|
||||
find_package(OpenCV)
|
||||
IF ( OpenCV_FOUND AND raspicam_CV_FOUND)
|
||||
MESSAGE(STATUS "COMPILING OPENCV TESTS")
|
||||
add_executable (simpletest_raspicam_cv simpletest_raspicam_cv.cpp)
|
||||
target_link_libraries (simpletest_raspicam_cv ${raspicam_CV_LIBS})
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR "OPENCV NOT FOUND IN YOUR SYSTEM")
|
||||
ENDIF()
|
||||
#####################################
|
||||
|
||||
Finally, create,compile and execute
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
./simpletest_raspicam_cv
|
||||
|
208
Input/Externals/raspicam-master/README.md
vendored
208
Input/Externals/raspicam-master/README.md
vendored
@ -1,208 +0,0 @@
|
||||
# RaspiCam: C++ API for using Raspberry camera (with OpenCV)
|
||||
|
||||
This library allows to use the Raspberry Pi Camera under BSD License.
|
||||
|
||||
The project is started by the AVA research group (rafael Muñoz Salinas; rmsalinas@uco.es) and is now maintained
|
||||
on this GIT repository by Cédric Verstraeten. Please note that is NOT the OFFICIAL repository of RaspiCam, these can be found [here](http://www.uco.es/investiga/grupos/ava/node/40).
|
||||
|
||||
This repository is used in the [Kerberos.io](https://github.com/kerberos-io) project.
|
||||
|
||||
## Release notes
|
||||
|
||||
Update 2014/03/04: version 0.1.1 released Download at SourceForge
|
||||
Main feaure in 0.0.7 : Still camera API. You can now use the still mode for high resolution (includes OpenCv interface). See examples for more info.
|
||||
|
||||
Notes:
|
||||
Requires to update the firmware to use shutterspeed (sudo rpi-update)
|
||||
|
||||
Main features
|
||||
- Provides class RaspiCam for easy and full control of the camera
|
||||
- Provides class RaspiCam_Still and RaspiCam_Still_Cv for controlling the camera in still mode
|
||||
- Provides class RaspiCam_Cv for easy control of the camera with OpenCV.
|
||||
- Provides class RaspiCam_Still and RaspiCam_Still_Cv for controlling the camera in still mode
|
||||
- Provides class RaspiCam_Still and RaspiCam_Still_Cv for using the still camera mode
|
||||
- Easy compilation/installation using cmake.
|
||||
- No need to install development file of userland. Implementation is hidden.
|
||||
- Many examples
|
||||
|
||||
Performance
|
||||
Following, we show the capture performance of the library (measured capturing 600 frames).
|
||||
Gray and YUV420 Mode
|
||||
- 1280x960: 29.5fps, 640x480 : 29.5fps, 320x240 : 29.5fps
|
||||
RGB Mode
|
||||
- 1280x960: 28 fps, 640x480 : 29.29fps, 320x240 : 29.24fps
|
||||
BGR Mode
|
||||
- 1280x960: 14 fps, 640x480 : 29.29fps, 320x240 : 29.24fps
|
||||
|
||||
Note: when using the full resolution video callbacks with the full resolution of the Raspberry Pi Camera v2, you will likely get an error such as `mmal: mmal_vc_port_enable: failed to enable port vc.ril.camera:out:1(BGR3): ENOSPC`. In order to fix this increase your GPU memory to at least 256MB.
|
||||
|
||||
Color conversion is the most time consuming part. We still need to improve that part. Go to src/private and check if you can contribute!
|
||||
|
||||
Note: the library is compiled with the options: -Wall -ffunction-sections -fomit-frame-pointer -O2 -ffast-math -DNDEBUG -mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard -ftree-vectorize
|
||||
Note 2: the library is currently setting the camera in video mode. So, maximum resolution is 1280x960. I am working on the still port to enable higher resolutions.
|
||||
|
||||
## Compiling
|
||||
|
||||
Clone the repository to your raspberry. Then, uncompress the file and compile
|
||||
|
||||
git clone https://github.com/cedricve/raspicam.git
|
||||
cd raspicam
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
|
||||
At this point you'll see something like
|
||||
|
||||
-- CREATE OPENCV MODULE=1
|
||||
-- CMAKE_INSTALL_PREFIX=/usr/local
|
||||
-- REQUIRED_LIBRARIES=/opt/vc/lib/libmmal_core.so;/opt/vc/lib/libmmal_util.so;/opt/vc/lib/libmmal.so
|
||||
-- Change a value with: cmake -D<Variable>=<Value>
|
||||
--
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /home/pi/raspicam/trunk/build
|
||||
|
||||
If OpenCV development files are installed in your system, then you see following output; otherwise this option will be 0 and the opencv module of the library will not be compiled.
|
||||
|
||||
-- CREATE OPENCV MODULE=1
|
||||
|
||||
|
||||
Finally compile, install and update the ldconfig:
|
||||
|
||||
make
|
||||
sudo make install
|
||||
sudo ldconfig
|
||||
|
||||
After that, you have the programs raspicam_test and raspicam_cv_test (if opencv was enabled) in build/utils.
|
||||
Run the first program to check that compilation is ok.
|
||||
```
|
||||
sudo ./raspicam_test
|
||||
sudo ./raspicam_cv_test
|
||||
```
|
||||
|
||||
### Using it in your projects
|
||||
|
||||
You can learn how to use the library by taking a look at the examples in the utils directory and by analyzing the header files. In addition, we provide a some simple examples on how to use the library with cmake.
|
||||
First, create a directory for our own project. Then, go in and create a file with the name simpletest_raspicam.cpp and add the following code
|
||||
|
||||
/**
|
||||
*/
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <raspicam/raspicam.h>
|
||||
using namespace std;
|
||||
|
||||
int main ( int argc,char **argv ) {
|
||||
raspicam::RaspiCam Camera; //Camera object
|
||||
//Open camera
|
||||
cout<<"Opening Camera..."<<endl;
|
||||
if ( !Camera.open()) {cerr<<"Error opening camera"<<endl;return -1;}
|
||||
//wait a while until camera stabilizes
|
||||
cout<<"Sleeping for 3 secs"<<endl;
|
||||
sleep(3);
|
||||
//capture
|
||||
Camera.grab();
|
||||
//allocate memory
|
||||
unsigned char *data=new unsigned char[ Camera.getImageTypeSize ( raspicam::RASPICAM_FORMAT_RGB )];
|
||||
//extract the image in rgb format
|
||||
Camera.retrieve ( data,raspicam::RASPICAM_FORMAT_RGB );//get camera image
|
||||
//save
|
||||
std::ofstream outFile ( "raspicam_image.ppm",std::ios::binary );
|
||||
outFile<<"P6\n"<<Camera.getWidth() <<" "<<Camera.getHeight() <<" 255\n";
|
||||
outFile.write ( ( char* ) data, Camera.getImageTypeSize ( raspicam::RASPICAM_FORMAT_RGB ) );
|
||||
cout<<"Image saved at raspicam_image.ppm"<<endl;
|
||||
//free resrources
|
||||
delete data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
For cmake users, create a file named CMakeLists.txt and add:
|
||||
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
project (raspicam_test)
|
||||
find_package(raspicam REQUIRED)
|
||||
add_executable (simpletest_raspicam simpletest_raspicam.cpp)
|
||||
target_link_libraries (simpletest_raspicam ${raspicam_LIBS})
|
||||
|
||||
|
||||
Finally, create build dir,compile and execute
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
./simpletest_raspicam
|
||||
|
||||
If you do not like cmake, simply
|
||||
|
||||
g++ simpletest_raspicam.cpp -o simpletest_raspicam -I/usr/local/include -lraspicam -lmmal -lmmal_core -lmmal_util
|
||||
|
||||
### OpenCV Interface
|
||||
|
||||
If the OpenCV is found when compiling the library, the libraspicam_cv.so module is created and the RaspiCam_Cv class available. Take a look at the examples in utils to see how to use the class. In addition, we show here how you can use the RaspiCam_Cv in your own project using cmake.
|
||||
|
||||
First create a file with the name simpletest_raspicam_cv.cpp and add the following code
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <raspicam/raspicam_cv.h>
|
||||
using namespace std;
|
||||
|
||||
int main ( int argc,char **argv ) {
|
||||
|
||||
time_t timer_begin,timer_end;
|
||||
raspicam::RaspiCam_Cv Camera;
|
||||
cv::Mat image;
|
||||
int nCount=100;
|
||||
//set camera params
|
||||
Camera.set( CV_CAP_PROP_FORMAT, CV_8UC1 );
|
||||
//Open camera
|
||||
cout<<"Opening Camera..."<<endl;
|
||||
if (!Camera.open()) {cerr<<"Error opening the camera"<<endl;return -1;}
|
||||
//Start capture
|
||||
cout<<"Capturing "<<nCount<<" frames ...."<<endl;
|
||||
time ( &timer_begin );
|
||||
for ( int i=0; i<nCount; i++ ) {
|
||||
Camera.grab();
|
||||
Camera.retrieve ( image);
|
||||
if ( i%5==0 ) cout<<"\r captured "<<i<<" images"<<std::flush;
|
||||
}
|
||||
cout<<"Stop camera..."<<endl;
|
||||
Camera.release();
|
||||
//show time statistics
|
||||
time ( &timer_end ); /* get current time; same as: timer = time(NULL) */
|
||||
double secondsElapsed = difftime ( timer_end,timer_begin );
|
||||
cout<< secondsElapsed<<" seconds for "<< nCount<<" frames : FPS = "<< ( float ) ( ( float ) ( nCount ) /secondsElapsed ) <<endl;
|
||||
//save image
|
||||
cv::imwrite("raspicam_cv_image.jpg",image);
|
||||
cout<<"Image saved at raspicam_cv_image.jpg"<<endl;
|
||||
}
|
||||
|
||||
For cmake users, create a file named CMakeLists.txt and add:
|
||||
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
project (raspicam_test)
|
||||
find_package(raspicam REQUIRED)
|
||||
find_package(OpenCV)
|
||||
IF ( OpenCV_FOUND AND raspicam_CV_FOUND)
|
||||
MESSAGE(STATUS "COMPILING OPENCV TESTS")
|
||||
add_executable (simpletest_raspicam_cv simpletest_raspicam_cv.cpp)
|
||||
target_link_libraries (simpletest_raspicam_cv ${raspicam_CV_LIBS})
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR "OPENCV NOT FOUND IN YOUR SYSTEM")
|
||||
ENDIF()
|
||||
|
||||
Finally, create,compile and execute
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
./simpletest_raspicam_cv
|
||||
|
||||
|
||||
If you do not like cmake:
|
||||
|
||||
g++ simpletest_raspicam_cv.cpp -o simpletest_raspicam_cv -I/usr/local/include/ -lraspicam -lraspicam_cv -lmmal -lmmal_core -lmmal_util -lopencv_core -lopencv_highgui
|
||||
|
@ -1,28 +0,0 @@
|
||||
# -----------------------------------------------
|
||||
# File that provides "make uninstall" target
|
||||
# We use the file 'install_manifest.txt'
|
||||
# -----------------------------------------------
|
||||
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
|
||||
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
|
||||
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||
STRING(REGEX REPLACE "\n" ";" files "${files}")
|
||||
FOREACH(file ${files})
|
||||
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
|
||||
# IF(EXISTS "$ENV{DESTDIR}${file}")
|
||||
# EXEC_PROGRAM(
|
||||
# "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
# OUTPUT_VARIABLE rm_out
|
||||
# RETURN_VALUE rm_retval
|
||||
# )
|
||||
EXECUTE_PROCESS(COMMAND rm $ENV{DESTDIR}${file})
|
||||
# IF(NOT "${rm_retval}" STREQUAL 0)
|
||||
# MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
|
||||
# ENDIF(NOT "${rm_retval}" STREQUAL 0)
|
||||
# ELSE(EXISTS "$ENV{DESTDIR}${file}")
|
||||
# MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
|
||||
# ENDIF(EXISTS "$ENV{DESTDIR}${file}")
|
||||
ENDFOREACH(file)
|
||||
|
||||
|
34
Input/Externals/raspicam-master/config.cmake.in
vendored
34
Input/Externals/raspicam-master/config.cmake.in
vendored
@ -1,34 +0,0 @@
|
||||
# ===================================================================================
|
||||
# @PROJECT_NAME@ CMake configuration file
|
||||
#
|
||||
# ** File generated automatically, do not modify **
|
||||
#
|
||||
# Usage from an external project:
|
||||
# In your CMakeLists.txt, add these lines:
|
||||
#
|
||||
# FIND_PACKAGE(@PROJECT_NAME@ REQUIRED )
|
||||
# TARGET_LINK_LIBRARIES(MY_TARGET_NAME ${@PROJECT_NAME@_LIBS})
|
||||
#
|
||||
# This file will define the following variables:
|
||||
# - @PROJECT_NAME@_LIBS : The list of libraries to links against.
|
||||
# - @PROJECT_NAME@_LIB_DIR : The directory where lib files are. Calling LINK_DIRECTORIES
|
||||
# with this path is NOT needed.
|
||||
# - @PROJECT_NAME@_VERSION : The version of this PROJECT_NAME build. Example: "1.2.0"
|
||||
# - @PROJECT_NAME@_VERSION_MAJOR : Major version part of VERSION. Example: "1"
|
||||
# - @PROJECT_NAME@_VERSION_MINOR : Minor version part of VERSION. Example: "2"
|
||||
# - @PROJECT_NAME@_VERSION_PATCH : Patch version part of VERSION. Example: "0"
|
||||
#
|
||||
# ===================================================================================
|
||||
INCLUDE_DIRECTORIES(@REQUIRED_INC_DIR@;@CMAKE_INSTALL_PREFIX@/include)
|
||||
LINK_DIRECTORIES("@CMAKE_INSTALL_PREFIX@/lib")
|
||||
|
||||
SET(@PROJECT_NAME@_LIBS @REQUIRED_LIBRARIES@ @PROJECT_NAME@@PROJECT_DLLVERSION@)
|
||||
SET(@PROJECT_NAME@_FOUND "YES")
|
||||
|
||||
SET(@PROJECT_NAME@_CV_FOUND "@PROJECT_CV_CREATED_FLAG@")
|
||||
SET(@PROJECT_NAME@_CV_LIBS @REQUIRED_LIBRARIES@ @PROJECT_NAME@@PROJECT_DLLVERSION@ @OpenCV_LIBS@ @PROJECT_NAME@_cv@PROJECT_DLLVERSION@)
|
||||
|
||||
SET(@PROJECT_NAME@_VERSION @PROJECT_VERSION@)
|
||||
SET(@PROJECT_NAME@_VERSION_MAJOR @PROJECT_VERSION_MAJOR@)
|
||||
SET(@PROJECT_NAME@_VERSION_MINOR @PROJECT_VERSION_MINOR@)
|
||||
SET(@PROJECT_NAME@_VERSION_PATCH @PROJECT_VERSION_PATCH@)
|
@ -1,46 +0,0 @@
|
||||
# We support building both static and shared libraries
|
||||
if (NOT DEFINED LIBRARY_TYPE)
|
||||
set(LIBRARY_TYPE SHARED)
|
||||
endif (NOT DEFINED LIBRARY_TYPE)
|
||||
|
||||
add_definitions(-Wall -Werror)
|
||||
|
||||
add_library(mmal SHARED util/mmal_util.c)
|
||||
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(util)
|
||||
add_subdirectory(vc)
|
||||
add_subdirectory(components)
|
||||
add_subdirectory(openmaxil)
|
||||
add_subdirectory(client)
|
||||
|
||||
target_link_libraries(mmal mmal_core mmal_util mmal_vc_client vcos mmal_components)
|
||||
|
||||
install(TARGETS mmal DESTINATION lib)
|
||||
install(FILES
|
||||
mmal.h
|
||||
mmal_buffer.h
|
||||
mmal_clock.h
|
||||
mmal_common.h
|
||||
mmal_component.h
|
||||
mmal_encodings.h
|
||||
mmal_events.h
|
||||
mmal_format.h
|
||||
mmal_logging.h
|
||||
mmal_metadata.h
|
||||
mmal_parameters.h
|
||||
mmal_parameters_audio.h
|
||||
mmal_parameters_camera.h
|
||||
mmal_parameters_clock.h
|
||||
mmal_parameters_common.h
|
||||
mmal_parameters_video.h
|
||||
mmal_pool.h mmal_port.h
|
||||
mmal_queue.h
|
||||
mmal_types.h
|
||||
DESTINATION include/interface/mmal
|
||||
)
|
||||
|
||||
# Test apps
|
||||
if(BUILD_MMAL_APPS)
|
||||
add_subdirectory(test)
|
||||
endif(BUILD_MMAL_APPS)
|
@ -1 +0,0 @@
|
||||
add_subdirectory(brcmjpeg)
|
@ -1,6 +0,0 @@
|
||||
add_library(brcmjpeg SHARED brcmjpeg.c)
|
||||
target_link_libraries(brcmjpeg mmal_core mmal_util mmal_vc_client)
|
||||
|
||||
include_directories(../../../../host_applications/linux/libs/sm)
|
||||
add_executable(brcmjpeg_test brcmjpeg_test.c)
|
||||
target_link_libraries(brcmjpeg_test brcmjpeg vcsm vcos)
|
@ -1,914 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Jpeg encoder and decoder library using the hardware jpeg codec
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "util/mmal_component_wrapper.h"
|
||||
#include "util/mmal_util_params.h"
|
||||
#include "mmal_logging.h"
|
||||
#include "brcmjpeg.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Defines
|
||||
*******************************************************************************/
|
||||
#define MMAL_COMPONENT_IMAGE_DECODE "vc.aggregator.pipeline:ril.image_decode:video_convert"
|
||||
#define MMAL_COMPONENT_IMAGE_ENCODE "vc.ril.image_encode"
|
||||
|
||||
#define ENABLE_SLICE_MODE 0
|
||||
|
||||
#define CHECK_MMAL_STATUS(status, jerr, msg, ...) \
|
||||
if (status != MMAL_SUCCESS) {LOG_ERROR(msg, ## __VA_ARGS__); \
|
||||
err = BRCMJPEG_ERROR_##jerr; goto error;}
|
||||
|
||||
/*******************************************************************************
|
||||
* Type definitions
|
||||
*******************************************************************************/
|
||||
struct BRCMJPEG_T
|
||||
{
|
||||
BRCMJPEG_TYPE_T type;
|
||||
unsigned int ref_count;
|
||||
unsigned int init;
|
||||
|
||||
MMAL_WRAPPER_T *mmal;
|
||||
unsigned int slice_height;
|
||||
|
||||
VCOS_MUTEX_T lock;
|
||||
VCOS_MUTEX_T process_lock;
|
||||
VCOS_SEMAPHORE_T sema;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Local prototypes
|
||||
*******************************************************************************/
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_init_encoder(BRCMJPEG_T *);
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_init_decoder(BRCMJPEG_T *);
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_configure_encoder(BRCMJPEG_T *, BRCMJPEG_REQUEST_T *);
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_configure_decoder(BRCMJPEG_T *, BRCMJPEG_REQUEST_T *);
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_encode(BRCMJPEG_T *, BRCMJPEG_REQUEST_T *);
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_decode(BRCMJPEG_T *, BRCMJPEG_REQUEST_T *);
|
||||
static void brcmjpeg_destroy(BRCMJPEG_T *);
|
||||
|
||||
static MMAL_FOURCC_T brcmjpeg_pixfmt_to_encoding(BRCMJPEG_PIXEL_FORMAT_T);
|
||||
static unsigned int brcmjpeg_copy_pixels(uint8_t *out, unsigned int out_size,
|
||||
const uint8_t *in, unsigned int in_size, BRCMJPEG_PIXEL_FORMAT_T fmt,
|
||||
unsigned int out_width, unsigned int out_height,
|
||||
unsigned int in_width, unsigned int in_height,
|
||||
unsigned int line_offset, unsigned int convert_from);
|
||||
|
||||
static BRCMJPEG_T *brcmjpeg_encoder = NULL;
|
||||
static BRCMJPEG_T *brcmjpeg_decoder = NULL;
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform specific code
|
||||
*******************************************************************************/
|
||||
static VCOS_ONCE_T once = VCOS_ONCE_INIT;
|
||||
static VCOS_MUTEX_T brcmjpeg_lock;
|
||||
|
||||
static void brcmjpeg_init_once(void)
|
||||
{
|
||||
vcos_mutex_create(&brcmjpeg_lock, VCOS_FUNCTION);
|
||||
}
|
||||
|
||||
#define LOCK() vcos_mutex_lock(&brcmjpeg_lock)
|
||||
#define UNLOCK() vcos_mutex_unlock(&brcmjpeg_lock)
|
||||
#define LOCK_COMP(ctx) vcos_mutex_lock(&(ctx)->lock)
|
||||
#define UNLOCK_COMP(ctx) vcos_mutex_unlock(&(ctx)->lock)
|
||||
#define LOCK_PROCESS(ctx) vcos_mutex_lock(&(ctx)->process_lock)
|
||||
#define UNLOCK_PROCESS(ctx) vcos_mutex_unlock(&(ctx)->process_lock)
|
||||
#define WAIT(ctx) vcos_semaphore_wait(&(ctx)->sema)
|
||||
#define SIGNAL(ctx) vcos_semaphore_post(&(ctx)->sema)
|
||||
|
||||
/*******************************************************************************
|
||||
* Implementation
|
||||
*******************************************************************************/
|
||||
|
||||
BRCMJPEG_STATUS_T brcmjpeg_create(BRCMJPEG_TYPE_T type, BRCMJPEG_T **ctx)
|
||||
{
|
||||
BRCMJPEG_STATUS_T status = BRCMJPEG_SUCCESS;
|
||||
BRCMJPEG_T **comp;
|
||||
|
||||
if (type == BRCMJPEG_TYPE_ENCODER)
|
||||
comp = &brcmjpeg_encoder;
|
||||
else
|
||||
comp = &brcmjpeg_decoder;
|
||||
|
||||
vcos_once(&once, brcmjpeg_init_once);
|
||||
LOCK();
|
||||
if (!*comp)
|
||||
{
|
||||
int init1, init2, init3;
|
||||
*comp = calloc(sizeof(BRCMJPEG_T), 1);
|
||||
if (!*comp)
|
||||
{
|
||||
UNLOCK();
|
||||
return BRCMJPEG_ERROR_NOMEM;
|
||||
}
|
||||
(*comp)->type = type;
|
||||
init1 = vcos_mutex_create(&(*comp)->lock, "brcmjpeg lock") != VCOS_SUCCESS;
|
||||
init2 = vcos_mutex_create(&(*comp)->process_lock, "brcmjpeg process lock") != VCOS_SUCCESS;
|
||||
init3 = vcos_semaphore_create(&(*comp)->sema, "brcmjpeg sema", 0) != VCOS_SUCCESS;
|
||||
if (init1 | init2 | init3)
|
||||
{
|
||||
if (init1) vcos_mutex_delete(&(*comp)->lock);
|
||||
if (init2) vcos_mutex_delete(&(*comp)->process_lock);
|
||||
if (init3) vcos_semaphore_delete(&(*comp)->sema);
|
||||
free(comp);
|
||||
UNLOCK();
|
||||
return BRCMJPEG_ERROR_NOMEM;
|
||||
}
|
||||
}
|
||||
(*comp)->ref_count++;
|
||||
UNLOCK();
|
||||
|
||||
LOCK_COMP(*comp);
|
||||
if (!(*comp)->init)
|
||||
{
|
||||
if (type == BRCMJPEG_TYPE_ENCODER)
|
||||
status = brcmjpeg_init_encoder(*comp);
|
||||
else
|
||||
status = brcmjpeg_init_decoder(*comp);
|
||||
|
||||
(*comp)->init = status == BRCMJPEG_SUCCESS;
|
||||
}
|
||||
UNLOCK_COMP(*comp);
|
||||
|
||||
if (status != BRCMJPEG_SUCCESS)
|
||||
brcmjpeg_release(*comp);
|
||||
|
||||
*ctx = *comp;
|
||||
return status;
|
||||
}
|
||||
|
||||
void brcmjpeg_acquire(BRCMJPEG_T *ctx)
|
||||
{
|
||||
LOCK_COMP(ctx);
|
||||
ctx->ref_count++;
|
||||
UNLOCK_COMP(ctx);
|
||||
}
|
||||
|
||||
void brcmjpeg_release(BRCMJPEG_T *ctx)
|
||||
{
|
||||
LOCK_COMP(ctx);
|
||||
if (--ctx->ref_count)
|
||||
{
|
||||
UNLOCK_COMP(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK();
|
||||
if (ctx->type == BRCMJPEG_TYPE_ENCODER)
|
||||
brcmjpeg_encoder = NULL;
|
||||
else
|
||||
brcmjpeg_decoder = NULL;
|
||||
UNLOCK();
|
||||
UNLOCK_COMP(ctx);
|
||||
|
||||
brcmjpeg_destroy(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
BRCMJPEG_STATUS_T brcmjpeg_process(BRCMJPEG_T *ctx, BRCMJPEG_REQUEST_T *req)
|
||||
{
|
||||
BRCMJPEG_STATUS_T status;
|
||||
|
||||
/* Sanity check */
|
||||
if ((req->input && req->input_handle) ||
|
||||
(req->output && req->output_handle))
|
||||
{
|
||||
LOG_ERROR("buffer pointer and handle both set (%p/%u %p/%u)",
|
||||
req->input, req->input_handle, req->output, req->output_handle);
|
||||
return BRCMJPEG_ERROR_REQUEST;
|
||||
}
|
||||
|
||||
LOCK_PROCESS(ctx);
|
||||
if (ctx->type == BRCMJPEG_TYPE_ENCODER)
|
||||
status = brcmjpeg_encode(ctx, req);
|
||||
else
|
||||
status = brcmjpeg_decode(ctx, req);
|
||||
UNLOCK_PROCESS(ctx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void brcmjpeg_destroy(BRCMJPEG_T *ctx)
|
||||
{
|
||||
if (ctx->mmal)
|
||||
mmal_wrapper_destroy(ctx->mmal);
|
||||
vcos_mutex_delete(&ctx->lock);
|
||||
vcos_mutex_delete(&ctx->process_lock);
|
||||
vcos_semaphore_delete(&ctx->sema);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static void brcmjpeg_mmal_cb(MMAL_WRAPPER_T *wrapper)
|
||||
{
|
||||
BRCMJPEG_T *ctx = wrapper->user_data;
|
||||
SIGNAL(ctx);
|
||||
}
|
||||
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_init_encoder(BRCMJPEG_T *ctx)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
BRCMJPEG_STATUS_T err = BRCMJPEG_SUCCESS;
|
||||
|
||||
/* Create encoder component */
|
||||
status = mmal_wrapper_create(&ctx->mmal, MMAL_COMPONENT_IMAGE_ENCODE);
|
||||
CHECK_MMAL_STATUS(status, INIT, "failed to create encoder");
|
||||
ctx->mmal->user_data = ctx;
|
||||
ctx->mmal->callback = brcmjpeg_mmal_cb;
|
||||
|
||||
/* Configure things that won't change from encode to encode */
|
||||
mmal_port_parameter_set_boolean(ctx->mmal->control,
|
||||
MMAL_PARAMETER_EXIF_DISABLE, MMAL_TRUE);
|
||||
|
||||
ctx->mmal->output[0]->format->encoding = MMAL_ENCODING_JPEG;
|
||||
status = mmal_port_format_commit(ctx->mmal->output[0]);
|
||||
CHECK_MMAL_STATUS(status, INIT, "failed to commit output port format");
|
||||
|
||||
ctx->mmal->output[0]->buffer_size = ctx->mmal->output[0]->buffer_size_min;
|
||||
ctx->mmal->output[0]->buffer_num = 3;
|
||||
status = mmal_wrapper_port_enable(ctx->mmal->output[0], 0);
|
||||
CHECK_MMAL_STATUS(status, INIT, "failed to enable output port");
|
||||
|
||||
LOG_DEBUG("encoder initialised (output chunk size %i)",
|
||||
ctx->mmal->output[0]->buffer_size);
|
||||
return BRCMJPEG_SUCCESS;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_init_decoder(BRCMJPEG_T *ctx)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
BRCMJPEG_STATUS_T err = BRCMJPEG_SUCCESS;
|
||||
|
||||
/* Create decoder component */
|
||||
status = mmal_wrapper_create(&ctx->mmal, MMAL_COMPONENT_IMAGE_DECODE);
|
||||
CHECK_MMAL_STATUS(status, INIT, "failed to create decoder");
|
||||
ctx->mmal->user_data = ctx;
|
||||
ctx->mmal->callback = brcmjpeg_mmal_cb;
|
||||
|
||||
/* Configure things that won't change from decode to decode */
|
||||
ctx->mmal->input[0]->format->encoding = MMAL_ENCODING_JPEG;
|
||||
status = mmal_port_format_commit(ctx->mmal->input[0]);
|
||||
CHECK_MMAL_STATUS(status, INIT, "failed to commit input port format");
|
||||
|
||||
ctx->mmal->input[0]->buffer_size = ctx->mmal->input[0]->buffer_size_min;
|
||||
ctx->mmal->input[0]->buffer_num = 3;
|
||||
status = mmal_wrapper_port_enable(ctx->mmal->input[0], 0);
|
||||
CHECK_MMAL_STATUS(status, INIT, "failed to enable input port");
|
||||
|
||||
LOG_DEBUG("decoder initialised (input chunk size %i)",
|
||||
ctx->mmal->input[0]->buffer_size);
|
||||
return BRCMJPEG_SUCCESS;
|
||||
|
||||
error:
|
||||
return BRCMJPEG_ERROR_INIT;
|
||||
}
|
||||
|
||||
/* Configuration which needs to be done on a per encode basis */
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_configure_encoder(BRCMJPEG_T *ctx,
|
||||
BRCMJPEG_REQUEST_T *req)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_SUCCESS;
|
||||
MMAL_FOURCC_T encoding = brcmjpeg_pixfmt_to_encoding(req->pixel_format);
|
||||
MMAL_PORT_T *port_in;
|
||||
BRCMJPEG_STATUS_T err = BRCMJPEG_SUCCESS;
|
||||
MMAL_BOOL_T slice_mode = MMAL_FALSE;
|
||||
|
||||
if (encoding == MMAL_ENCODING_UNKNOWN)
|
||||
status = MMAL_EINVAL;
|
||||
CHECK_MMAL_STATUS(status, INPUT_FORMAT, "format not supported (%i)",
|
||||
req->pixel_format);
|
||||
|
||||
if (!req->buffer_width)
|
||||
req->buffer_width = req->width;
|
||||
if (!req->buffer_height)
|
||||
req->buffer_height = req->height;
|
||||
if (req->buffer_width < req->width || req->buffer_height < req->height)
|
||||
status = MMAL_EINVAL;
|
||||
CHECK_MMAL_STATUS(status, INPUT_FORMAT, "invalid buffer width/height "
|
||||
"(%i<=%i %i<=%i)", req->buffer_width, req->width, req->buffer_height,
|
||||
req->height);
|
||||
|
||||
ctx->slice_height = 0;
|
||||
ctx->mmal->status = MMAL_SUCCESS;
|
||||
port_in = ctx->mmal->input[0];
|
||||
|
||||
/* The input port needs to be re-configured to take into account
|
||||
* the properties of the new frame to encode */
|
||||
if (port_in->is_enabled)
|
||||
{
|
||||
status = mmal_wrapper_port_disable(port_in);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to disable input port");
|
||||
}
|
||||
|
||||
port_in->format->encoding = encoding;
|
||||
port_in->format->es->video.width =
|
||||
port_in->format->es->video.crop.width = req->width;
|
||||
port_in->format->es->video.height =
|
||||
port_in->format->es->video.crop.height = req->height;
|
||||
port_in->buffer_num = 1;
|
||||
|
||||
if (!req->input_handle &&
|
||||
(port_in->format->encoding == MMAL_ENCODING_I420 ||
|
||||
port_in->format->encoding == MMAL_ENCODING_I422))
|
||||
{
|
||||
if (port_in->format->encoding == MMAL_ENCODING_I420)
|
||||
port_in->format->encoding = MMAL_ENCODING_I420_SLICE;
|
||||
else if (port_in->format->encoding == MMAL_ENCODING_I422)
|
||||
port_in->format->encoding = MMAL_ENCODING_I422_SLICE;
|
||||
slice_mode = MMAL_TRUE;
|
||||
port_in->buffer_num = 3;
|
||||
}
|
||||
|
||||
status = mmal_port_format_commit(port_in);
|
||||
CHECK_MMAL_STATUS(status, INPUT_FORMAT, "failed to commit input port format");
|
||||
|
||||
ctx->slice_height = slice_mode ? 16 : port_in->format->es->video.height;
|
||||
port_in->buffer_size = port_in->buffer_size_min;
|
||||
|
||||
if (req->input_handle)
|
||||
status = mmal_wrapper_port_enable(port_in, MMAL_WRAPPER_FLAG_PAYLOAD_USE_SHARED_MEMORY);
|
||||
else
|
||||
status = mmal_wrapper_port_enable(port_in, MMAL_WRAPPER_FLAG_PAYLOAD_ALLOCATE);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to enable input port");
|
||||
|
||||
mmal_port_parameter_set_uint32(ctx->mmal->output[0],
|
||||
MMAL_PARAMETER_JPEG_Q_FACTOR, req->quality);
|
||||
|
||||
if (!ctx->mmal->output[0]->is_enabled)
|
||||
{
|
||||
status = mmal_wrapper_port_enable(ctx->mmal->output[0], 0);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to enable output port");
|
||||
}
|
||||
|
||||
LOG_DEBUG("encoder configured (%4.4s:%ux%u|%ux%u slice: %u)",
|
||||
(char *)&port_in->format->encoding,
|
||||
port_in->format->es->video.crop.width, port_in->format->es->video.crop.height,
|
||||
port_in->format->es->video.width, port_in->format->es->video.height,
|
||||
ctx->slice_height);
|
||||
return BRCMJPEG_SUCCESS;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Configuration which needs to be done on a per decode basis */
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_configure_decoder(BRCMJPEG_T *ctx,
|
||||
BRCMJPEG_REQUEST_T *req)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_SUCCESS;
|
||||
MMAL_FOURCC_T encoding = brcmjpeg_pixfmt_to_encoding(req->pixel_format);
|
||||
MMAL_PORT_T *port_out;
|
||||
BRCMJPEG_STATUS_T err = BRCMJPEG_SUCCESS;
|
||||
|
||||
if (encoding != MMAL_ENCODING_I420 &&
|
||||
encoding != MMAL_ENCODING_I422 &&
|
||||
encoding != MMAL_ENCODING_RGBA)
|
||||
status = MMAL_EINVAL;
|
||||
CHECK_MMAL_STATUS(status, OUTPUT_FORMAT, "format not supported");
|
||||
|
||||
ctx->slice_height = 0;
|
||||
ctx->mmal->status = MMAL_SUCCESS;
|
||||
port_out = ctx->mmal->output[0];
|
||||
|
||||
/* The input port needs to be re-configured to take into account
|
||||
* the properties of the new frame to decode */
|
||||
if (port_out->is_enabled)
|
||||
{
|
||||
status = mmal_wrapper_port_disable(port_out);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to disable output port");
|
||||
}
|
||||
|
||||
/* We assume that we do not know the format of the new jpeg to be decoded
|
||||
* and configure the input port for autodetecting the new format */
|
||||
port_out->format->encoding = encoding;
|
||||
port_out->format->es->video.width =
|
||||
port_out->format->es->video.crop.width = 0;
|
||||
port_out->format->es->video.height =
|
||||
port_out->format->es->video.crop.height = 0;
|
||||
status = mmal_port_format_commit(port_out);
|
||||
CHECK_MMAL_STATUS(status, OUTPUT_FORMAT, "failed to commit output port format");
|
||||
|
||||
port_out->buffer_num = 1;
|
||||
if (req->output_handle)
|
||||
status = mmal_wrapper_port_enable(port_out, MMAL_WRAPPER_FLAG_PAYLOAD_USE_SHARED_MEMORY);
|
||||
else
|
||||
status = mmal_wrapper_port_enable(port_out, MMAL_WRAPPER_FLAG_PAYLOAD_ALLOCATE);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to enable output port");
|
||||
|
||||
LOG_DEBUG("decoder configured (%4.4s:%ux%u|%ux%u)", (char *)&port_out->format->encoding,
|
||||
port_out->format->es->video.crop.width, port_out->format->es->video.crop.height,
|
||||
port_out->format->es->video.width, port_out->format->es->video.height);
|
||||
return BRCMJPEG_SUCCESS;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_encode(BRCMJPEG_T *ctx,
|
||||
BRCMJPEG_REQUEST_T *je)
|
||||
{
|
||||
BRCMJPEG_STATUS_T err;
|
||||
MMAL_STATUS_T status = MMAL_SUCCESS;
|
||||
MMAL_BUFFER_HEADER_T *in, *out;
|
||||
MMAL_BOOL_T eos = MMAL_FALSE;
|
||||
const uint8_t *outBuf = je->output;
|
||||
unsigned int loop = 0, slices = 0, outBufSize = je->output_alloc_size;
|
||||
MMAL_PORT_T *port_in = ctx->mmal->input[0];
|
||||
MMAL_PORT_T *port_out = ctx->mmal->output[0];
|
||||
|
||||
je->output_size = 0;
|
||||
err = brcmjpeg_configure_encoder(ctx, je);
|
||||
if (err != BRCMJPEG_SUCCESS)
|
||||
return err;
|
||||
|
||||
/* Then we read the encoded data back from the encoder */
|
||||
|
||||
while (!eos && status == MMAL_SUCCESS)
|
||||
{
|
||||
/* send buffers to be filled */
|
||||
while (mmal_wrapper_buffer_get_empty(port_out, &out, 0) == MMAL_SUCCESS)
|
||||
{
|
||||
out->data = (uint8_t *)outBuf;
|
||||
out->alloc_size = MMAL_MIN(port_out->buffer_size, outBufSize);
|
||||
outBufSize -= out->alloc_size;
|
||||
outBuf += out->alloc_size;
|
||||
status = mmal_port_send_buffer(port_out, out);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to send buffer");
|
||||
}
|
||||
|
||||
/* Send slices to be encoded */
|
||||
if (slices * ctx->slice_height < port_in->format->es->video.height &&
|
||||
mmal_wrapper_buffer_get_empty(port_in, &in, 0) == MMAL_SUCCESS)
|
||||
{
|
||||
if (je->input_handle)
|
||||
{
|
||||
in->data = (uint8_t *)je->input_handle;
|
||||
in->length = in->alloc_size = je->input_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
in->length = brcmjpeg_copy_pixels(in->data, in->alloc_size,
|
||||
je->input, je->input_size, je->pixel_format,
|
||||
port_in->format->es->video.width,
|
||||
ctx->slice_height, je->buffer_width, je->buffer_height,
|
||||
slices * ctx->slice_height, 1);
|
||||
if (!in->length)
|
||||
status = MMAL_EINVAL;
|
||||
CHECK_MMAL_STATUS(status, INPUT_BUFFER, "input buffer too small");
|
||||
}
|
||||
|
||||
slices++;
|
||||
if (slices * ctx->slice_height >= port_in->format->es->video.height)
|
||||
in->flags = MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
status = mmal_port_send_buffer(port_in, in);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to send buffer");
|
||||
}
|
||||
|
||||
status = mmal_wrapper_buffer_get_full(port_out, &out, 0);
|
||||
if (status == MMAL_EAGAIN)
|
||||
{
|
||||
status = MMAL_SUCCESS;
|
||||
WAIT(ctx);
|
||||
continue;
|
||||
}
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to get full buffer");
|
||||
|
||||
LOG_DEBUG("received %i bytes", out->length);
|
||||
je->output_size += out->length;
|
||||
eos = out->flags & MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
|
||||
/* Detect when the encoder is running out of space for its output */
|
||||
if (++loop >= port_out->buffer_num && !eos && !out->length)
|
||||
{
|
||||
LOG_ERROR("no more output space for encoder");
|
||||
status = MMAL_EINVAL;
|
||||
}
|
||||
|
||||
mmal_buffer_header_release(out);
|
||||
}
|
||||
|
||||
/* Check if buffer was too small */
|
||||
CHECK_MMAL_STATUS(status, OUTPUT_BUFFER, "output buffer too small");
|
||||
|
||||
LOG_DEBUG("encoded W:%ixH:%i:%i (%i bytes) in %i slices",
|
||||
je->width, je->height, je->pixel_format, je->output_size, slices);
|
||||
mmal_port_flush(port_out);
|
||||
return BRCMJPEG_SUCCESS;
|
||||
|
||||
error:
|
||||
mmal_wrapper_port_disable(port_in);
|
||||
mmal_wrapper_port_disable(port_out);
|
||||
return err;
|
||||
}
|
||||
|
||||
static BRCMJPEG_STATUS_T brcmjpeg_decode(BRCMJPEG_T *ctx,
|
||||
BRCMJPEG_REQUEST_T *jd)
|
||||
{
|
||||
BRCMJPEG_STATUS_T err;
|
||||
MMAL_STATUS_T status;
|
||||
MMAL_BUFFER_HEADER_T *in, *out;
|
||||
MMAL_BOOL_T eos = MMAL_FALSE;
|
||||
const uint8_t *inBuf = jd->input;
|
||||
unsigned int slices = 0, inBufSize = jd->input_size;
|
||||
MMAL_PORT_T *port_in = ctx->mmal->input[0];
|
||||
MMAL_PORT_T *port_out = ctx->mmal->output[0];
|
||||
LOG_DEBUG("decode %i bytes", jd->input_size);
|
||||
|
||||
jd->output_size = 0;
|
||||
err = brcmjpeg_configure_decoder(ctx, jd);
|
||||
if (err != BRCMJPEG_SUCCESS)
|
||||
return err;
|
||||
|
||||
while (!eos)
|
||||
{
|
||||
/* Send as many chunks of data to decode as we can */
|
||||
while (inBufSize)
|
||||
{
|
||||
status = mmal_wrapper_buffer_get_empty(port_in, &in, 0);
|
||||
if (status == MMAL_EAGAIN)
|
||||
break;
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to get empty buffer (%i)", status);
|
||||
|
||||
in->data = (uint8_t *)inBuf;
|
||||
in->length = MMAL_MIN(port_in->buffer_size, inBufSize);
|
||||
in->alloc_size = in->length;
|
||||
inBufSize -= in->length;
|
||||
inBuf += in->length;
|
||||
in->flags = inBufSize ? 0 : MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
LOG_DEBUG("send decode in (%i bytes)", in->length);
|
||||
status = mmal_port_send_buffer(port_in, in);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to send input buffer");
|
||||
}
|
||||
|
||||
/* Check for decoded data */
|
||||
status = mmal_wrapper_buffer_get_full(port_out, &out, 0);
|
||||
if (status == MMAL_EAGAIN)
|
||||
{
|
||||
WAIT(ctx);
|
||||
continue;
|
||||
}
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "error decoding");
|
||||
|
||||
/* Check if a new format has been auto-detected by the decoder */
|
||||
if (out->cmd == MMAL_EVENT_FORMAT_CHANGED)
|
||||
{
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(out);
|
||||
|
||||
if (event)
|
||||
mmal_format_copy(port_out->format, event->format);
|
||||
mmal_buffer_header_release(out);
|
||||
|
||||
if (!event)
|
||||
status = MMAL_EINVAL;
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "invalid format change event");
|
||||
|
||||
LOG_DEBUG("new format (%4.4s:%ux%u|%ux%u)", (char *)&event->format->encoding,
|
||||
event->format->es->video.crop.width, event->format->es->video.crop.height,
|
||||
event->format->es->video.width, event->format->es->video.height);
|
||||
|
||||
/* re-setup the output port for the new format */
|
||||
status = mmal_wrapper_port_disable(port_out);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to disable output port");
|
||||
|
||||
ctx->slice_height = event->format->es->video.height;
|
||||
if (ENABLE_SLICE_MODE && !jd->output_handle)
|
||||
{
|
||||
/* setup slice mode */
|
||||
if (port_out->format->encoding == MMAL_ENCODING_I420 ||
|
||||
port_out->format->encoding == MMAL_ENCODING_I422)
|
||||
{
|
||||
if (port_out->format->encoding == MMAL_ENCODING_I420)
|
||||
port_out->format->encoding = MMAL_ENCODING_I420_SLICE;
|
||||
if (port_out->format->encoding == MMAL_ENCODING_I422)
|
||||
port_out->format->encoding = MMAL_ENCODING_I422_SLICE;
|
||||
ctx->slice_height = 16;
|
||||
port_out->buffer_num = 3;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("using slice size %u", ctx->slice_height);
|
||||
status = mmal_port_format_commit(port_out);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "invalid format change event");
|
||||
port_out->buffer_size = port_out->buffer_size_min;
|
||||
if (jd->output_handle)
|
||||
status = mmal_wrapper_port_enable(port_out, MMAL_WRAPPER_FLAG_PAYLOAD_USE_SHARED_MEMORY);
|
||||
else
|
||||
status = mmal_wrapper_port_enable(port_out, MMAL_WRAPPER_FLAG_PAYLOAD_ALLOCATE);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to enable output port");
|
||||
|
||||
/* send all our output buffers to the decoder */
|
||||
while (mmal_wrapper_buffer_get_empty(port_out, &out, 0) == MMAL_SUCCESS)
|
||||
{
|
||||
if (jd->output_handle)
|
||||
{
|
||||
out->data = (uint8_t*)jd->output_handle;
|
||||
out->alloc_size = jd->output_alloc_size;
|
||||
}
|
||||
status = mmal_port_send_buffer(port_out, out);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to send output buffer");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We have part of our output frame */
|
||||
jd->width = port_out->format->es->video.crop.width;
|
||||
if (!jd->width)
|
||||
jd->width = port_out->format->es->video.width;
|
||||
if (jd->output_handle)
|
||||
jd->buffer_width = port_out->format->es->video.width;
|
||||
if (!jd->buffer_width)
|
||||
jd->buffer_width = jd->width;
|
||||
jd->height = port_out->format->es->video.crop.height;
|
||||
if (!jd->height)
|
||||
jd->height = port_out->format->es->video.height;
|
||||
if (jd->output_handle)
|
||||
jd->buffer_height = port_out->format->es->video.height;
|
||||
if (!jd->buffer_height)
|
||||
jd->buffer_height = jd->height;
|
||||
|
||||
if (jd->output_handle)
|
||||
{
|
||||
jd->output_size += out->length;
|
||||
}
|
||||
else
|
||||
{
|
||||
jd->output_size = brcmjpeg_copy_pixels(jd->output, jd->output_alloc_size,
|
||||
out->data, out->length, jd->pixel_format,
|
||||
jd->buffer_width, jd->buffer_height,
|
||||
port_out->format->es->video.width,
|
||||
ctx->slice_height, slices * ctx->slice_height, 0);
|
||||
slices++;
|
||||
}
|
||||
|
||||
eos = out->flags & MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
out->length = 0;
|
||||
if (eos)
|
||||
{
|
||||
mmal_buffer_header_release(out);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = mmal_port_send_buffer(port_out, out);
|
||||
CHECK_MMAL_STATUS(status, EXECUTE, "failed to send output buffer");
|
||||
}
|
||||
|
||||
if (!jd->output_size)
|
||||
status = MMAL_EINVAL;
|
||||
CHECK_MMAL_STATUS(status, OUTPUT_BUFFER, "invalid output buffer");
|
||||
}
|
||||
|
||||
LOG_DEBUG("decoded W:%ixH%i:(W%ixH%i):%i in %i slices",
|
||||
jd->width, jd->height, jd->buffer_width, jd->buffer_height,
|
||||
jd->pixel_format, slices);
|
||||
mmal_port_flush(port_in);
|
||||
return BRCMJPEG_SUCCESS;
|
||||
|
||||
error:
|
||||
mmal_port_flush(port_in);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static struct {
|
||||
BRCMJPEG_PIXEL_FORMAT_T pixel_format;
|
||||
MMAL_FOURCC_T encoding;
|
||||
} mmal_raw_conversion[] = {
|
||||
{PIXEL_FORMAT_I420, MMAL_ENCODING_I420},
|
||||
{PIXEL_FORMAT_YV12, MMAL_ENCODING_I420},
|
||||
{PIXEL_FORMAT_I422, MMAL_ENCODING_I422},
|
||||
{PIXEL_FORMAT_YV16, MMAL_ENCODING_I422},
|
||||
{PIXEL_FORMAT_YUYV, MMAL_ENCODING_I422},
|
||||
{PIXEL_FORMAT_RGBA, MMAL_ENCODING_RGBA},
|
||||
{PIXEL_FORMAT_UNKNOWN, MMAL_ENCODING_UNKNOWN} };
|
||||
|
||||
static MMAL_FOURCC_T brcmjpeg_pixfmt_to_encoding(BRCMJPEG_PIXEL_FORMAT_T pixel_format)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; mmal_raw_conversion[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
|
||||
if (mmal_raw_conversion[i].pixel_format == pixel_format)
|
||||
break;
|
||||
return mmal_raw_conversion[i].encoding;
|
||||
}
|
||||
|
||||
// Copy a raw frame from 1 buffer to another, taking care of
|
||||
// stride / height differences between the input and output buffers.
|
||||
static unsigned int brcmjpeg_copy_pixels(uint8_t *out, unsigned int out_size,
|
||||
const uint8_t *in, unsigned int in_size, BRCMJPEG_PIXEL_FORMAT_T fmt,
|
||||
unsigned int out_width, unsigned int out_height,
|
||||
unsigned int in_width, unsigned int in_height,
|
||||
unsigned int line_offset, unsigned int convert_from)
|
||||
{
|
||||
struct {
|
||||
uint8_t *data;
|
||||
unsigned int pitch;
|
||||
unsigned int height;
|
||||
} planes[2][3];
|
||||
unsigned int num_planes = 0;
|
||||
unsigned int i, size = 0;
|
||||
unsigned int in_height_full = in_height;
|
||||
unsigned int out_height_full = out_height;
|
||||
unsigned int k = convert_from ? 1 : 0;
|
||||
|
||||
// Sanity check line_offset
|
||||
if (line_offset >= (convert_from ? in_height : out_height))
|
||||
return 0;
|
||||
|
||||
if (convert_from)
|
||||
in_height -= line_offset;
|
||||
else
|
||||
out_height -= line_offset;
|
||||
|
||||
if (fmt == PIXEL_FORMAT_I420 ||
|
||||
fmt == PIXEL_FORMAT_YV12)
|
||||
{
|
||||
planes[0][0].data = out;
|
||||
planes[0][0].pitch = out_width;
|
||||
planes[0][0].height = out_height;
|
||||
|
||||
planes[1][0].data = (uint8_t *)in;
|
||||
planes[1][0].pitch = in_width;
|
||||
planes[1][0].height = in_height;
|
||||
|
||||
planes[0][1].pitch = planes[0][2].pitch = out_width / 2;
|
||||
planes[0][1].height = planes[0][2].height = out_height / 2;
|
||||
planes[0][1].data = planes[0][0].data + out_width * out_height_full;
|
||||
planes[0][2].data = planes[0][1].data + out_width * out_height_full / 4;
|
||||
|
||||
planes[1][1].pitch = planes[1][2].pitch = in_width / 2;
|
||||
planes[1][1].height = planes[1][2].height = in_height / 2;
|
||||
planes[1][1].data = planes[1][0].data + in_width * in_height_full;
|
||||
planes[1][2].data = planes[1][1].data + in_width * in_height_full / 4;
|
||||
|
||||
if (fmt == PIXEL_FORMAT_YV12)
|
||||
{
|
||||
// We need to swap U and V
|
||||
uint8_t *tmp = planes[1][2].data;
|
||||
planes[1][2].data = planes[1][1].data;
|
||||
planes[1][1].data = tmp;
|
||||
}
|
||||
|
||||
// Add the line offset
|
||||
planes[k][0].data += planes[k][0].pitch * line_offset;
|
||||
planes[k][1].data += planes[k][1].pitch * line_offset/2;
|
||||
planes[k][2].data += planes[k][2].pitch * line_offset/2;
|
||||
|
||||
num_planes = 3;
|
||||
size = out_width * out_height_full * 3 / 2;
|
||||
|
||||
if (in_size < in_width * in_height * 3 / 2)
|
||||
return 0;
|
||||
|
||||
} else if (fmt == PIXEL_FORMAT_I422 ||
|
||||
fmt == PIXEL_FORMAT_YV16 ||
|
||||
fmt == PIXEL_FORMAT_YUYV)
|
||||
{
|
||||
planes[0][0].data = out;
|
||||
planes[0][0].pitch = out_width;
|
||||
planes[0][0].height = out_height;
|
||||
|
||||
planes[1][0].data = (uint8_t *)in;
|
||||
planes[1][0].pitch = in_width;
|
||||
planes[1][0].height = in_height;
|
||||
|
||||
planes[0][1].pitch = planes[0][2].pitch = out_width / 2;
|
||||
planes[0][1].height = planes[0][2].height = out_height;
|
||||
planes[0][1].data = planes[0][0].data + out_width * out_height_full;
|
||||
planes[0][2].data = planes[0][1].data + out_width * out_height_full / 2;
|
||||
|
||||
planes[1][1].pitch = planes[1][2].pitch = in_width / 2;
|
||||
planes[1][1].height = planes[1][2].height = in_height;
|
||||
planes[1][1].data = planes[1][0].data + in_width * in_height_full;
|
||||
planes[1][2].data = planes[1][1].data + in_width * in_height_full / 2;
|
||||
|
||||
// Add the line offset
|
||||
planes[k][0].data += planes[k][0].pitch * line_offset;
|
||||
planes[k][1].data += planes[k][1].pitch * line_offset;
|
||||
planes[k][2].data += planes[k][2].pitch * line_offset;
|
||||
if (fmt == PIXEL_FORMAT_YUYV)
|
||||
planes[k][0].data += planes[k][0].pitch * line_offset;
|
||||
|
||||
if (fmt == PIXEL_FORMAT_YV16)
|
||||
{
|
||||
// We need to swap U and V
|
||||
uint8_t *tmp = planes[1][2].data;
|
||||
planes[1][2].data = planes[1][1].data;
|
||||
planes[1][1].data = tmp;
|
||||
}
|
||||
|
||||
num_planes = 3;
|
||||
size = out_width * out_height_full * 2;
|
||||
|
||||
if (in_size < in_width * in_height * 2)
|
||||
return 0;
|
||||
} else if (fmt == PIXEL_FORMAT_RGBA)
|
||||
{
|
||||
planes[0][0].data = out;
|
||||
planes[0][0].pitch = out_width * 4;
|
||||
planes[0][0].height = out_height;
|
||||
|
||||
planes[1][0].data = (uint8_t *)in;
|
||||
planes[1][0].pitch = in_width * 4;
|
||||
planes[1][0].height = in_height;
|
||||
|
||||
// Add the line offset
|
||||
planes[k][0].data += planes[k][0].pitch * line_offset;
|
||||
|
||||
num_planes = 1;
|
||||
size = out_width * out_height_full * 4;
|
||||
|
||||
if (in_size < in_width * in_height * 4)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out_size < size)
|
||||
return 0;
|
||||
|
||||
// Special case for YUYV where don't just copy but convert to/from I422
|
||||
if (fmt == PIXEL_FORMAT_YUYV)
|
||||
{
|
||||
unsigned int width = in_width > out_width ? out_width : in_width;
|
||||
unsigned int height = in_height > out_height ? out_height : in_height;
|
||||
uint8_t *y = planes[convert_from ? 0 : 1][0].data;
|
||||
uint8_t *u = planes[convert_from ? 0 : 1][1].data;
|
||||
uint8_t *v = planes[convert_from ? 0 : 1][2].data;
|
||||
uint8_t *yuyv = planes[convert_from ? 1 : 0][0].data;
|
||||
unsigned int y_diff = (convert_from ? out_width : in_width) - width;
|
||||
unsigned int yuyv_diff = ((convert_from ? in_width : out_width) - width) * 2;
|
||||
|
||||
while (height--)
|
||||
{
|
||||
if (convert_from)
|
||||
for (i = width / 2; i; i--)
|
||||
{
|
||||
*y++ = *yuyv++;
|
||||
*u++ = *yuyv++;
|
||||
*y++ = *yuyv++;
|
||||
*v++ = *yuyv++;
|
||||
}
|
||||
else
|
||||
for (i = width / 2; i; i--)
|
||||
{
|
||||
*yuyv++ = *y++;
|
||||
*yuyv++ = *u++;
|
||||
*yuyv++ = *y++;
|
||||
*yuyv++ = *v++;
|
||||
}
|
||||
|
||||
yuyv += yuyv_diff;
|
||||
y += y_diff;
|
||||
u += y_diff >> 1;
|
||||
v += y_diff >> 1;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_planes; i++)
|
||||
{
|
||||
unsigned int width = MMAL_MIN(planes[0][i].pitch, planes[1][i].pitch);
|
||||
unsigned int height = MMAL_MIN(planes[0][i].height, planes[1][i].height);
|
||||
uint8_t *data_out = planes[0][i].data;
|
||||
uint8_t *data_in = planes[1][i].data;
|
||||
|
||||
while (height--)
|
||||
{
|
||||
memcpy(data_out, data_in, width);
|
||||
data_out += planes[0][i].pitch;
|
||||
data_in += planes[1][i].pitch;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Jpeg encoder and decoder library using the hardware jpeg codec
|
||||
*/
|
||||
|
||||
#ifndef BRCM_JPEG_H
|
||||
#define BRCM_JPEG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Status return codes from the API */
|
||||
typedef enum
|
||||
{
|
||||
BRCMJPEG_SUCCESS = 0,
|
||||
BRCMJPEG_ERROR_NOMEM,
|
||||
BRCMJPEG_ERROR_INIT,
|
||||
BRCMJPEG_ERROR_INPUT_FORMAT,
|
||||
BRCMJPEG_ERROR_OUTPUT_FORMAT,
|
||||
BRCMJPEG_ERROR_INPUT_BUFFER,
|
||||
BRCMJPEG_ERROR_OUTPUT_BUFFER,
|
||||
BRCMJPEG_ERROR_EXECUTE,
|
||||
BRCMJPEG_ERROR_REQUEST,
|
||||
} BRCMJPEG_STATUS_T;
|
||||
|
||||
/** Type of the codec instance to create */
|
||||
typedef enum
|
||||
{
|
||||
BRCMJPEG_TYPE_ENCODER = 0,
|
||||
BRCMJPEG_TYPE_DECODER
|
||||
} BRCMJPEG_TYPE_T;
|
||||
|
||||
/** Pixel formats supported by the codec */
|
||||
typedef enum
|
||||
{
|
||||
PIXEL_FORMAT_UNKNOWN = 0,
|
||||
PIXEL_FORMAT_I420, /* planar YUV 4:2:0 */
|
||||
PIXEL_FORMAT_YV12, /* planar YVU 4:2:0 */
|
||||
PIXEL_FORMAT_I422, /* planar YUV 4:2:2 */
|
||||
PIXEL_FORMAT_YV16, /* planar YVU 4:2:2 */
|
||||
PIXEL_FORMAT_YUYV, /* interleaved YUV 4:2:2 */
|
||||
PIXEL_FORMAT_RGBA, /* interleaved RGBA */
|
||||
} BRCMJPEG_PIXEL_FORMAT_T;
|
||||
|
||||
/** Definition of a codec request */
|
||||
typedef struct
|
||||
{
|
||||
/** Pointer to the buffer containing the input data
|
||||
* A client should set input OR input_handle, but not both. */
|
||||
const unsigned char *input;
|
||||
/** Actual size of the input data */
|
||||
unsigned int input_size;
|
||||
/** Handle to input buffer containing input data */
|
||||
unsigned int input_handle;
|
||||
|
||||
/** Pointer to the buffer used for the output data
|
||||
* A client should set output OR output_handle, but not both. */
|
||||
unsigned char *output;
|
||||
/** Total size of the output buffer */
|
||||
unsigned int output_alloc_size;
|
||||
/** Actual size of the output data (this is an output parameter) */
|
||||
unsigned int output_size;
|
||||
/** Handle to the buffer used for the output data */
|
||||
unsigned int output_handle;
|
||||
|
||||
/** Width of the raw frame (this is an input parameter for encode) */
|
||||
unsigned int width;
|
||||
/** Height of the raw frame (this is an input parameter for encode) */
|
||||
unsigned int height;
|
||||
/** Pixel format of the raw frame (this is an input parameter) */
|
||||
BRCMJPEG_PIXEL_FORMAT_T pixel_format;
|
||||
|
||||
/** Width of the buffer containing the raw frame (input parameter).
|
||||
* This is optional but if set, is used to specify the actual width
|
||||
* of the buffer containing the raw frame */
|
||||
unsigned int buffer_width;
|
||||
/** Height of the buffer containing the raw frame (input parameter).
|
||||
* This is optional but if set, is used to specify the actual height
|
||||
* of the buffer containing the raw frame */
|
||||
unsigned int buffer_height;
|
||||
|
||||
/** Encode quality - 0 to 100 */
|
||||
unsigned int quality;
|
||||
} BRCMJPEG_REQUEST_T;
|
||||
|
||||
/** Type of the codec instance */
|
||||
typedef struct BRCMJPEG_T BRCMJPEG_T;
|
||||
|
||||
/** Create an instance of the jpeg codec
|
||||
* This will actually re-use an existing instance if one is
|
||||
* available.
|
||||
*
|
||||
* @param type type of codec instance required
|
||||
* @param ctx will point to the newly created instance
|
||||
* @return BRCMJPEG_SUCCESS on success
|
||||
*/
|
||||
BRCMJPEG_STATUS_T brcmjpeg_create(BRCMJPEG_TYPE_T type, BRCMJPEG_T **ctx);
|
||||
|
||||
/** Acquire a new reference on a codec instance
|
||||
*
|
||||
* @param ctx instance to acquire a reference on
|
||||
*/
|
||||
void brcmjpeg_acquire(BRCMJPEG_T *ctx);
|
||||
|
||||
/** Release an instance of the jpeg codec
|
||||
* This will only trigger the destruction of the codec instance when
|
||||
* the last reference to it is being released.
|
||||
*
|
||||
* @param ctx instance to release
|
||||
*/
|
||||
void brcmjpeg_release(BRCMJPEG_T *ctx);
|
||||
|
||||
/** Process a jpeg codec request
|
||||
*
|
||||
* @param ctx instance of codec to use
|
||||
* @param request codec request to execute
|
||||
* @return BRCMJPEG_SUCCESS on success
|
||||
*/
|
||||
BRCMJPEG_STATUS_T brcmjpeg_process(BRCMJPEG_T *ctx, BRCMJPEG_REQUEST_T *request);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BRCM_JPEG_H */
|
@ -1,236 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "brcmjpeg.h"
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <user-vcsm.h>
|
||||
|
||||
#define MAX_WIDTH 5000
|
||||
#define MAX_HEIGHT 5000
|
||||
#define MAX_ENCODED (15*1024*1024)
|
||||
#define MAX_DECODED (MAX_WIDTH*MAX_HEIGHT*2)
|
||||
|
||||
static uint8_t encodedInBuf[MAX_ENCODED];
|
||||
static uint8_t encodedOutBuf[MAX_ENCODED];
|
||||
static uint8_t decodedBuf[MAX_DECODED];
|
||||
static char outFileName[2048];
|
||||
|
||||
int64_t get_time_microsec(void)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
return now.tv_sec * 1000000LL + now.tv_usec;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BRCMJPEG_STATUS_T status;
|
||||
BRCMJPEG_REQUEST_T enc_request, dec_request;
|
||||
BRCMJPEG_T *enc = 0, *dec = 0;
|
||||
int64_t start, stop, time_dec = 0, time_enc = 0;
|
||||
unsigned int count = 1, format = PIXEL_FORMAT_YUYV;
|
||||
unsigned int use_vcsm = 0, handle = 0, vc_handle = 0;
|
||||
int i, arg = 1, help = 0;
|
||||
|
||||
// Parse command line arguments
|
||||
while (arg < argc && argv[arg][0] == '-')
|
||||
{
|
||||
if (!strcmp(argv[arg], "-n"))
|
||||
{
|
||||
if (++arg >= argc || sscanf(argv[arg++], "%u", &count) != 1)
|
||||
arg = argc;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-f"))
|
||||
{
|
||||
if (++arg >= argc || sscanf(argv[arg++], "%u", &format) != 1)
|
||||
arg = argc;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-s"))
|
||||
{
|
||||
use_vcsm = 1;
|
||||
arg++;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-h"))
|
||||
{
|
||||
help = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = argc;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg == argc || help)
|
||||
{
|
||||
if (!help) fprintf(stderr, "invalid arguments\n");
|
||||
fprintf(stderr, "usage: %s [options] file1 ... fileN\n", argv[0]);
|
||||
fprintf(stderr, "options list:\n");
|
||||
fprintf(stderr, " -h : help\n");
|
||||
fprintf(stderr, " -n <N> : process each file N times\n");
|
||||
fprintf(stderr, " -f <N> : force color format\n");
|
||||
fprintf(stderr, " -s : use shared-memory for intermediate buffer\n");
|
||||
return !help;
|
||||
}
|
||||
|
||||
if (use_vcsm)
|
||||
{
|
||||
if (vcsm_init() < 0)
|
||||
{
|
||||
fprintf(stderr, "failed to initialise vcsm\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
handle = vcsm_malloc_cache(MAX_DECODED, VCSM_CACHE_TYPE_HOST, "brcmjpeg-test");
|
||||
if (!handle)
|
||||
{
|
||||
fprintf(stderr, "failed to alloc vcsm buffer\n");
|
||||
vcsm_exit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
vc_handle = vcsm_vc_hdl_from_hdl(handle);
|
||||
|
||||
fprintf(stderr, "decodedBuf handle %u vc_handle %u\n", handle, vc_handle);
|
||||
}
|
||||
|
||||
// Setup of the dec / enc requests
|
||||
memset(&enc_request, 0, sizeof(enc_request));
|
||||
memset(&dec_request, 0, sizeof(dec_request));
|
||||
dec_request.input = encodedInBuf;
|
||||
dec_request.output = use_vcsm ? NULL : decodedBuf;
|
||||
dec_request.output_handle = use_vcsm ? vc_handle : 0;
|
||||
dec_request.output_alloc_size = MAX_DECODED;
|
||||
enc_request.input = dec_request.output;
|
||||
enc_request.input_handle = dec_request.output_handle;
|
||||
enc_request.output = encodedOutBuf;
|
||||
enc_request.output_alloc_size = sizeof(encodedOutBuf);
|
||||
enc_request.quality = 75;
|
||||
enc_request.pixel_format = dec_request.pixel_format = format;
|
||||
|
||||
status = brcmjpeg_create(BRCMJPEG_TYPE_ENCODER, &enc);
|
||||
if (status != BRCMJPEG_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "could not create encoder\n");
|
||||
return 1;
|
||||
}
|
||||
status = brcmjpeg_create(BRCMJPEG_TYPE_DECODER, &dec);
|
||||
if (status != BRCMJPEG_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "could not create decoder\n");
|
||||
brcmjpeg_release(enc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = arg; i < argc; i++)
|
||||
{
|
||||
unsigned int j;
|
||||
fprintf(stderr, "processing %s\n", argv[i]);
|
||||
|
||||
FILE *file_in = fopen(argv[i], "rb");
|
||||
if (!file_in) {
|
||||
fprintf(stderr, "could not open file %s\n", argv[i]);
|
||||
continue;
|
||||
}
|
||||
snprintf(outFileName, sizeof(outFileName), "%s.out", argv[i]);
|
||||
FILE *file_out = fopen(outFileName, "wb+");
|
||||
if (!file_out) {
|
||||
fprintf(stderr, "could not open file %s\n", outFileName);
|
||||
fclose(file_in);
|
||||
continue;
|
||||
}
|
||||
dec_request.input_size = fread(encodedInBuf, 1, sizeof(encodedInBuf), file_in);
|
||||
|
||||
for (j = 0; j < count; j++)
|
||||
{
|
||||
dec_request.buffer_width = 0;
|
||||
dec_request.buffer_height = 0;
|
||||
|
||||
start = get_time_microsec();
|
||||
status = brcmjpeg_process(dec, &dec_request);
|
||||
stop = get_time_microsec();
|
||||
if (status != BRCMJPEG_SUCCESS) {
|
||||
fprintf(stderr, "could not decode %s\n", argv[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "decoded %ix%i(%ix%i), %i bytes in %lldus\n",
|
||||
dec_request.width, dec_request.height,
|
||||
dec_request.buffer_width, dec_request.buffer_height,
|
||||
dec_request.input_size, stop - start);
|
||||
time_dec += stop - start;
|
||||
|
||||
enc_request.input_size = dec_request.output_size;
|
||||
enc_request.width = dec_request.width;
|
||||
enc_request.height = dec_request.height;
|
||||
enc_request.buffer_width = dec_request.buffer_width;
|
||||
enc_request.buffer_height = dec_request.buffer_height;
|
||||
|
||||
start = get_time_microsec();
|
||||
status = brcmjpeg_process(enc, &enc_request);
|
||||
stop = get_time_microsec();
|
||||
if (status != BRCMJPEG_SUCCESS) {
|
||||
fprintf(stderr, "could not encode %s\n", outFileName);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "encoded %ix%i(%ix%i), %i bytes in %lldus\n",
|
||||
enc_request.width, enc_request.height,
|
||||
enc_request.buffer_width, enc_request.buffer_height,
|
||||
enc_request.output_size, stop - start);
|
||||
time_enc += stop - start;
|
||||
}
|
||||
|
||||
if (status != BRCMJPEG_SUCCESS)
|
||||
continue;
|
||||
|
||||
fwrite(enc_request.output, 1, enc_request.output_size, file_out);
|
||||
fclose(file_out);
|
||||
fclose(file_in);
|
||||
|
||||
fprintf(stderr, "decode times %lldus (%lldus per run)\n",
|
||||
time_dec, time_dec / count);
|
||||
fprintf(stderr, "encode times %lldus (%lldus per run)\n",
|
||||
time_enc, time_enc / count);
|
||||
}
|
||||
|
||||
brcmjpeg_release(dec);
|
||||
brcmjpeg_release(enc);
|
||||
|
||||
if (use_vcsm)
|
||||
{
|
||||
vcsm_free(handle);
|
||||
vcsm_exit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
add_library(mmal_components ${LIBRARY_TYPE}
|
||||
container_reader.c
|
||||
null_sink.c
|
||||
passthrough.c
|
||||
scheduler.c
|
||||
splitter.c
|
||||
copy.c
|
||||
artificial_camera.c
|
||||
aggregator.c
|
||||
clock.c
|
||||
spdif.c
|
||||
)
|
||||
|
||||
set(extra_components_SRCS avcodec_video_decoder.c avcodec_audio_decoder.c
|
||||
sdl_video_render.c sdl_audio_render.c aaf_audio_render.cpp android_media_codec.cpp)
|
||||
|
||||
#target_link_libraries(mmal_components avcodec avutil)
|
||||
#target_link_libraries(mmal_components SDL)
|
||||
#if (WIN32)
|
||||
#target_link_libraries(mmal_components avcore avutil z) # For avcodec
|
||||
#target_link_libraries(mmal_components gdi32 winmm) # For SDL
|
||||
#endif (WIN32)
|
||||
|
||||
add_custom_target(mmal_components_extra ALL
|
||||
COMMAND touch ${extra_components_SRCS}
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/interface/mmal/components)
|
||||
|
||||
set(container_libs ${container_libs} containers)
|
||||
|
||||
target_link_libraries(mmal_components ${container_libs} mmal_util)
|
||||
target_link_libraries(mmal_components mmal_core)
|
||||
|
||||
install(TARGETS mmal_components DESTINATION lib)
|
||||
|
@ -1,504 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "mmal_logging.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "core/mmal_clock_private.h"
|
||||
|
||||
#include <media/AudioTrack.h>
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
/* Buffering requirements */
|
||||
#define INPUT_MIN_BUFFER_NUM 4
|
||||
#define INPUT_RECOMMENDED_BUFFER_NUM 8
|
||||
|
||||
#define SPDIF_AC3_FRAME_SIZE 6144
|
||||
|
||||
/*****************************************************************************/
|
||||
enum TRACK_STATE_T {
|
||||
TRACK_STATE_STOPPED,
|
||||
TRACK_STATE_RUNNING,
|
||||
TRACK_STATE_PAUSED
|
||||
};
|
||||
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
MMAL_QUEUE_T *queue;
|
||||
|
||||
android::sp<android::AudioTrack> track;
|
||||
|
||||
Mutex *lock;
|
||||
uint32_t bytes_queued;
|
||||
|
||||
MMAL_BOOL_T is_enabled;
|
||||
TRACK_STATE_T state;
|
||||
|
||||
MMAL_ES_FORMAT_T *format; /**< format currently configured */
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void aaf_track_callback(int event, void *user, void *info);
|
||||
|
||||
static struct encoding_table_t {
|
||||
MMAL_FOURCC_T encoding;
|
||||
audio_format_t format;
|
||||
} encoding_list[] =
|
||||
{ {MMAL_ENCODING_PCM_SIGNED, AUDIO_FORMAT_PCM_16_BIT},
|
||||
#ifdef ANDROID_SUPPORTS_AC3
|
||||
{MMAL_ENCODING_AC3, AUDIO_FORMAT_AC3_SPDIF},
|
||||
{MMAL_ENCODING_EAC3, AUDIO_FORMAT_EAC3_SPDIF},
|
||||
#endif
|
||||
{0, AUDIO_FORMAT_INVALID}
|
||||
};
|
||||
|
||||
static audio_format_t encoding_to_audio_format(MMAL_FOURCC_T encoding)
|
||||
{
|
||||
struct encoding_table_t *entry = encoding_list;
|
||||
|
||||
for (entry = encoding_list; entry->encoding; entry++)
|
||||
if (entry->encoding == encoding)
|
||||
break;
|
||||
|
||||
return entry->format;
|
||||
}
|
||||
|
||||
static void aaf_track_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
if (module->track != NULL)
|
||||
{
|
||||
module->track->stop();
|
||||
module->track = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T aaf_track_create(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *port = component->input[0];
|
||||
audio_channel_mask_t channels_mask;
|
||||
int frame_count = 256;
|
||||
|
||||
/* Reset track on format change. Can do better than that? */
|
||||
if (module->track != NULL)
|
||||
aaf_track_destroy(component);
|
||||
|
||||
channels_mask = audio_channel_out_mask_from_count(port->format->es->audio.channels);
|
||||
LOG_INFO("%s(%p) %4.4s, %i Hz, mask %x, chan %i", port->name, port,
|
||||
(char *)&port->format->encoding,
|
||||
(int)port->format->es->audio.sample_rate, channels_mask,
|
||||
(int)port->format->es->audio.channels);
|
||||
|
||||
AudioTrack::getMinFrameCount(&frame_count);
|
||||
if (port->format->encoding == MMAL_ENCODING_AC3)
|
||||
frame_count = SPDIF_AC3_FRAME_SIZE;
|
||||
else if (port->format->encoding == MMAL_ENCODING_EAC3)
|
||||
frame_count = SPDIF_AC3_FRAME_SIZE * 4;
|
||||
frame_count *= 2; /* Twice the minimum should be enough */
|
||||
|
||||
module->track = new AudioTrack(AUDIO_STREAM_MUSIC,
|
||||
port->format->es->audio.sample_rate,
|
||||
encoding_to_audio_format(port->format->encoding), channels_mask,
|
||||
frame_count, port->format->encoding == MMAL_ENCODING_PCM_SIGNED ?
|
||||
AUDIO_OUTPUT_FLAG_NONE : AUDIO_OUTPUT_FLAG_DIRECT,
|
||||
&aaf_track_callback, port, 0);
|
||||
|
||||
if (module->track == NULL || module->track->initCheck() != OK)
|
||||
{
|
||||
LOG_ERROR("%s(%p): track creation failed", port->name, port);
|
||||
module->track = NULL;
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static void aaf_track_callback(int event, void *user, void *info)
|
||||
{
|
||||
MMAL_PORT_T *port = (MMAL_PORT_T *)user;
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
AudioTrack::Buffer *trackbuf = NULL;
|
||||
unsigned int bytes, space;
|
||||
uint8_t *dest;
|
||||
|
||||
if (event == AudioTrack::EVENT_UNDERRUN)
|
||||
LOG_ERROR("underrun");
|
||||
|
||||
if (event != AudioTrack::EVENT_MORE_DATA)
|
||||
return;
|
||||
|
||||
trackbuf = (AudioTrack::Buffer *)info;
|
||||
space = trackbuf->size;
|
||||
dest = (uint8_t *)trackbuf->raw;
|
||||
trackbuf->size = 0;
|
||||
|
||||
if (!mmal_queue_length(module->queue))
|
||||
{
|
||||
LOG_ERROR("no buffers queued");
|
||||
return;
|
||||
}
|
||||
|
||||
while (space > 0)
|
||||
{
|
||||
buffer = mmal_queue_get(module->queue);
|
||||
if (!buffer)
|
||||
break;
|
||||
|
||||
bytes = MMAL_MIN(buffer->length, space);
|
||||
memcpy(dest, buffer->data + buffer->offset, bytes);
|
||||
buffer->offset += bytes;
|
||||
buffer->length -= bytes;
|
||||
dest += bytes;
|
||||
space -= bytes;
|
||||
trackbuf->size += bytes;
|
||||
|
||||
if (buffer->length)
|
||||
{
|
||||
/* Re-queue */
|
||||
mmal_queue_put_back(module->queue, buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle the EOS */
|
||||
if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS)
|
||||
mmal_event_eos_send(port);
|
||||
|
||||
buffer->offset = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
}
|
||||
|
||||
module->lock->lock();
|
||||
module->bytes_queued -= trackbuf->size;
|
||||
module->lock->unlock();
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T aaf_track_state_update(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
TRACK_STATE_T new_state = TRACK_STATE_STOPPED;
|
||||
|
||||
if (module->track == NULL)
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
if (module->is_enabled)
|
||||
{
|
||||
MMAL_RATIONAL_T scale = mmal_port_clock_scale_get(component->clock[0]);
|
||||
new_state = TRACK_STATE_PAUSED;
|
||||
if (scale.den && scale.den == scale.num)
|
||||
new_state = TRACK_STATE_RUNNING;
|
||||
}
|
||||
|
||||
if (new_state == module->state)
|
||||
return MMAL_SUCCESS; /* Nothing to do */
|
||||
|
||||
if (module->state == TRACK_STATE_STOPPED && new_state == TRACK_STATE_RUNNING)
|
||||
{
|
||||
module->track->start();
|
||||
}
|
||||
else if (module->state == TRACK_STATE_RUNNING)
|
||||
{
|
||||
if (new_state == TRACK_STATE_STOPPED)
|
||||
module->track->stop();
|
||||
else if (new_state == TRACK_STATE_PAUSED)
|
||||
module->track->pause();
|
||||
}
|
||||
else if (module->state == TRACK_STATE_PAUSED)
|
||||
{
|
||||
if (new_state == TRACK_STATE_STOPPED)
|
||||
module->track->stop();
|
||||
else if (new_state == TRACK_STATE_RUNNING)
|
||||
module->track->start();
|
||||
}
|
||||
|
||||
module->state = new_state;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T aaf_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
aaf_track_destroy(component);
|
||||
|
||||
if(component->input_num)
|
||||
mmal_ports_free(component->input, component->input_num);
|
||||
if(component->clock_num)
|
||||
mmal_ports_clock_free(component->clock, component->clock_num);
|
||||
if(module->format)
|
||||
mmal_format_free(module->format);
|
||||
if(module->queue)
|
||||
mmal_queue_destroy(module->queue);
|
||||
delete module->lock;
|
||||
vcos_free(module);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T aaf_port_set_format(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
|
||||
if (!mmal_format_compare(port->format, component->priv->module->format))
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
/* Check the format is supported */
|
||||
if (encoding_to_audio_format(port->format->encoding) == AUDIO_FORMAT_INVALID)
|
||||
{
|
||||
LOG_ERROR("port does not support '%4.4s'", (char *)&port->format->encoding);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
/* Specific checks for PCM */
|
||||
if (port->format->encoding == MMAL_ENCODING_PCM_SIGNED)
|
||||
{
|
||||
|
||||
if (port->format->es->audio.bits_per_sample != 16 &&
|
||||
port->format->es->audio.bits_per_sample != 32)
|
||||
{
|
||||
LOG_ERROR("port does not support '%4.4s' at %ibps",
|
||||
(char *)&port->format->encoding,
|
||||
port->format->es->audio.bits_per_sample);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
if (!audio_channel_out_mask_from_count(port->format->es->audio.channels))
|
||||
{
|
||||
LOG_ERROR("%s invalid channels mask from %i", port->name,
|
||||
(int)port->format->es->audio.channels);
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
mmal_format_copy(component->priv->module->format, port->format);
|
||||
|
||||
return aaf_track_create(component);
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T aaf_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_STATUS_T status = MMAL_SUCCESS;
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
|
||||
if (module->track == NULL)
|
||||
status = aaf_port_set_format(port);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
module->is_enabled = MMAL_TRUE;
|
||||
aaf_track_state_update(component);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T aaf_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
while((buffer = mmal_queue_get(module->queue)))
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
|
||||
module->lock->lock();
|
||||
module->bytes_queued = 0;
|
||||
module->lock->unlock();
|
||||
|
||||
if (module->track == NULL)
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
module->track->stop();
|
||||
module->track->flush();
|
||||
module->state = TRACK_STATE_STOPPED;
|
||||
aaf_track_state_update(component);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T aaf_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
module->is_enabled = MMAL_FALSE;
|
||||
aaf_track_state_update(component);
|
||||
|
||||
return aaf_port_flush(port);
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T aaf_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
unsigned int bits_per_sample, channels, sample_rate;
|
||||
uint32_t aaf_bytes_queued = 0;
|
||||
int64_t latency, ts;
|
||||
|
||||
/* Handle event buffers */
|
||||
if (buffer->cmd)
|
||||
{
|
||||
LOG_ERROR("discarding event %i on port %p", (int)buffer->cmd, port);
|
||||
buffer->length = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
return module->status;
|
||||
|
||||
bits_per_sample = port->format->es->audio.bits_per_sample;
|
||||
channels = port->format->es->audio.channels;
|
||||
sample_rate = port->format->es->audio.sample_rate;
|
||||
|
||||
if (port->format->encoding == MMAL_ENCODING_AC3 ||
|
||||
port->format->encoding == MMAL_ENCODING_EAC3)
|
||||
{
|
||||
uint32_t aaf_latency = 0;
|
||||
AudioSystem::getOutputLatency(&aaf_latency, AUDIO_STREAM_MUSIC);
|
||||
latency = aaf_latency * 1000LL;
|
||||
|
||||
bits_per_sample = 16;
|
||||
channels = 2;
|
||||
if (port->format->encoding == MMAL_ENCODING_EAC3 &&
|
||||
sample_rate <= 48000)
|
||||
sample_rate *= 4;
|
||||
aaf_bytes_queued = module->track->frameCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
latency = module->track->latency() * 1000LL;
|
||||
}
|
||||
|
||||
/* Keep aaf_track_callback from sending more samples */
|
||||
module->lock->lock();
|
||||
|
||||
module->bytes_queued += buffer->length;
|
||||
latency += (module->bytes_queued + aaf_bytes_queued) / channels /
|
||||
(bits_per_sample / 8) * 1000000LL / sample_rate;
|
||||
ts = buffer->pts - latency;
|
||||
|
||||
module->lock->unlock();
|
||||
|
||||
mmal_port_clock_media_time_set(component->clock[0], ts);
|
||||
|
||||
mmal_queue_put(module->queue, buffer);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
void aaf_clock_event(MMAL_PORT_T *port, const MMAL_CLOCK_EVENT_T *event)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
|
||||
switch (event->id)
|
||||
{
|
||||
case MMAL_CLOCK_EVENT_SCALE:
|
||||
aaf_track_state_update(component);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_TIME:
|
||||
case MMAL_CLOCK_EVENT_REFERENCE:
|
||||
case MMAL_CLOCK_EVENT_ACTIVE:
|
||||
/* nothing to do */
|
||||
break;
|
||||
default:
|
||||
LOG_DEBUG("unknown event id %4.4s", (char*)&event->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_aaf(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
|
||||
/* Check we're the requested component */
|
||||
if(strcmp(name, "aaf." MMAL_AUDIO_RENDER))
|
||||
return MMAL_ENOENT;
|
||||
|
||||
/* Allocate our module context */
|
||||
component->priv->module = module = (MMAL_COMPONENT_MODULE_T *)vcos_calloc(1, sizeof(*module), "mmal module");
|
||||
if(!module)
|
||||
return MMAL_ENOMEM;
|
||||
module->lock = new Mutex();
|
||||
if (!module->lock)
|
||||
goto error;
|
||||
|
||||
/* Allocate the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, 0);
|
||||
if(!component->input)
|
||||
goto error;
|
||||
component->input_num = 1;
|
||||
|
||||
/* Create the clock port (clock ports are managed by the framework) */
|
||||
component->clock = mmal_ports_clock_alloc(component, 1, 0, aaf_clock_event);
|
||||
if (!component->clock)
|
||||
goto error;
|
||||
component->clock_num = 1;
|
||||
|
||||
module->queue = mmal_queue_create();
|
||||
if(!module->queue)
|
||||
goto error;
|
||||
|
||||
module->format = mmal_format_alloc();
|
||||
if(!module->format)
|
||||
goto error;
|
||||
|
||||
component->input[0]->priv->pf_set_format = aaf_port_set_format;
|
||||
component->input[0]->priv->pf_enable = aaf_port_enable;
|
||||
component->input[0]->priv->pf_disable = aaf_port_disable;
|
||||
component->input[0]->priv->pf_flush = aaf_port_flush;
|
||||
component->input[0]->priv->pf_send = aaf_port_send;
|
||||
component->input[0]->buffer_num_min = INPUT_MIN_BUFFER_NUM;
|
||||
component->input[0]->buffer_num_recommended = INPUT_RECOMMENDED_BUFFER_NUM;
|
||||
component->input[0]->format->type = MMAL_ES_TYPE_AUDIO;
|
||||
|
||||
component->priv->pf_destroy = aaf_component_destroy;
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
aaf_component_destroy(component);
|
||||
return MMAL_ENOMEM;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_aaf_audio);
|
||||
void mmal_register_component_aaf_audio(void)
|
||||
{
|
||||
mmal_component_supplier_register("aaf", mmal_component_create_aaf);
|
||||
}
|
@ -1,188 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "util/mmal_graph.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#define AGGREGATOR_PREFIX "aggregator"
|
||||
#define AGGREGATOR_PIPELINE_PREFIX "pipeline"
|
||||
|
||||
typedef struct MMAL_GRAPH_USERDATA_T {
|
||||
int dummy;
|
||||
} MMAL_GRAPH_USERDATA_T;
|
||||
|
||||
static MMAL_STATUS_T aggregator_parameter_set(MMAL_GRAPH_T *graph,
|
||||
MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(graph);
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(param);
|
||||
LOG_TRACE("graph %p, port %p, param %p", graph, port, param);
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T aggregator_parameter_get(MMAL_GRAPH_T *graph,
|
||||
MMAL_PORT_T *port, MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(graph);
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(param);
|
||||
LOG_TRACE("graph %p, port %p, param %p", graph, port, param);
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_aggregator_pipeline(const char *full_name,
|
||||
const char *component_names, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_GRAPH_T *graph = 0;
|
||||
MMAL_COMPONENT_T *subcomponent[2] = {0};
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
unsigned int length;
|
||||
char *orig, *names;
|
||||
|
||||
length = strlen(component_names);
|
||||
names = orig = vcos_calloc(1, length + 1, "mmal aggregator");
|
||||
if (!names)
|
||||
goto error;
|
||||
memcpy(names, component_names, length);
|
||||
|
||||
/* We'll build the aggregator using a graph */
|
||||
status = mmal_graph_create(&graph, sizeof(MMAL_GRAPH_USERDATA_T));
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
graph->pf_parameter_get = aggregator_parameter_get;
|
||||
graph->pf_parameter_set = aggregator_parameter_set;
|
||||
|
||||
/* Iterate through all the specified components */
|
||||
while (*names)
|
||||
{
|
||||
MMAL_CONNECTION_T *connection;
|
||||
const char *name;
|
||||
|
||||
/* Switch to a new connection */
|
||||
if (subcomponent[0])
|
||||
mmal_component_destroy(subcomponent[0]);
|
||||
subcomponent[0] = subcomponent[1];
|
||||
subcomponent[1] = 0;
|
||||
|
||||
/* Extract the name of the next component */
|
||||
for (name = names; *names && *names != ':'; names++);
|
||||
|
||||
/* Replace the separator */
|
||||
if (*names)
|
||||
*(names++) = 0;
|
||||
|
||||
/* Skip empty strings */
|
||||
if (!*name)
|
||||
continue;
|
||||
|
||||
status = mmal_component_create(name, &subcomponent[1]);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
status = mmal_graph_add_component(graph, subcomponent[1]);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
/* Special case for dealing with the first component in the chain */
|
||||
if (!subcomponent[0])
|
||||
{
|
||||
/* Add first input port if any */
|
||||
if (subcomponent[1]->input_num)
|
||||
{
|
||||
status = mmal_graph_add_port(graph, subcomponent[1]->input[0]);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create connection between the 2 ports */
|
||||
if (subcomponent[0]->output_num < 1 || subcomponent[1]->input_num < 1)
|
||||
goto error;
|
||||
status = mmal_connection_create(&connection, subcomponent[0]->output[0],
|
||||
subcomponent[1]->input[0], 0);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
status = mmal_graph_add_connection(graph, connection);
|
||||
/* Now the connection is added to the graph we don't care about it anymore */
|
||||
mmal_connection_destroy(connection);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Add last output port if any */
|
||||
if (subcomponent[1] && subcomponent[1]->output_num && subcomponent[1]->output[0])
|
||||
{
|
||||
status = mmal_graph_add_port(graph, subcomponent[1]->output[0]);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Build the graph */
|
||||
component->priv->module = (struct MMAL_COMPONENT_MODULE_T *)graph;
|
||||
status = mmal_graph_component_constructor(full_name, component);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
end:
|
||||
if (subcomponent[0])
|
||||
mmal_component_destroy(subcomponent[0]);
|
||||
if (subcomponent[1])
|
||||
mmal_component_destroy(subcomponent[1]);
|
||||
vcos_free(orig);
|
||||
return status;
|
||||
|
||||
error:
|
||||
if (graph)
|
||||
mmal_graph_destroy(graph);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_aggregator(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
const char *stripped = name + sizeof(AGGREGATOR_PREFIX);
|
||||
|
||||
/* Select the requested aggregator */
|
||||
if (!strncmp(stripped, AGGREGATOR_PIPELINE_PREFIX ":", sizeof(AGGREGATOR_PIPELINE_PREFIX)))
|
||||
return mmal_component_create_aggregator_pipeline(name,
|
||||
stripped + sizeof(AGGREGATOR_PIPELINE_PREFIX), component);
|
||||
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_aggregator);
|
||||
void mmal_register_component_aggregator(void)
|
||||
{
|
||||
mmal_component_supplier_register(AGGREGATOR_PREFIX, mmal_component_create_aggregator);
|
||||
}
|
@ -1,861 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#include <media/stagefright/MediaCodec.h>
|
||||
#include <media/stagefright/MediaErrors.h>
|
||||
#include <media/stagefright/foundation/ABuffer.h>
|
||||
#include <media/stagefright/foundation/AMessage.h>
|
||||
#include <media/ICrypto.h>
|
||||
#include <gui/ISurfaceComposer.h>
|
||||
#include <gui/SurfaceComposerClient.h>
|
||||
#include <binder/ProcessState.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
/* List of variants supported by this component */
|
||||
#define AMC_VARIANT_UNKNOWN 0
|
||||
#define AMC_VARIANT_AUDIO_DECODE 1
|
||||
#define AMC_VARIANT_AUDIO_DECODE_NAME "audio_decode"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct AmcHandler : public AHandler
|
||||
{
|
||||
AmcHandler(MMAL_COMPONENT_T *component) :
|
||||
mComponent(component), mNotificationRequested(false) {}
|
||||
|
||||
void requestNotification(sp<MediaCodec> &codec)
|
||||
{
|
||||
if (mActivityNotify == NULL)
|
||||
mActivityNotify = new AMessage(0, id());
|
||||
|
||||
if (!mNotificationRequested)
|
||||
{
|
||||
mNotificationRequested = true;
|
||||
codec->requestActivityNotification(mActivityNotify->dup());
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
mNotificationRequested = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void onMessageReceived(const sp<AMessage> &msg)
|
||||
{
|
||||
(void)msg;
|
||||
mNotificationRequested = false;
|
||||
mmal_component_action_trigger(mComponent);
|
||||
}
|
||||
|
||||
private:
|
||||
MMAL_COMPONENT_T *mComponent;
|
||||
sp<AMessage> mActivityNotify;
|
||||
bool mNotificationRequested;
|
||||
};
|
||||
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status; /**< current status of the component */
|
||||
|
||||
sp<MediaCodec> codec;
|
||||
sp<AmcHandler> ahandler;
|
||||
sp<ALooper> alooper;
|
||||
Vector<sp<ABuffer> > input_buffers; /**< list of buffers exported by mediacodec */
|
||||
Vector<sp<ABuffer> > output_buffers; /**< list of buffers exported by mediacodec */
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
typedef struct MMAL_PORT_MODULE_T
|
||||
{
|
||||
MMAL_ES_FORMAT_T *format; /**< format currently configured */
|
||||
MMAL_QUEUE_T *queue; /**< queue for the buffers sent to the ports */
|
||||
MMAL_BOOL_T needs_configuring; /**< port is waiting for a format commit */
|
||||
|
||||
List<size_t> *dequeued; /* buffers already dequeued from the codec */
|
||||
|
||||
const char *mime;
|
||||
unsigned int actual_channels;
|
||||
|
||||
} MMAL_PORT_MODULE_T;
|
||||
|
||||
static struct encoding_table_t {
|
||||
const char *mime;
|
||||
MMAL_FOURCC_T encoding;
|
||||
MMAL_ES_TYPE_T type;
|
||||
MMAL_FOURCC_T encoding_variant;
|
||||
} encoding_list[] =
|
||||
{ {"audio/3gpp", MMAL_ENCODING_AMRNB, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/amr-wb", MMAL_ENCODING_AMRWB, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/mpeg", MMAL_ENCODING_MPGA, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/mp4a-latm", MMAL_ENCODING_MP4A, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/mp4a-latm", MMAL_ENCODING_MP4A, MMAL_ES_TYPE_AUDIO, MMAL_ENCODING_VARIANT_MP4A_ADTS},
|
||||
{"audio/vorbis", MMAL_ENCODING_VORBIS, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/g711-alaw", MMAL_ENCODING_ALAW, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/g711-ulaw", MMAL_ENCODING_MULAW, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/ac3", MMAL_ENCODING_AC3, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/ec3", MMAL_ENCODING_EAC3, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/eac3", MMAL_ENCODING_EAC3, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"audio/raw", MMAL_ENCODING_PCM_SIGNED, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{"", MMAL_ENCODING_PCM_SIGNED, MMAL_ES_TYPE_AUDIO, 0},
|
||||
{ 0, 0, MMAL_ES_TYPE_UNKNOWN, 0}
|
||||
};
|
||||
|
||||
static const char *encoding_to_mime(MMAL_ES_TYPE_T type, MMAL_FOURCC_T encoding,
|
||||
MMAL_FOURCC_T encoding_variant)
|
||||
{
|
||||
struct encoding_table_t *entry = encoding_list;
|
||||
|
||||
for (entry = encoding_list; entry->mime; entry++)
|
||||
if (entry->encoding == encoding && entry->type == type &&
|
||||
entry->encoding_variant == encoding_variant)
|
||||
break;
|
||||
|
||||
return entry->mime;
|
||||
}
|
||||
|
||||
static void mime_to_encoding(const char *mime,
|
||||
MMAL_ES_TYPE_T *type, MMAL_FOURCC_T *encoding, MMAL_FOURCC_T *encoding_variant)
|
||||
{
|
||||
struct encoding_table_t *entry = encoding_list;
|
||||
|
||||
for (entry = encoding_list; entry->mime; entry++)
|
||||
if (!strcmp(mime, entry->mime))
|
||||
break;
|
||||
|
||||
*encoding = entry->encoding;
|
||||
*type = entry->type;
|
||||
*encoding_variant = entry->encoding_variant;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Actual processing functions */
|
||||
static MMAL_BOOL_T amc_do_input_processing(MMAL_COMPONENT_T *component,
|
||||
MMAL_BOOL_T *notification)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *port = component->input[0];
|
||||
MMAL_PORT_MODULE_T *port_module = port->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *in;
|
||||
status_t astatus;
|
||||
size_t size, index;
|
||||
uint32_t flags = 0;
|
||||
|
||||
in = mmal_queue_get(port_module->queue);
|
||||
|
||||
/* Get an input buffer from the codec. We dequeue input buffers even
|
||||
* if we do not any data to process to make sure that we do not get
|
||||
* flooded with notifications from the codec that buffers are
|
||||
* available. */
|
||||
if (port_module->dequeued->empty() || !in)
|
||||
{
|
||||
astatus = module->codec->dequeueInputBuffer(&index, 0ll);
|
||||
if (astatus == OK)
|
||||
{
|
||||
LOG_TRACE("dequeueInputBuffer %i", index);
|
||||
port_module->dequeued->push_back(index);
|
||||
}
|
||||
else if (astatus != -EAGAIN)
|
||||
{
|
||||
LOG_TRACE("dequeueInputBuffer failed (%i)", astatus);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether we can process data */
|
||||
if (!in)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (port_module->dequeued->empty())
|
||||
{
|
||||
mmal_queue_put_back(port_module->queue, in);
|
||||
|
||||
/* We have data we want to process so request to be notified as soon
|
||||
* as the codec is available to process it */
|
||||
*notification |= MMAL_TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We have some processing to do */
|
||||
|
||||
index = *port_module->dequeued->begin();
|
||||
sp<ABuffer> inBuf = module->input_buffers.itemAt(index);
|
||||
if (inBuf->capacity() < in->length)
|
||||
LOG_ERROR("MediaCodec input buffer too small (%i/%i)",
|
||||
(int)inBuf->capacity(), (int)in->length);
|
||||
size = MMAL_MIN(inBuf->capacity(), in->length);
|
||||
|
||||
if (in->length)
|
||||
memcpy(inBuf->data(), in->data + in->offset, size);
|
||||
if (in->flags & MMAL_BUFFER_HEADER_FLAG_EOS)
|
||||
flags |= MediaCodec::BUFFER_FLAG_EOS;
|
||||
if (in->flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
|
||||
flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
|
||||
if (in->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG)
|
||||
flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
|
||||
|
||||
LOG_TRACE("queueInputBuffer %i %ibytes, %lldus", index, in->length, in->pts);
|
||||
astatus = module->codec->queueInputBuffer(index, 0, size, in->pts, flags);
|
||||
if (astatus != OK)
|
||||
{
|
||||
LOG_ERROR("queueInputBuffer failed (%i)", astatus);
|
||||
mmal_event_error_send(component, MMAL_EIO);
|
||||
module->status = MMAL_EIO;
|
||||
}
|
||||
|
||||
/* Send buffers back */
|
||||
in->length = 0;
|
||||
mmal_port_buffer_header_callback(port, in);
|
||||
port_module->dequeued->erase(port_module->dequeued->begin());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void amc_output_format_changed(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *port = component->output[0];
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
MMAL_STATUS_T status;
|
||||
int32_t value;
|
||||
|
||||
sp<AMessage> format = new AMessage;
|
||||
status_t astatus = module->codec->getOutputFormat(&format);
|
||||
LOG_DEBUG("INFO_FORMAT_CHANGED (%i): %s", astatus,
|
||||
format->debugString().c_str());
|
||||
|
||||
/* Get an event buffer */
|
||||
status = mmal_port_event_get(port, &buffer, MMAL_EVENT_FORMAT_CHANGED);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("unable to get an event buffer");
|
||||
return;
|
||||
}
|
||||
event = mmal_event_format_changed_get(buffer);
|
||||
|
||||
AString amime;
|
||||
format->findString("mime", &amime);
|
||||
mime_to_encoding(amime.c_str(),
|
||||
&event->format->type, &event->format->encoding,
|
||||
&event->format->encoding_variant);
|
||||
|
||||
switch (port->format->type)
|
||||
{
|
||||
case MMAL_ES_TYPE_VIDEO:
|
||||
if (format->findInt32("width", &value))
|
||||
event->format->es->video.width = value;
|
||||
if (format->findInt32("height", &value))
|
||||
event->format->es->video.height = value;
|
||||
break;
|
||||
case MMAL_ES_TYPE_AUDIO:
|
||||
if (format->findInt32("channel-count", &value))
|
||||
event->format->es->audio.channels = value;
|
||||
if (format->findInt32("sample-rate", &value))
|
||||
event->format->es->audio.sample_rate = value;
|
||||
if (format->findInt32("bitrate", &value))
|
||||
event->format->bitrate = value;
|
||||
if (event->format->encoding == MMAL_ENCODING_PCM_SIGNED)
|
||||
event->format->es->audio.bits_per_sample = 16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Work-around for the ril audio_render component which only supports
|
||||
* power of 2 arrangements */
|
||||
if (event->format->type == MMAL_ES_TYPE_AUDIO &&
|
||||
event->format->encoding == MMAL_ENCODING_PCM_SIGNED)
|
||||
{
|
||||
port->priv->module->actual_channels = event->format->es->audio.channels;
|
||||
if (event->format->es->audio.channels == 6)
|
||||
event->format->es->audio.channels = 8;
|
||||
}
|
||||
|
||||
/* Update current format */
|
||||
mmal_format_copy(port->priv->module->format, event->format);
|
||||
|
||||
/* Pass on the buffer requirements */
|
||||
event->buffer_num_min = port->buffer_num_min;
|
||||
event->buffer_size_min = port->buffer_size_min;
|
||||
event->buffer_size_recommended = port->buffer_size_recommended;
|
||||
event->buffer_num_recommended = port->buffer_num_recommended;
|
||||
|
||||
mmal_port_event_send(port, buffer);
|
||||
}
|
||||
|
||||
static MMAL_BOOL_T amc_do_output_processing(MMAL_COMPONENT_T *component,
|
||||
MMAL_BOOL_T *notification)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *port_out = component->output[0];
|
||||
MMAL_BUFFER_HEADER_T *out;
|
||||
status_t astatus;
|
||||
size_t size, offset, index;
|
||||
int64_t pts;
|
||||
uint32_t flags;
|
||||
|
||||
if (port_out->priv->module->needs_configuring)
|
||||
return 0;
|
||||
|
||||
out = mmal_queue_get(port_out->priv->module->queue);
|
||||
if (!out)
|
||||
{
|
||||
/* We do not want notifications in that case. We've already filled
|
||||
* our output buffers so we should really wait to receive more
|
||||
* output buffers before resuming the processing */
|
||||
*notification = MMAL_FALSE;
|
||||
return 0;
|
||||
}
|
||||
out->flags = 0;
|
||||
|
||||
astatus = module->codec->dequeueOutputBuffer(&index, &offset, &size, &pts, &flags, 0ll);
|
||||
if (astatus != OK)
|
||||
{
|
||||
MMAL_BOOL_T do_more = 0;
|
||||
|
||||
switch (astatus)
|
||||
{
|
||||
case INFO_OUTPUT_BUFFERS_CHANGED:
|
||||
LOG_DEBUG("INFO_OUTPUT_BUFFERS_CHANGED");
|
||||
astatus = module->codec->getOutputBuffers(&module->output_buffers);
|
||||
do_more = MMAL_TRUE;
|
||||
break;
|
||||
case INFO_FORMAT_CHANGED:
|
||||
amc_output_format_changed(component);
|
||||
port_out->priv->module->needs_configuring = 1;
|
||||
do_more = MMAL_TRUE;
|
||||
break;
|
||||
case -EAGAIN:
|
||||
/* We have data we want to process so request to be notified as soon
|
||||
* as the codec is available to process it */
|
||||
*notification |= MMAL_TRUE;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("dequeueOutputBuffer failed (%i)", astatus);
|
||||
}
|
||||
|
||||
mmal_queue_put_back(port_out->priv->module->queue, out);
|
||||
return do_more;
|
||||
}
|
||||
|
||||
LOG_TRACE("dequeueOutputBuffer %i, %ibytes, %lldus, flags %x",
|
||||
index, size, pts, flags);
|
||||
sp<ABuffer> outBuf = module->output_buffers.itemAt(index);
|
||||
|
||||
out->flags = 0;
|
||||
out->offset = 0;
|
||||
out->pts = pts;
|
||||
out->dts = 0;
|
||||
|
||||
if (flags & MediaCodec::BUFFER_FLAG_EOS)
|
||||
out->flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME)
|
||||
out->flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
|
||||
if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)
|
||||
out->flags |= MMAL_BUFFER_HEADER_FLAG_CONFIG;
|
||||
|
||||
if (out->alloc_size < size)
|
||||
LOG_ERROR("MediaCodec output buffer too big (%i/%i)",
|
||||
(int)out->alloc_size, (int)size);
|
||||
size = MMAL_MIN(out->alloc_size, size);
|
||||
|
||||
/* Audio render only accepts power of 2 channel configurations */
|
||||
if (port_out->format->type == MMAL_ES_TYPE_AUDIO &&
|
||||
port_out->format->encoding == MMAL_ENCODING_PCM_SIGNED &&
|
||||
port_out->priv->module->actual_channels !=
|
||||
port_out->format->es->audio.channels)
|
||||
{
|
||||
unsigned int valid = port_out->priv->module->actual_channels * 2;
|
||||
unsigned int pitch = port_out->format->es->audio.channels * 2;
|
||||
uint8_t *src = outBuf->data() + offset;
|
||||
uint8_t *dst = out->data;
|
||||
unsigned int i;
|
||||
|
||||
size = size * port_out->format->es->audio.channels /
|
||||
port_out->priv->module->actual_channels;
|
||||
size = MMAL_MIN(out->alloc_size, size);
|
||||
memset(dst, 0, size);
|
||||
for (i = size / pitch; i; i--, src += valid, dst += pitch)
|
||||
memcpy(dst, src, valid);
|
||||
}
|
||||
else if (size)
|
||||
memcpy(out->data, outBuf->data() + offset, size);
|
||||
out->length = size;
|
||||
|
||||
/* Send buffers back */
|
||||
module->codec->releaseOutputBuffer(index);
|
||||
mmal_port_buffer_header_callback(port_out, out);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static MMAL_BOOL_T amc_do_processing(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BOOL_T do_more, request_notification = MMAL_FALSE;
|
||||
|
||||
if (module->codec == NULL)
|
||||
return 0;
|
||||
|
||||
/* Don't do anything if we've already seen an error */
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
return 0;
|
||||
|
||||
do_more = amc_do_input_processing(component, &request_notification);
|
||||
do_more |= amc_do_output_processing(component, &request_notification);
|
||||
|
||||
if (request_notification)
|
||||
module->ahandler->requestNotification(module->codec);
|
||||
|
||||
return do_more;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void amc_do_processing_loop(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
while (amc_do_processing(component));
|
||||
}
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T amc_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < component->input_num; i++)
|
||||
{
|
||||
if(component->input[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->input[i]->priv->module->queue);
|
||||
if(component->input[i]->priv->module->format)
|
||||
mmal_format_free(component->input[i]->priv->module->format);
|
||||
if(component->input[i]->priv->module->dequeued)
|
||||
delete component->input[i]->priv->module->dequeued;
|
||||
}
|
||||
if(component->input_num)
|
||||
mmal_ports_free(component->input, component->input_num);
|
||||
|
||||
for(i = 0; i < component->output_num; i++)
|
||||
{
|
||||
if(component->output[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->output[i]->priv->module->queue);
|
||||
if(component->output[i]->priv->module->format)
|
||||
mmal_format_free(component->output[i]->priv->module->format);
|
||||
}
|
||||
if(component->output_num)
|
||||
mmal_ports_free(component->output, component->output_num);
|
||||
|
||||
if (module->codec != NULL)
|
||||
{
|
||||
module->codec->stop();
|
||||
module->codec->release();
|
||||
}
|
||||
|
||||
module->alooper->unregisterHandler(module->ahandler->id());
|
||||
module->alooper->stop();
|
||||
delete module;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T amc_codec_start(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *in = component->input[0];
|
||||
sp<AMessage> format = new AMessage;
|
||||
status_t astatus;
|
||||
const char *mime;
|
||||
|
||||
mime = encoding_to_mime(in->format->type, in->format->encoding,
|
||||
in->format->encoding_variant);
|
||||
if (!mime)
|
||||
{
|
||||
LOG_ERROR("cannot match codec %4.4s(%4.4s) with a mime type",
|
||||
(char *)&in->format->encoding, (char *)&in->format->encoding_variant);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
/* We need to restart MediaCodec when the codec type changes */
|
||||
if (module->codec == NULL || mime != in->priv->module->mime)
|
||||
{
|
||||
LOG_DEBUG("creating codec for %s", mime);
|
||||
|
||||
/* Start by releasing any instance we've previously created */
|
||||
if (module->codec != NULL)
|
||||
{
|
||||
module->codec->stop();
|
||||
module->codec->release();
|
||||
}
|
||||
|
||||
module->codec = MediaCodec::CreateByType(module->alooper, mime, false);
|
||||
if (module->codec == NULL)
|
||||
{
|
||||
LOG_ERROR("cannot instantiate MediaCodec for mime: %s", mime);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
in->priv->module->mime = mime;
|
||||
module->ahandler->reset();
|
||||
LOG_TRACE("creation done");
|
||||
}
|
||||
/* When reusing an existing instance, we just need to stop it */
|
||||
else
|
||||
{
|
||||
module->codec->stop();
|
||||
}
|
||||
|
||||
/* Configure MediaCodec */
|
||||
switch (in->format->type)
|
||||
{
|
||||
case MMAL_ES_TYPE_VIDEO:
|
||||
format->setInt32("width", in->format->es->video.width);
|
||||
format->setInt32("height", in->format->es->video.height);
|
||||
if (in->format->es->video.frame_rate.num && in->format->es->video.frame_rate.den)
|
||||
format->setFloat("frame-rate", in->format->es->video.frame_rate.num /
|
||||
(float)in->format->es->video.frame_rate.den);
|
||||
break;
|
||||
case MMAL_ES_TYPE_AUDIO:
|
||||
format->setInt32("channel-count", in->format->es->audio.channels);
|
||||
format->setInt32("sample-rate", in->format->es->audio.sample_rate);
|
||||
format->setInt32("bitrate", in->format->bitrate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
format->setString("mime", mime);
|
||||
|
||||
/* Handle the codec specific data */
|
||||
if (in->format->extradata_size)
|
||||
{
|
||||
sp<ABuffer> csd = new ABuffer(in->format->extradata,
|
||||
in->format->extradata_size);
|
||||
csd->meta()->setInt32("csd", true);
|
||||
csd->meta()->setInt64("timeUs", 0);
|
||||
format->setBuffer("csd-0", csd);
|
||||
}
|
||||
|
||||
/* Propagate the buffer size setting of the input port to the
|
||||
* codec */
|
||||
format->setInt32("max-input-size", in->buffer_size);
|
||||
|
||||
LOG_TRACE("configuring: %s", format->debugString().c_str());
|
||||
astatus = module->codec->configure(format, NULL, NULL, 0);
|
||||
if (astatus)
|
||||
{
|
||||
LOG_ERROR("configure failed (%i)", astatus);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
LOG_TRACE("starting");
|
||||
astatus = module->codec->start();
|
||||
if (astatus != OK)
|
||||
{
|
||||
LOG_ERROR("failed to start codec (%i)", astatus);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
LOG_TRACE("started");
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T amc_input_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_STATUS_T status;
|
||||
status_t astatus;
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
|
||||
/* Make sure the format as been committed */
|
||||
status = port->priv->pf_set_format(port);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("cannot commit port format (%i)", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = amc_codec_start(component);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
astatus = module->codec->getInputBuffers(&module->input_buffers);
|
||||
if (astatus != OK)
|
||||
{
|
||||
LOG_ERROR("failed to get codec input buffers (%i)", astatus);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
if (module->input_buffers.size())
|
||||
LOG_TRACE("%i input buffers of size %i", module->input_buffers.size(),
|
||||
module->input_buffers.itemAt(0)->capacity());
|
||||
|
||||
astatus = module->codec->getOutputBuffers(&module->output_buffers);
|
||||
if (astatus != OK)
|
||||
{
|
||||
LOG_ERROR("failed to get codec output buffers (%i)", astatus);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
if (module->output_buffers.size())
|
||||
LOG_TRACE("%i output buffers of size %i", module->output_buffers.size(),
|
||||
module->output_buffers.itemAt(0)->capacity());
|
||||
|
||||
module->status = MMAL_SUCCESS;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T amc_output_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T amc_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PORT_MODULE_T *port_module = port->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
status_t astatus;
|
||||
|
||||
/* Flush buffers that our component is holding on to */
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
while(buffer)
|
||||
{
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
}
|
||||
|
||||
if (port_module->dequeued)
|
||||
port_module->dequeued->clear();
|
||||
|
||||
/* Flush codec itself */
|
||||
if (port->type == MMAL_PORT_TYPE_INPUT && module->codec != NULL)
|
||||
{
|
||||
astatus = module->codec->flush();
|
||||
if (astatus != OK)
|
||||
LOG_ERROR("failed to flush codec (%i)", astatus);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T amc_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
status_t astatus;
|
||||
|
||||
if (port->type == MMAL_PORT_TYPE_INPUT)
|
||||
{
|
||||
astatus = module->codec->stop();
|
||||
if (astatus != OK)
|
||||
LOG_ERROR("failed to stop codec (%i)", astatus);
|
||||
module->codec->release();
|
||||
module->codec = NULL;
|
||||
}
|
||||
|
||||
/* We just need to flush our internal queue */
|
||||
return amc_port_flush(port);
|
||||
}
|
||||
|
||||
/** Send a buffer header to a port */
|
||||
static MMAL_STATUS_T amc_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
mmal_queue_put(port->priv->module->queue, buffer);
|
||||
mmal_component_action_trigger(port->component);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on input port */
|
||||
static MMAL_STATUS_T amc_input_port_format_commit(MMAL_PORT_T *in)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
const char *mime;
|
||||
|
||||
if (in->is_enabled)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
if (!mmal_format_compare(in->format, in->priv->module->format))
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
mime = encoding_to_mime(in->format->type, in->format->encoding,
|
||||
in->format->encoding_variant);
|
||||
if (!mime)
|
||||
{
|
||||
LOG_ERROR("cannot match codec %4.4s(%4.4s) with a mime type",
|
||||
(char *)&in->format->encoding, (char *)&in->format->encoding_variant);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
/* Note that the MediaCodec object is only created when the input
|
||||
* port is enabled to avoid deadlocking when we're running inside an
|
||||
* Android OMX component (you can't create an OMX odec instance while
|
||||
* you're already instantiating one) */
|
||||
|
||||
status = mmal_format_full_copy(in->priv->module->format, in->format);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* No need to propagate anything to the output port since
|
||||
* we'll generate a format change event for it later on */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Set format on output port */
|
||||
static MMAL_STATUS_T amc_output_port_format_commit(MMAL_PORT_T *out)
|
||||
{
|
||||
/* The format of the output port needs to match the output of
|
||||
* MediaCodec */
|
||||
if (mmal_format_compare(out->format, out->priv->module->format))
|
||||
return MMAL_EINVAL;
|
||||
|
||||
out->priv->module->needs_configuring = 0;
|
||||
mmal_component_action_trigger(out->component);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_android_media_codec(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
const char *variant_name = name + sizeof("amc");
|
||||
unsigned int variant = AMC_VARIANT_UNKNOWN;
|
||||
|
||||
if (!strcmp(variant_name, AMC_VARIANT_AUDIO_DECODE_NAME))
|
||||
variant = AMC_VARIANT_AUDIO_DECODE;
|
||||
|
||||
if (variant == AMC_VARIANT_UNKNOWN)
|
||||
{
|
||||
LOG_ERROR("unsupported variant %s", variant_name);
|
||||
return MMAL_ENOENT;
|
||||
}
|
||||
|
||||
/* Allocate the context for our module */
|
||||
component->priv->module = module = new MMAL_COMPONENT_MODULE_T;
|
||||
if (!module)
|
||||
return MMAL_ENOMEM;
|
||||
|
||||
component->priv->pf_destroy = amc_component_destroy;
|
||||
module->status = MMAL_SUCCESS;
|
||||
ProcessState::self()->startThreadPool();
|
||||
module->ahandler = new AmcHandler(component);
|
||||
module->alooper = new ALooper;
|
||||
module->alooper->setName("amc_looper");
|
||||
module->alooper->registerHandler(module->ahandler);
|
||||
module->alooper->start(false);
|
||||
|
||||
/* Allocate and initialise all the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->input)
|
||||
goto error;
|
||||
component->input_num = 1;
|
||||
component->input[0]->priv->pf_enable = amc_input_port_enable;
|
||||
component->input[0]->priv->pf_disable = amc_port_disable;
|
||||
component->input[0]->priv->pf_flush = amc_port_flush;
|
||||
component->input[0]->priv->pf_send = amc_port_send;
|
||||
component->input[0]->priv->pf_set_format = amc_input_port_format_commit;
|
||||
component->input[0]->buffer_num_min = 1;
|
||||
component->input[0]->buffer_num_recommended = 3;
|
||||
component->input[0]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->input[0]->priv->module->queue)
|
||||
goto error;
|
||||
component->input[0]->priv->module->format = mmal_format_alloc();
|
||||
if(!component->input[0]->priv->module->format)
|
||||
goto error;
|
||||
component->input[0]->priv->module->dequeued = new List<size_t>;
|
||||
if(!component->input[0]->priv->module->dequeued)
|
||||
goto error;
|
||||
|
||||
component->output = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_OUTPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->output)
|
||||
goto error;
|
||||
component->output_num = 1;
|
||||
component->output[0]->priv->pf_enable = amc_output_port_enable;
|
||||
component->output[0]->priv->pf_disable = amc_port_disable;
|
||||
component->output[0]->priv->pf_flush = amc_port_flush;
|
||||
component->output[0]->priv->pf_send = amc_port_send;
|
||||
component->output[0]->priv->pf_set_format = amc_output_port_format_commit;
|
||||
component->output[0]->buffer_num_min = 1;
|
||||
component->output[0]->buffer_num_recommended = 3;
|
||||
component->output[0]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->output[0]->priv->module->queue)
|
||||
goto error;
|
||||
component->output[0]->priv->module->format = mmal_format_alloc();
|
||||
if(!component->output[0]->priv->module->format)
|
||||
goto error;
|
||||
|
||||
status = mmal_component_action_register(component, amc_do_processing_loop);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
/* Setup ports according to selected variant */
|
||||
if (variant == AMC_VARIANT_AUDIO_DECODE)
|
||||
{
|
||||
component->input[0]->format->type = MMAL_ES_TYPE_AUDIO;
|
||||
component->input[0]->format->encoding = MMAL_ENCODING_EAC3;
|
||||
component->input[0]->format->es->audio.sample_rate = 48000;
|
||||
component->input[0]->format->es->audio.channels = 2;
|
||||
component->input[0]->buffer_size_min = 4 * 1024;
|
||||
|
||||
component->output[0]->format->type = MMAL_ES_TYPE_AUDIO;
|
||||
component->output[0]->format->encoding = MMAL_ENCODING_PCM_SIGNED;
|
||||
component->output[0]->format->es->audio.sample_rate = 48000;
|
||||
component->output[0]->format->es->audio.channels = 2;
|
||||
component->output[0]->format->es->audio.bits_per_sample = 16;
|
||||
component->output[0]->buffer_size_min = 32 * 1024;
|
||||
}
|
||||
|
||||
/* Update our current view of the output format */
|
||||
mmal_format_copy(component->output[0]->priv->module->format,
|
||||
component->output[0]->format);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
amc_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_android_media_codec);
|
||||
void mmal_register_component_android_media_codec(void)
|
||||
{
|
||||
mmal_component_supplier_register("amc", mmal_component_create_android_media_codec);
|
||||
}
|
@ -1,287 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#define ARTIFICIAL_CAMERA_PORTS_NUM 3
|
||||
|
||||
/* Buffering requirements */
|
||||
#define OUTPUT_MIN_BUFFER_NUM 1
|
||||
#define OUTPUT_RECOMMENDED_BUFFER_NUM 4
|
||||
|
||||
#define DEFAULT_WIDTH 320
|
||||
#define DEFAULT_HEIGHT 240
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef struct MMAL_PORT_MODULE_T
|
||||
{
|
||||
MMAL_BUFFER_HEADER_VIDEO_SPECIFIC_T frame;
|
||||
unsigned int frame_size;
|
||||
int count;
|
||||
|
||||
MMAL_QUEUE_T *queue;
|
||||
|
||||
} MMAL_PORT_MODULE_T;
|
||||
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
static void artificial_camera_do_processing(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
unsigned int i;
|
||||
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
return;
|
||||
|
||||
/* Loop through all the ports */
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
{
|
||||
MMAL_PORT_T *port = component->output[i];
|
||||
|
||||
buffer = mmal_queue_get(port->priv->module->queue);
|
||||
if (!buffer)
|
||||
continue;
|
||||
|
||||
/* Sanity check the buffer size */
|
||||
if (buffer->alloc_size < port->priv->module->frame_size)
|
||||
{
|
||||
LOG_ERROR("buffer too small (%i/%i)",
|
||||
buffer->alloc_size, port->priv->module->frame_size);
|
||||
module->status = MMAL_EINVAL;
|
||||
mmal_queue_put_back(port->priv->module->queue, buffer);
|
||||
mmal_event_error_send(component, module->status);
|
||||
return;
|
||||
}
|
||||
module->status = mmal_buffer_header_mem_lock(buffer);
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("invalid buffer (%p, %p)", buffer, buffer->data);
|
||||
mmal_queue_put_back(port->priv->module->queue, buffer);
|
||||
mmal_event_error_send(component, module->status);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer->offset = 0;
|
||||
buffer->length = port->priv->module->frame_size;
|
||||
buffer->type->video = port->priv->module->frame;
|
||||
|
||||
memset(buffer->data, 0xff, buffer->length);
|
||||
if (buffer->type->video.planes > 1)
|
||||
memset(buffer->data + buffer->type->video.offset[1],
|
||||
0x7f - port->priv->module->count++,
|
||||
buffer->length - buffer->type->video.offset[1]);
|
||||
|
||||
mmal_buffer_header_mem_unlock(buffer);
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
}
|
||||
|
||||
vcos_sleep(10); /* Make sure we don't peg all the resources */
|
||||
}
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T artificial_camera_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
if (component->output[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->output[i]->priv->module->queue);
|
||||
|
||||
if(component->output_num)
|
||||
mmal_ports_free(component->output, component->output_num);
|
||||
|
||||
vcos_free(component->priv->module);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T artificial_camera_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T artificial_camera_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T artificial_camera_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Send a buffer header to a port */
|
||||
static MMAL_STATUS_T artificial_camera_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
/* Just queue the buffer */
|
||||
mmal_queue_put(port->priv->module->queue, buffer);
|
||||
mmal_component_action_trigger(port->component);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T artificial_camera_port_format_commit(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PORT_MODULE_T *port_module = port->priv->module;
|
||||
unsigned int width = port->format->es->video.width;
|
||||
unsigned int height = port->format->es->video.height;
|
||||
width = (width + 31) & ~31;
|
||||
height = (height + 15) & ~15;
|
||||
|
||||
/* We only support a few formats */
|
||||
switch(port->format->encoding)
|
||||
{
|
||||
case MMAL_ENCODING_I420:
|
||||
port_module->frame_size = width * height * 3 / 2;
|
||||
port_module->frame.planes = 3;
|
||||
port_module->frame.pitch[0] = width;
|
||||
port_module->frame.offset[1] = port_module->frame.pitch[0] * height;
|
||||
port_module->frame.pitch[1] = width / 2;
|
||||
port_module->frame.offset[2] = port_module->frame.offset[1] + port_module->frame.pitch[1] * height / 2;
|
||||
port_module->frame.pitch[2] = width / 2;
|
||||
break;
|
||||
case MMAL_ENCODING_NV21:
|
||||
port_module->frame_size = width * height * 3 / 2;
|
||||
port_module->frame.planes = 2;
|
||||
port_module->frame.pitch[0] = width;
|
||||
port_module->frame.offset[1] = port_module->frame.pitch[0] * height;
|
||||
port_module->frame.pitch[1] = width;
|
||||
break;
|
||||
case MMAL_ENCODING_I422:
|
||||
port_module->frame_size = width * height * 2;
|
||||
port_module->frame.planes = 3;
|
||||
port_module->frame.pitch[0] = width;
|
||||
port_module->frame.offset[1] = port_module->frame.pitch[0] * height;
|
||||
port_module->frame.pitch[1] = width / 2;
|
||||
port_module->frame.offset[2] = port_module->frame.offset[1] + port_module->frame.pitch[1] * height;
|
||||
port_module->frame.pitch[2] = width / 2;
|
||||
break;
|
||||
default:
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
port->buffer_size_min = port->buffer_size_recommended = port_module->frame_size;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set parameter on a port */
|
||||
static MMAL_STATUS_T artificial_port_parameter_set(MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
switch (param->id)
|
||||
{
|
||||
default:
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get parameter on a port */
|
||||
static MMAL_STATUS_T artificial_port_parameter_get(MMAL_PORT_T *port, MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
switch (param->id)
|
||||
{
|
||||
default:
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_artificial_camera(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
unsigned int i;
|
||||
MMAL_PARAM_UNUSED(name);
|
||||
|
||||
/* Allocate our module context */
|
||||
component->priv->module = vcos_calloc(1, sizeof(*component->priv->module), "mmal module");
|
||||
if (!component->priv->module)
|
||||
return MMAL_ENOMEM;
|
||||
|
||||
component->priv->pf_destroy = artificial_camera_component_destroy;
|
||||
|
||||
/* Allocate all the ports for this component */
|
||||
component->output = mmal_ports_alloc(component, ARTIFICIAL_CAMERA_PORTS_NUM, MMAL_PORT_TYPE_OUTPUT,
|
||||
sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->output)
|
||||
goto error;
|
||||
component->output_num = ARTIFICIAL_CAMERA_PORTS_NUM;
|
||||
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
{
|
||||
component->output[i]->priv->pf_enable = artificial_camera_port_enable;
|
||||
component->output[i]->priv->pf_disable = artificial_camera_port_disable;
|
||||
component->output[i]->priv->pf_flush = artificial_camera_port_flush;
|
||||
component->output[i]->priv->pf_send = artificial_camera_port_send;
|
||||
component->output[i]->priv->pf_send = artificial_camera_port_send;
|
||||
component->output[i]->priv->pf_set_format = artificial_camera_port_format_commit;
|
||||
component->output[i]->priv->pf_parameter_set = artificial_port_parameter_set;
|
||||
component->output[i]->priv->pf_parameter_get = artificial_port_parameter_get;
|
||||
component->output[i]->format->type = MMAL_ES_TYPE_VIDEO;
|
||||
component->output[i]->format->encoding = MMAL_ENCODING_I420;
|
||||
component->output[i]->format->es->video.width = DEFAULT_WIDTH;
|
||||
component->output[i]->format->es->video.height = DEFAULT_HEIGHT;
|
||||
component->output[i]->buffer_num_min = OUTPUT_MIN_BUFFER_NUM;
|
||||
component->output[i]->buffer_num_recommended = OUTPUT_RECOMMENDED_BUFFER_NUM;
|
||||
artificial_camera_port_format_commit(component->output[i]);
|
||||
|
||||
component->output[i]->priv->module->queue = mmal_queue_create();
|
||||
if (!component->output[i]->priv->module->queue)
|
||||
goto error;
|
||||
}
|
||||
|
||||
status = mmal_component_action_register(component, artificial_camera_do_processing);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
artificial_camera_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_artificial_camera);
|
||||
void mmal_register_component_artificial_camera(void)
|
||||
{
|
||||
mmal_component_supplier_register("artificial_camera", mmal_component_create_artificial_camera);
|
||||
}
|
@ -1,607 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/mathematics.h"
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 52, 23, 0 )
|
||||
# include "libavformat/avformat.h"
|
||||
static AVPacket null_packet = {AV_NOPTS_VALUE, AV_NOPTS_VALUE};
|
||||
# define av_init_packet(a) *(a) = null_packet
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 53
|
||||
# define avcodec_decode_audio3(a,b,c,d) avcodec_decode_audio2(a,b,c,(d)->data,(d)->size)
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 54
|
||||
#define AVSampleFormat SampleFormat
|
||||
#define AV_SAMPLE_FMT_NONE SAMPLE_FMT_NONE
|
||||
#define AV_SAMPLE_FMT_U8 SAMPLE_FMT_U8
|
||||
#define AV_SAMPLE_FMT_S16 SAMPLE_FMT_S16
|
||||
#define AV_SAMPLE_FMT_S32 SAMPLE_FMT_S32
|
||||
#define AV_SAMPLE_FMT_FLT SAMPLE_FMT_FLT
|
||||
#define AV_SAMPLE_FMT_DBL SAMPLE_FMT_DBL
|
||||
#endif
|
||||
|
||||
/* Buffering requirements */
|
||||
#define INPUT_MIN_BUFFER_SIZE (4*1024)
|
||||
#define INPUT_MIN_BUFFER_NUM 1
|
||||
#define INPUT_RECOMMENDED_BUFFER_SIZE INPUT_MIN_BUFFER_SIZE
|
||||
#define INPUT_RECOMMENDED_BUFFER_NUM 10
|
||||
#define OUTPUT_MIN_BUFFER_NUM 1
|
||||
#define OUTPUT_RECOMMENDED_BUFFER_NUM 4
|
||||
#define OUTPUT_MIN_BUFFER_SIZE 512
|
||||
#define OUTPUT_RECOMMENDED_BUFFER_SIZE 4096
|
||||
|
||||
static uint32_t encoding_to_codecid(uint32_t encoding);
|
||||
static uint32_t samplefmt_to_encoding(enum AVSampleFormat);
|
||||
static unsigned int samplefmt_to_sample_size(enum AVSampleFormat samplefmt);
|
||||
|
||||
/****************************/
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
MMAL_QUEUE_T *queue_in;
|
||||
MMAL_QUEUE_T *queue_out;
|
||||
|
||||
int64_t pts;
|
||||
|
||||
int64_t last_pts;
|
||||
int64_t samples_since_last_pts;
|
||||
|
||||
int output_buffer_size;
|
||||
uint8_t *output_buffer;
|
||||
|
||||
uint8_t *output;
|
||||
int output_size;
|
||||
AVCodecContext *codec_context;
|
||||
AVCodec *codec;
|
||||
|
||||
enum AVSampleFormat sample_fmt;
|
||||
int channels;
|
||||
int sample_rate;
|
||||
int bits_per_sample;
|
||||
|
||||
MMAL_BOOL_T output_needs_configuring;
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T avcodec_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
if (module->codec_context)
|
||||
{
|
||||
if (module->codec_context->extradata)
|
||||
vcos_free(module->codec_context->extradata);
|
||||
if (module->codec_context->codec)
|
||||
avcodec_close(module->codec_context);
|
||||
av_free(module->codec_context);
|
||||
}
|
||||
if (module->output_buffer)
|
||||
av_free(module->output_buffer);
|
||||
|
||||
if (module->queue_in)
|
||||
mmal_queue_destroy(module->queue_in);
|
||||
if (module->queue_out)
|
||||
mmal_queue_destroy(module->queue_out);
|
||||
vcos_free(module);
|
||||
if (component->input_num)
|
||||
mmal_ports_free(component->input, 1);
|
||||
if (component->output_num)
|
||||
mmal_ports_free(component->output, 1);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T avcodec_input_port_set_format(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
enum CodecID codec_id;
|
||||
AVCodec *codec;
|
||||
|
||||
codec_id = encoding_to_codecid(port->format->encoding);
|
||||
if (codec_id == CODEC_ID_NONE ||
|
||||
!(codec = avcodec_find_decoder(codec_id)))
|
||||
{
|
||||
LOG_ERROR("ffmpeg codec id %d (for %4.4s) not recognized",
|
||||
codec_id, (char *)&port->format->encoding);
|
||||
return MMAL_ENXIO;
|
||||
}
|
||||
|
||||
module->output_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||
if (module->output_buffer)
|
||||
av_free(module->output_buffer);
|
||||
module->output_buffer = av_malloc(module->output_buffer_size);
|
||||
|
||||
module->codec_context->sample_rate = port->format->es->audio.sample_rate;
|
||||
module->codec_context->channels = port->format->es->audio.channels;
|
||||
module->codec_context->block_align = port->format->es->audio.block_align;
|
||||
module->codec_context->bit_rate = port->format->bitrate;
|
||||
module->codec_context->bits_per_coded_sample = port->format->es->audio.bits_per_sample;
|
||||
module->codec_context->extradata_size = port->format->extradata_size;
|
||||
module->codec_context->extradata =
|
||||
vcos_calloc(1, port->format->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE,
|
||||
"avcodec extradata");
|
||||
if (module->codec_context->extradata)
|
||||
memcpy(module->codec_context->extradata, port->format->extradata,
|
||||
port->format->extradata_size);
|
||||
|
||||
if (codec->capabilities & CODEC_CAP_TRUNCATED)
|
||||
module->codec_context->flags |= CODEC_FLAG_TRUNCATED;
|
||||
|
||||
if (avcodec_open(module->codec_context, codec) < 0)
|
||||
{
|
||||
LOG_ERROR("could not open codec");
|
||||
return MMAL_EIO;
|
||||
}
|
||||
|
||||
/* Set a default format */
|
||||
if (module->codec_context->sample_fmt == AV_SAMPLE_FMT_NONE)
|
||||
module->codec_context->sample_fmt = AV_SAMPLE_FMT_S16;
|
||||
|
||||
/* Copy format to output */
|
||||
mmal_format_copy(component->output[0]->format, port->format);
|
||||
LOG_DEBUG("avcodec output format %i", module->codec_context->sample_fmt);
|
||||
component->output[0]->format->encoding = samplefmt_to_encoding(module->codec_context->sample_fmt);
|
||||
component->output[0]->format->es->audio.bits_per_sample =
|
||||
samplefmt_to_sample_size(module->codec_context->sample_fmt);
|
||||
|
||||
component->output[0]->priv->pf_set_format(component->output[0]);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T avcodec_output_port_set_format(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
/* Format can only be set to what is output by the codec */
|
||||
if (samplefmt_to_encoding(module->codec_context->sample_fmt) != port->format->encoding ||
|
||||
samplefmt_to_sample_size(module->codec_context->sample_fmt) != port->format->es->audio.bits_per_sample)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
if (!port->format->es->audio.sample_rate || !port->format->es->audio.channels)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
module->sample_fmt = module->codec_context->sample_fmt;
|
||||
module->sample_rate = port->format->es->audio.sample_rate;
|
||||
module->channels = port->format->es->audio.channels;
|
||||
module->bits_per_sample = port->format->es->audio.bits_per_sample;
|
||||
|
||||
port->component->priv->module->output_needs_configuring = 0;
|
||||
mmal_component_action_trigger(port->component);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T avcodec_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T avcodec_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
MMAL_QUEUE_T *queue;
|
||||
|
||||
if(port->type == MMAL_PORT_TYPE_OUTPUT)
|
||||
queue = module->queue_out;
|
||||
else if(port->type == MMAL_PORT_TYPE_INPUT)
|
||||
queue = module->queue_in;
|
||||
else
|
||||
return MMAL_EINVAL;
|
||||
|
||||
/* Flush buffers that our component is holding on to.
|
||||
* If the reading thread is holding onto a buffer it will send it back ASAP as well
|
||||
* so no need to care about that. */
|
||||
while((buffer = mmal_queue_get(queue)))
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T avcodec_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
/* Actions are prevented from running at that point so a flush
|
||||
* will return all buffers. */
|
||||
status = avcodec_port_flush(port);
|
||||
if(status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void avcodec_send_event_format_changed(MMAL_COMPONENT_T *component, MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer = NULL;
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event;
|
||||
|
||||
/* Get an event buffer */
|
||||
module->status = mmal_port_event_get(port, &buffer, MMAL_EVENT_FORMAT_CHANGED);
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("unable to get an event buffer");
|
||||
return;
|
||||
}
|
||||
event = mmal_event_format_changed_get(buffer);
|
||||
|
||||
/* Fill in the new format */
|
||||
mmal_format_copy(event->format, port->format);
|
||||
event->format->es->audio.sample_rate = module->codec_context->sample_rate;
|
||||
event->format->es->audio.channels = module->codec_context->channels;
|
||||
event->format->encoding = samplefmt_to_encoding(module->codec_context->sample_fmt);
|
||||
event->format->es->audio.bits_per_sample = samplefmt_to_sample_size(module->codec_context->sample_fmt);
|
||||
|
||||
/* Pass on the buffer requirements */
|
||||
event->buffer_num_min = port->buffer_num_min;
|
||||
event->buffer_size_min = port->buffer_size_min;
|
||||
event->buffer_size_recommended = event->buffer_size_min;
|
||||
event->buffer_num_recommended = port->buffer_num_recommended;
|
||||
|
||||
module->output_needs_configuring = 1;
|
||||
mmal_port_event_send(port, buffer);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static MMAL_STATUS_T avcodec_send_eos(MMAL_COMPONENT_T *component, MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *out = mmal_queue_get(module->queue_out);
|
||||
|
||||
if (!out)
|
||||
return MMAL_EAGAIN;
|
||||
|
||||
out->length = 0;
|
||||
out->flags = MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
mmal_port_buffer_header_callback(port, out);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static MMAL_STATUS_T avcodec_send_frame(MMAL_COMPONENT_T *component, MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *out;
|
||||
int size, samples;
|
||||
|
||||
/* Detect format changes */
|
||||
if (module->codec_context->channels != module->channels ||
|
||||
module->codec_context->sample_rate != module->sample_rate ||
|
||||
module->codec_context->sample_fmt != module->sample_fmt)
|
||||
{
|
||||
avcodec_send_event_format_changed(component, port);
|
||||
return MMAL_EAGAIN;
|
||||
}
|
||||
|
||||
out = mmal_queue_get(module->queue_out);
|
||||
if (!out)
|
||||
return MMAL_EAGAIN;
|
||||
|
||||
size = module->output_size;
|
||||
if (size > (int)out->alloc_size)
|
||||
size = out->alloc_size;
|
||||
|
||||
samples = size / module->channels * 8 / module->bits_per_sample;
|
||||
size = samples * module->channels * module->bits_per_sample / 8;
|
||||
out->length = size;
|
||||
out->pts = module->pts;
|
||||
out->flags = 0;
|
||||
memcpy(out->data, module->output, size);
|
||||
module->output_size -= size;
|
||||
module->output += size;
|
||||
|
||||
if (module->pts != MMAL_TIME_UNKNOWN)
|
||||
{
|
||||
module->last_pts = module->pts;
|
||||
module->samples_since_last_pts = 0;
|
||||
}
|
||||
module->pts = MMAL_TIME_UNKNOWN;
|
||||
module->samples_since_last_pts += samples;
|
||||
|
||||
if (out->pts == MMAL_TIME_UNKNOWN)
|
||||
out->pts = module->last_pts + module->samples_since_last_pts * 1000000 / module->sample_rate;
|
||||
|
||||
out->dts = out->pts;
|
||||
mmal_port_buffer_header_callback(port, out);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static MMAL_BOOL_T avaudio_do_processing(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *port_in = component->input[0];
|
||||
MMAL_PORT_T *port_out = component->output[0];
|
||||
MMAL_BUFFER_HEADER_T *in;
|
||||
AVPacket avpkt;
|
||||
int used = 0;
|
||||
|
||||
if (module->output_needs_configuring)
|
||||
return 0;
|
||||
|
||||
if (module->output_size &&
|
||||
avcodec_send_frame(component, port_out) != MMAL_SUCCESS)
|
||||
return 0;
|
||||
if (module->output_size)
|
||||
return 1;
|
||||
|
||||
/* Get input buffer to decode */
|
||||
in = mmal_queue_get(module->queue_in);
|
||||
if (!in)
|
||||
return 0;
|
||||
|
||||
/* Discard empty buffers. EOS buffers are not discarded since they will be used
|
||||
* to flush the codec. */
|
||||
if (!in->length && !(in->flags & MMAL_BUFFER_HEADER_FLAG_EOS))
|
||||
goto end;
|
||||
|
||||
/* Avcodec expects padded input data */
|
||||
if (in->length && !in->offset)
|
||||
{
|
||||
if(in->length + FF_INPUT_BUFFER_PADDING_SIZE <= in->alloc_size)
|
||||
memset(in->data + in->length, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
else
|
||||
LOG_WARN("could not pad buffer"); // Try to decode the data anyway
|
||||
}
|
||||
|
||||
/* The actual decoding */
|
||||
av_init_packet(&avpkt);
|
||||
avpkt.data = in->length ? in->data + in->offset : 0;
|
||||
avpkt.size = in->length;
|
||||
module->output_size = module->output_buffer_size;
|
||||
module->output = module->output_buffer;
|
||||
used = avcodec_decode_audio3(module->codec_context, (int16_t*)module->output,
|
||||
&module->output_size, &avpkt);
|
||||
|
||||
/* Check for errors */
|
||||
if (used < 0 || used > (int)in->length)
|
||||
{
|
||||
LOG_ERROR("decoding failed (%i), discarding buffer", used);
|
||||
used = in->length;
|
||||
}
|
||||
|
||||
module->pts = in->dts;
|
||||
if (module->pts == MMAL_TIME_UNKNOWN)
|
||||
module->pts = in->pts;
|
||||
|
||||
end:
|
||||
in->offset += used;
|
||||
in->length -= used;
|
||||
|
||||
if (in->length)
|
||||
{
|
||||
mmal_queue_put_back(module->queue_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We want to keep the EOS buffer until all the frames have been flushed */
|
||||
if ((in->flags & MMAL_BUFFER_HEADER_FLAG_EOS) &&
|
||||
module->output_size)
|
||||
{
|
||||
mmal_queue_put_back(module->queue_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Send EOS */
|
||||
if ((in->flags & MMAL_BUFFER_HEADER_FLAG_EOS) &&
|
||||
avcodec_send_eos(component, port_out) != MMAL_SUCCESS)
|
||||
{
|
||||
mmal_queue_put_back(module->queue_in, in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
in->offset = 0;
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void avcodec_do_processing_loop(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
while (avaudio_do_processing(component));
|
||||
}
|
||||
|
||||
/** Buffer sending */
|
||||
static MMAL_STATUS_T avcodec_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
if(port->type == MMAL_PORT_TYPE_OUTPUT) mmal_queue_put(module->queue_out, buffer);
|
||||
if(port->type == MMAL_PORT_TYPE_INPUT) mmal_queue_put(module->queue_in, buffer);
|
||||
mmal_component_action_trigger(port->component);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_avcodec(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
|
||||
/* Check we're the requested component */
|
||||
if(strcmp(name, "avcodec." MMAL_AUDIO_DECODE))
|
||||
return MMAL_ENOENT;
|
||||
|
||||
/* Allocate our module context */
|
||||
component->priv->module = module = vcos_calloc(1, sizeof(*module), "mmal module");
|
||||
if(!module)
|
||||
return MMAL_ENOENT;
|
||||
|
||||
/* Allocate the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, 0);
|
||||
if(!component->input) goto error;
|
||||
component->input_num = 1;
|
||||
component->output = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_OUTPUT, 0);
|
||||
if(!component->output) goto error;
|
||||
component->output_num = 1;
|
||||
|
||||
module->queue_in = mmal_queue_create();
|
||||
if(!module->queue_in) goto error;
|
||||
module->queue_out = mmal_queue_create();
|
||||
if(!module->queue_out) goto error;
|
||||
|
||||
module->codec_context = avcodec_alloc_context();
|
||||
if(!module->codec_context) goto error;
|
||||
|
||||
component->input[0]->priv->pf_set_format = avcodec_input_port_set_format;
|
||||
component->input[0]->priv->pf_enable = avcodec_port_enable;
|
||||
component->input[0]->priv->pf_disable = avcodec_port_disable;
|
||||
component->input[0]->priv->pf_flush = avcodec_port_flush;
|
||||
component->input[0]->priv->pf_send = avcodec_port_send;
|
||||
component->input[0]->buffer_num_min = INPUT_MIN_BUFFER_NUM;
|
||||
component->input[0]->buffer_num_recommended = INPUT_RECOMMENDED_BUFFER_NUM;
|
||||
component->input[0]->buffer_size_min = INPUT_MIN_BUFFER_SIZE;
|
||||
component->input[0]->buffer_size_recommended = INPUT_RECOMMENDED_BUFFER_SIZE;
|
||||
|
||||
component->output[0]->priv->pf_set_format = avcodec_output_port_set_format;
|
||||
component->output[0]->priv->pf_enable = avcodec_port_enable;
|
||||
component->output[0]->priv->pf_disable = avcodec_port_disable;
|
||||
component->output[0]->priv->pf_disable = avcodec_port_flush;
|
||||
component->output[0]->priv->pf_send = avcodec_port_send;
|
||||
component->output[0]->buffer_num_min = OUTPUT_MIN_BUFFER_NUM;
|
||||
component->output[0]->buffer_num_recommended = OUTPUT_RECOMMENDED_BUFFER_NUM;
|
||||
component->output[0]->buffer_size_min = OUTPUT_MIN_BUFFER_SIZE;
|
||||
component->output[0]->buffer_size_recommended = OUTPUT_RECOMMENDED_BUFFER_SIZE;
|
||||
|
||||
component->output[0]->format->type = MMAL_ES_TYPE_AUDIO;
|
||||
component->output[0]->format->encoding = MMAL_ENCODING_PCM_SIGNED_LE;
|
||||
|
||||
component->priv->pf_destroy = avcodec_component_destroy;
|
||||
|
||||
status = mmal_component_action_register(component, avcodec_do_processing_loop);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
avcodec_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct {
|
||||
uint32_t encoding;
|
||||
int codecid;
|
||||
} codec_to_encoding_table[] =
|
||||
{
|
||||
{MMAL_ENCODING_MP4A, CODEC_ID_AAC},
|
||||
{MMAL_ENCODING_MPGA, CODEC_ID_MP3},
|
||||
{MMAL_ENCODING_ALAW, CODEC_ID_PCM_ALAW},
|
||||
{MMAL_ENCODING_MULAW, CODEC_ID_PCM_MULAW},
|
||||
{MMAL_ENCODING_ADPCM_MS, CODEC_ID_ADPCM_MS},
|
||||
{MMAL_ENCODING_ADPCM_IMA_MS, CODEC_ID_ADPCM_IMA_WAV},
|
||||
{MMAL_ENCODING_ADPCM_SWF, CODEC_ID_ADPCM_SWF},
|
||||
{MMAL_ENCODING_WMA1, CODEC_ID_WMAV1},
|
||||
{MMAL_ENCODING_WMA2, CODEC_ID_WMAV2},
|
||||
{MMAL_ENCODING_WMAP, CODEC_ID_WMAPRO},
|
||||
{MMAL_ENCODING_WMAL, CODEC_ID_NONE},
|
||||
{MMAL_ENCODING_WMAV, CODEC_ID_WMAVOICE},
|
||||
{MMAL_ENCODING_AMRNB, CODEC_ID_AMR_NB},
|
||||
{MMAL_ENCODING_AMRWB, CODEC_ID_AMR_WB},
|
||||
{MMAL_ENCODING_AMRWBP, CODEC_ID_NONE},
|
||||
{MMAL_ENCODING_AC3, CODEC_ID_AC3},
|
||||
{MMAL_ENCODING_EAC3, CODEC_ID_EAC3},
|
||||
{MMAL_ENCODING_DTS, CODEC_ID_DTS},
|
||||
{MMAL_ENCODING_MLP, CODEC_ID_MLP},
|
||||
{MMAL_ENCODING_FLAC, CODEC_ID_FLAC},
|
||||
{MMAL_ENCODING_VORBIS, CODEC_ID_VORBIS},
|
||||
{MMAL_ENCODING_SPEEX, CODEC_ID_SPEEX},
|
||||
{MMAL_ENCODING_NELLYMOSER, CODEC_ID_NELLYMOSER},
|
||||
{MMAL_ENCODING_QCELP, CODEC_ID_QCELP},
|
||||
|
||||
{MMAL_ENCODING_UNKNOWN, CODEC_ID_NONE}
|
||||
};
|
||||
|
||||
static uint32_t encoding_to_codecid(uint32_t encoding)
|
||||
{
|
||||
unsigned int i;
|
||||
for(i = 0; codec_to_encoding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
|
||||
if(codec_to_encoding_table[i].encoding == encoding) break;
|
||||
return codec_to_encoding_table[i].codecid;
|
||||
}
|
||||
|
||||
static struct {
|
||||
uint32_t encoding;
|
||||
enum AVSampleFormat samplefmt;
|
||||
unsigned int sample_size;
|
||||
} samplefmt_to_encoding_table[] =
|
||||
{
|
||||
{MMAL_ENCODING_PCM_UNSIGNED, AV_SAMPLE_FMT_U8, 8},
|
||||
{MMAL_ENCODING_PCM_SIGNED, AV_SAMPLE_FMT_S16, 16},
|
||||
{MMAL_ENCODING_PCM_SIGNED, AV_SAMPLE_FMT_S32, 32},
|
||||
{MMAL_ENCODING_PCM_FLOAT, AV_SAMPLE_FMT_FLT, 32},
|
||||
{MMAL_ENCODING_PCM_FLOAT, AV_SAMPLE_FMT_DBL, 64},
|
||||
{MMAL_ENCODING_UNKNOWN, AV_SAMPLE_FMT_NONE, 1}
|
||||
};
|
||||
|
||||
static uint32_t samplefmt_to_encoding(enum AVSampleFormat samplefmt)
|
||||
{
|
||||
unsigned int i;
|
||||
for(i = 0; samplefmt_to_encoding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
|
||||
if(samplefmt_to_encoding_table[i].samplefmt == samplefmt) break;
|
||||
return samplefmt_to_encoding_table[i].encoding;
|
||||
}
|
||||
|
||||
static unsigned int samplefmt_to_sample_size(enum AVSampleFormat samplefmt)
|
||||
{
|
||||
unsigned int i;
|
||||
for(i = 0; samplefmt_to_encoding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
|
||||
if(samplefmt_to_encoding_table[i].samplefmt == samplefmt) break;
|
||||
return samplefmt_to_encoding_table[i].sample_size;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_avcodec_audio);
|
||||
void mmal_register_component_avcodec_audio(void)
|
||||
{
|
||||
avcodec_init();
|
||||
avcodec_register_all();
|
||||
|
||||
mmal_component_supplier_register("avcodec", mmal_component_create_avcodec);
|
||||
}
|
@ -1,586 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#define attribute_deprecated
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/mathematics.h"
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 52, 23, 0 )
|
||||
# include "libavformat/avformat.h"
|
||||
static AVPacket null_packet = {AV_NOPTS_VALUE, AV_NOPTS_VALUE};
|
||||
# define av_init_packet(a) *(a) = null_packet
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 53
|
||||
# define avcodec_decode_video2(a,b,c,d) avcodec_decode_video(a,b,c,(d)->data,(d)->size)
|
||||
#endif
|
||||
|
||||
/* Buffering requirements */
|
||||
#define INPUT_MIN_BUFFER_SIZE (800*1024)
|
||||
#define INPUT_MIN_BUFFER_NUM 1
|
||||
#define INPUT_RECOMMENDED_BUFFER_SIZE INPUT_MIN_BUFFER_SIZE
|
||||
#define INPUT_RECOMMENDED_BUFFER_NUM 10
|
||||
#define OUTPUT_MIN_BUFFER_NUM 1
|
||||
#define OUTPUT_RECOMMENDED_BUFFER_NUM 4
|
||||
|
||||
#define DEFAULT_WIDTH 320
|
||||
#define DEFAULT_HEIGHT 240
|
||||
|
||||
static uint32_t encoding_to_codecid(uint32_t encoding);
|
||||
static uint32_t pixfmt_to_encoding(enum PixelFormat);
|
||||
|
||||
/****************************/
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
MMAL_QUEUE_T *queue_in;
|
||||
MMAL_QUEUE_T *queue_out;
|
||||
|
||||
int picture_available;
|
||||
int64_t pts;
|
||||
int64_t dts;
|
||||
|
||||
AVFrame *picture;
|
||||
AVCodecContext *codec_context;
|
||||
AVCodec *codec;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
enum PixelFormat pix_fmt;
|
||||
AVPicture layout;
|
||||
unsigned int planes;
|
||||
|
||||
int frame_size;
|
||||
MMAL_BOOL_T output_needs_configuring;
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T avcodec_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
if (module->picture)
|
||||
av_free(module->picture);
|
||||
if (module->codec_context)
|
||||
{
|
||||
if(module->codec_context->extradata) vcos_free(module->codec_context->extradata);
|
||||
if(module->codec_context->codec) avcodec_close(module->codec_context);
|
||||
av_free(module->codec_context);
|
||||
}
|
||||
|
||||
if(module->queue_in) mmal_queue_destroy(module->queue_in);
|
||||
if(module->queue_out) mmal_queue_destroy(module->queue_out);
|
||||
vcos_free(module);
|
||||
if(component->input_num) mmal_ports_free(component->input, 1);
|
||||
if(component->output_num) mmal_ports_free(component->output, 1);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T avcodec_input_port_set_format(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
enum CodecID codec_id;
|
||||
AVCodec *codec;
|
||||
|
||||
codec_id = encoding_to_codecid(port->format->encoding);
|
||||
if(codec_id == CODEC_ID_NONE ||
|
||||
!(codec = avcodec_find_decoder(codec_id)))
|
||||
{
|
||||
LOG_ERROR("ffmpeg codec id %d (for %4.4s) not recognized",
|
||||
codec_id, (char *)&port->format->encoding);
|
||||
return MMAL_ENXIO;
|
||||
}
|
||||
|
||||
module->picture = avcodec_alloc_frame();
|
||||
|
||||
module->codec_context->width = port->format->es->video.width;
|
||||
module->codec_context->height = port->format->es->video.height;
|
||||
module->codec_context->extradata_size = port->format->extradata_size;
|
||||
module->codec_context->extradata =
|
||||
vcos_calloc(1, port->format->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE,
|
||||
"avcodec extradata");
|
||||
if(module->codec_context->extradata)
|
||||
memcpy(module->codec_context->extradata, port->format->extradata,
|
||||
port->format->extradata_size);
|
||||
|
||||
if (codec->capabilities & CODEC_CAP_TRUNCATED)
|
||||
module->codec_context->flags |= CODEC_FLAG_TRUNCATED;
|
||||
|
||||
if (avcodec_open(module->codec_context, codec) < 0)
|
||||
{
|
||||
LOG_ERROR("could not open codec");
|
||||
return MMAL_EIO;
|
||||
}
|
||||
|
||||
/* Set a default format */
|
||||
if (module->codec_context->pix_fmt == PIX_FMT_NONE)
|
||||
module->codec_context->pix_fmt = PIX_FMT_YUV420P;
|
||||
|
||||
/* Copy format to output */
|
||||
LOG_DEBUG("avcodec output format %i (%ix%i)", module->codec_context->pix_fmt,
|
||||
module->codec_context->width, module->codec_context->height);
|
||||
port->format->es->video.width = module->codec_context->width;
|
||||
port->format->es->video.height = module->codec_context->height;
|
||||
mmal_format_copy(component->output[0]->format, port->format);
|
||||
component->output[0]->format->encoding = pixfmt_to_encoding(module->codec_context->pix_fmt);
|
||||
if (!component->output[0]->format->es->video.width)
|
||||
component->output[0]->format->es->video.width = DEFAULT_WIDTH;
|
||||
if (!component->output[0]->format->es->video.height)
|
||||
component->output[0]->format->es->video.height = DEFAULT_HEIGHT;
|
||||
|
||||
component->output[0]->priv->pf_set_format(component->output[0]);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T avcodec_output_port_set_format(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
/* Format can only be set to what is output by the codec */
|
||||
if (pixfmt_to_encoding(module->codec_context->pix_fmt) != port->format->encoding)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
module->pix_fmt = module->codec_context->pix_fmt;
|
||||
module->width = port->format->es->video.width;
|
||||
module->height = port->format->es->video.height;
|
||||
|
||||
module->frame_size =
|
||||
avpicture_fill(&module->layout, 0, module->pix_fmt, module->width, module->height);
|
||||
if (module->frame_size < 0)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
/* Calculate the number of planes for this format */
|
||||
for (module->planes = 0; module->planes < 4; )
|
||||
if (!module->layout.data[module->planes++])
|
||||
break;
|
||||
|
||||
port->buffer_size_min = module->frame_size;
|
||||
port->component->priv->module->output_needs_configuring = 0;
|
||||
mmal_component_action_trigger(port->component);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T avcodec_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T avcodec_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
MMAL_QUEUE_T *queue;
|
||||
|
||||
if(port->type == MMAL_PORT_TYPE_OUTPUT)
|
||||
queue = module->queue_out;
|
||||
else if(port->type == MMAL_PORT_TYPE_INPUT)
|
||||
queue = module->queue_in;
|
||||
else
|
||||
return MMAL_EINVAL;
|
||||
|
||||
/* Flush buffers that our component is holding on to.
|
||||
* If the reading thread is holding onto a buffer it will send it back ASAP as well
|
||||
* so no need to care about that. */
|
||||
while((buffer = mmal_queue_get(queue)))
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T avcodec_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
/* Actions are prevented from running at that point so a flush
|
||||
* will return all buffers. */
|
||||
status = avcodec_port_flush(port);
|
||||
if(status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void avcodec_send_event_format_changed(MMAL_COMPONENT_T *component, MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer = NULL;
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event;
|
||||
|
||||
/* Get an event buffer */
|
||||
module->status = mmal_port_event_get(port, &buffer, MMAL_EVENT_FORMAT_CHANGED);
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("unable to get an event buffer");
|
||||
return;
|
||||
}
|
||||
event = mmal_event_format_changed_get(buffer);
|
||||
|
||||
/* Fill in the new format */
|
||||
mmal_format_copy(event->format, port->format);
|
||||
event->format->es->video.width = module->codec_context->width;
|
||||
event->format->es->video.height = module->codec_context->height;
|
||||
event->format->encoding = pixfmt_to_encoding(module->codec_context->pix_fmt);
|
||||
|
||||
/* Pass on the buffer requirements */
|
||||
event->buffer_num_min = port->buffer_num_min;
|
||||
event->buffer_size_min = module->codec_context->width * module->codec_context->height * 2;
|
||||
event->buffer_size_recommended = event->buffer_size_min;
|
||||
event->buffer_num_recommended = port->buffer_num_recommended;
|
||||
|
||||
module->output_needs_configuring = 1;
|
||||
mmal_port_event_send(port, buffer);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static MMAL_STATUS_T avcodec_send_eos(MMAL_COMPONENT_T *component, MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *out = mmal_queue_get(module->queue_out);
|
||||
|
||||
if (!out)
|
||||
return MMAL_EAGAIN;
|
||||
|
||||
out->length = 0;
|
||||
out->flags = MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
mmal_port_buffer_header_callback(port, out);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static MMAL_STATUS_T avcodec_send_picture(MMAL_COMPONENT_T *component, MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *out;
|
||||
int i, size;
|
||||
|
||||
/* Detect format changes */
|
||||
if (module->codec_context->width != module->width ||
|
||||
module->codec_context->height != module->height ||
|
||||
module->codec_context->pix_fmt != module->pix_fmt)
|
||||
{
|
||||
avcodec_send_event_format_changed(component, port);
|
||||
return MMAL_EAGAIN;
|
||||
}
|
||||
|
||||
out = mmal_queue_get(module->queue_out);
|
||||
if (!out)
|
||||
return MMAL_EAGAIN;
|
||||
|
||||
size = avpicture_layout((AVPicture *)module->picture, module->pix_fmt,
|
||||
module->width, module->height, out->data, out->alloc_size);
|
||||
if (size < 0)
|
||||
{
|
||||
mmal_queue_put_back(module->queue_out, out);
|
||||
LOG_ERROR("avpicture_layout failed: %i, %i, %i, %i",module->pix_fmt,
|
||||
module->width, module->height, out->alloc_size );
|
||||
mmal_event_error_send(component, MMAL_EINVAL);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
out->length = size;
|
||||
out->pts = module->pts;
|
||||
out->flags = 0;
|
||||
|
||||
out->type->video.planes = module->planes;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
out->type->video.offset[i] = (uint64_t)module->layout.data[i];
|
||||
out->type->video.pitch[i] = module->layout.linesize[i];
|
||||
}
|
||||
|
||||
mmal_port_buffer_header_callback(port, out);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static MMAL_BOOL_T avcodec_do_processing(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *port_in = component->input[0];
|
||||
MMAL_PORT_T *port_out = component->output[0];
|
||||
MMAL_BUFFER_HEADER_T *in;
|
||||
AVPacket avpkt;
|
||||
int used = 0;
|
||||
|
||||
if (module->output_needs_configuring)
|
||||
return 0;
|
||||
|
||||
if (module->picture_available &&
|
||||
avcodec_send_picture(component, port_out) != MMAL_SUCCESS)
|
||||
return 0;
|
||||
|
||||
module->picture_available = 0;
|
||||
|
||||
/* Get input buffer to decode */
|
||||
in = mmal_queue_get(module->queue_in);
|
||||
if (!in)
|
||||
return 0;
|
||||
|
||||
/* Discard empty buffers. EOS buffers are not discarded since they will be used
|
||||
* to flush the codec. */
|
||||
if (!in->length && !(in->flags & MMAL_BUFFER_HEADER_FLAG_EOS))
|
||||
goto end;
|
||||
|
||||
/* Avcodec expects padded input data */
|
||||
if (in->length && !in->offset)
|
||||
{
|
||||
if(in->length + FF_INPUT_BUFFER_PADDING_SIZE <= in->alloc_size)
|
||||
memset(in->data + in->length, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
else
|
||||
LOG_WARN("could not pad buffer"); // Try to decode the data anyway
|
||||
}
|
||||
|
||||
/* The actual decoding */
|
||||
module->codec_context->reordered_opaque = in->pts;
|
||||
av_init_packet(&avpkt);
|
||||
avpkt.data = in->length ? in->data + in->offset : 0;
|
||||
avpkt.size = in->length;
|
||||
used = avcodec_decode_video2(module->codec_context, module->picture,
|
||||
&module->picture_available, &avpkt);
|
||||
|
||||
/* Check for errors */
|
||||
if (used < 0 || used > (int)in->length)
|
||||
{
|
||||
LOG_ERROR("decoding failed (%i), discarding buffer", used);
|
||||
used = in->length;
|
||||
}
|
||||
|
||||
if (module->picture_available)
|
||||
{
|
||||
module->pts = module->picture->reordered_opaque;
|
||||
if (module->pts == MMAL_TIME_UNKNOWN)
|
||||
module->pts = in->dts;
|
||||
}
|
||||
|
||||
end:
|
||||
in->offset += used;
|
||||
in->length -= used;
|
||||
|
||||
if (in->length)
|
||||
{
|
||||
mmal_queue_put_back(module->queue_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We want to keep the EOS buffer until all the frames have been flushed */
|
||||
if ((in->flags & MMAL_BUFFER_HEADER_FLAG_EOS) &&
|
||||
module->picture_available)
|
||||
{
|
||||
mmal_queue_put_back(module->queue_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Send EOS */
|
||||
if ((in->flags & MMAL_BUFFER_HEADER_FLAG_EOS) &&
|
||||
avcodec_send_eos(component, port_out) != MMAL_SUCCESS)
|
||||
{
|
||||
mmal_queue_put_back(module->queue_in, in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
in->offset = 0;
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void avcodec_do_processing_loop(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
while (avcodec_do_processing(component));
|
||||
}
|
||||
|
||||
/** Buffer sending */
|
||||
static MMAL_STATUS_T avcodec_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
if(port->type == MMAL_PORT_TYPE_OUTPUT) mmal_queue_put(module->queue_out, buffer);
|
||||
if(port->type == MMAL_PORT_TYPE_INPUT) mmal_queue_put(module->queue_in, buffer);
|
||||
mmal_component_action_trigger(port->component);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_avcodec(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
|
||||
/* Check we're the requested component */
|
||||
if(strcmp(name, "avcodec." MMAL_VIDEO_DECODE))
|
||||
return MMAL_ENOENT;
|
||||
|
||||
/* Allocate our module context */
|
||||
component->priv->module = module = vcos_malloc(sizeof(*module), "mmal module");
|
||||
memset(module, 0, sizeof(*module));
|
||||
|
||||
/* Allocate the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, 0);
|
||||
if(!component->input) goto error;
|
||||
component->input_num = 1;
|
||||
component->output = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_OUTPUT, 0);
|
||||
if(!component->output) goto error;
|
||||
component->output_num = 1;
|
||||
|
||||
module->queue_in = mmal_queue_create();
|
||||
if(!module->queue_in) goto error;
|
||||
module->queue_out = mmal_queue_create();
|
||||
if(!module->queue_out) goto error;
|
||||
|
||||
module->codec_context = avcodec_alloc_context();
|
||||
if(!module->codec_context) goto error;
|
||||
|
||||
component->input[0]->priv->pf_set_format = avcodec_input_port_set_format;
|
||||
component->input[0]->priv->pf_enable = avcodec_port_enable;
|
||||
component->input[0]->priv->pf_disable = avcodec_port_disable;
|
||||
component->input[0]->priv->pf_flush = avcodec_port_flush;
|
||||
component->input[0]->priv->pf_send = avcodec_port_send;
|
||||
component->input[0]->buffer_num_min = INPUT_MIN_BUFFER_NUM;
|
||||
component->input[0]->buffer_num_recommended = INPUT_RECOMMENDED_BUFFER_NUM;
|
||||
component->input[0]->buffer_size_min = INPUT_MIN_BUFFER_SIZE;
|
||||
component->input[0]->buffer_size_recommended = INPUT_RECOMMENDED_BUFFER_SIZE;
|
||||
|
||||
component->output[0]->priv->pf_set_format = avcodec_output_port_set_format;
|
||||
component->output[0]->priv->pf_enable = avcodec_port_enable;
|
||||
component->output[0]->priv->pf_disable = avcodec_port_disable;
|
||||
component->output[0]->priv->pf_flush = avcodec_port_flush;
|
||||
component->output[0]->priv->pf_send = avcodec_port_send;
|
||||
component->output[0]->buffer_num_min = OUTPUT_MIN_BUFFER_NUM;
|
||||
component->output[0]->buffer_num_recommended = OUTPUT_RECOMMENDED_BUFFER_NUM;
|
||||
|
||||
component->output[0]->format->type = MMAL_ES_TYPE_VIDEO;
|
||||
component->output[0]->format->encoding = MMAL_ENCODING_I420;
|
||||
component->output[0]->format->es->video.width = DEFAULT_WIDTH;
|
||||
component->output[0]->format->es->video.height = DEFAULT_HEIGHT;
|
||||
|
||||
component->priv->pf_destroy = avcodec_component_destroy;
|
||||
|
||||
status = mmal_component_action_register(component, avcodec_do_processing_loop);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
avcodec_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct {
|
||||
uint32_t encoding;
|
||||
int codecid;
|
||||
} codec_to_encoding_table[] =
|
||||
{
|
||||
{MMAL_ENCODING_H263, CODEC_ID_H263},
|
||||
{MMAL_ENCODING_H264, CODEC_ID_H264},
|
||||
{MMAL_ENCODING_MP4V, CODEC_ID_MPEG4},
|
||||
{MMAL_ENCODING_MP2V, CODEC_ID_MPEG2VIDEO},
|
||||
{MMAL_ENCODING_MP1V, CODEC_ID_MPEG1VIDEO},
|
||||
{MMAL_ENCODING_WMV3, CODEC_ID_WMV3},
|
||||
{MMAL_ENCODING_WMV2, CODEC_ID_WMV2},
|
||||
{MMAL_ENCODING_WMV1, CODEC_ID_WMV1},
|
||||
{MMAL_ENCODING_WVC1, CODEC_ID_VC1},
|
||||
{MMAL_ENCODING_VP6, CODEC_ID_VP6},
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 52, 68, 2 )
|
||||
{MMAL_ENCODING_VP8, CODEC_ID_VP8},
|
||||
#endif
|
||||
{MMAL_ENCODING_THEORA, CODEC_ID_THEORA},
|
||||
|
||||
{MMAL_ENCODING_GIF, CODEC_ID_GIF},
|
||||
{MMAL_ENCODING_PNG, CODEC_ID_PNG},
|
||||
{MMAL_ENCODING_PPM, CODEC_ID_PPM},
|
||||
{MMAL_ENCODING_BMP, CODEC_ID_BMP},
|
||||
{MMAL_ENCODING_JPEG, CODEC_ID_MJPEG},
|
||||
|
||||
{MMAL_ENCODING_UNKNOWN, CODEC_ID_NONE}
|
||||
};
|
||||
|
||||
static uint32_t encoding_to_codecid(uint32_t encoding)
|
||||
{
|
||||
unsigned int i;
|
||||
for(i = 0; codec_to_encoding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
|
||||
if(codec_to_encoding_table[i].encoding == encoding) break;
|
||||
return codec_to_encoding_table[i].codecid;
|
||||
}
|
||||
|
||||
static struct {
|
||||
uint32_t encoding;
|
||||
enum PixelFormat pixfmt;
|
||||
} pixfmt_to_encoding_table[] =
|
||||
{
|
||||
{MMAL_ENCODING_I420, PIX_FMT_YUV420P},
|
||||
{MMAL_ENCODING_I422, PIX_FMT_YUV422P},
|
||||
{MMAL_ENCODING_I420, PIX_FMT_YUVJ420P}, // FIXME
|
||||
{MMAL_ENCODING_I422, PIX_FMT_YUVJ422P}, // FIXME
|
||||
{MMAL_ENCODING_RGB16, PIX_FMT_RGB565},
|
||||
{MMAL_ENCODING_BGR16, PIX_FMT_BGR565},
|
||||
{MMAL_ENCODING_RGB24, PIX_FMT_RGB24},
|
||||
{MMAL_ENCODING_BGR24, PIX_FMT_BGR24},
|
||||
{MMAL_ENCODING_ARGB, PIX_FMT_ARGB},
|
||||
{MMAL_ENCODING_RGBA, PIX_FMT_RGBA},
|
||||
{MMAL_ENCODING_ABGR, PIX_FMT_ABGR},
|
||||
{MMAL_ENCODING_BGRA, PIX_FMT_BGRA},
|
||||
{MMAL_ENCODING_UNKNOWN, PIX_FMT_NONE}
|
||||
};
|
||||
|
||||
static uint32_t pixfmt_to_encoding(enum PixelFormat pixfmt)
|
||||
{
|
||||
unsigned int i;
|
||||
for(i = 0; pixfmt_to_encoding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
|
||||
if(pixfmt_to_encoding_table[i].pixfmt == pixfmt) break;
|
||||
return pixfmt_to_encoding_table[i].encoding;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_avcodec);
|
||||
void mmal_register_component_avcodec(void)
|
||||
{
|
||||
avcodec_init();
|
||||
avcodec_register_all();
|
||||
|
||||
mmal_component_supplier_register("avcodec", mmal_component_create_avcodec);
|
||||
}
|
@ -1,900 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "util/mmal_util_rational.h"
|
||||
#include "util/mmal_list.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
|
||||
#define CLOCK_PORTS_NUM 5
|
||||
|
||||
#define MAX_CLOCK_EVENT_SLOTS 16
|
||||
|
||||
#define DEFAULT_FRAME_RATE 30 /* frames per second */
|
||||
#define DEFAULT_CLOCK_LATENCY 60000 /* microseconds */
|
||||
|
||||
#define FILTER_DURATION 2 /* seconds */
|
||||
#define MAX_FILTER_LENGTH 180 /* samples */
|
||||
|
||||
#define MAX_TIME (~(1LL << 63)) /* microseconds */
|
||||
#define MIN_TIME (1LL << 63) /* microseconds */
|
||||
|
||||
#define ABS(a) ((a) < 0 ? -(a) : (a))
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
/** Set to 1 to enable additional stream timing log
|
||||
* messages used for debugging the clock algorithm */
|
||||
#define ENABLE_ADDITIONAL_LOGGING 0
|
||||
static int clock_additional_logging = ENABLE_ADDITIONAL_LOGGING;
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef int64_t TIME_T;
|
||||
|
||||
typedef struct FILTER_T
|
||||
{
|
||||
uint32_t first; /**< index to the oldest sample */
|
||||
uint32_t last; /**< index to the most recent sample*/
|
||||
uint32_t count; /**< total number of samples in the filter */
|
||||
uint32_t length; /**< maximum number of samples */
|
||||
TIME_T sum; /**< sum of all samples currently in the filter */
|
||||
TIME_T h[MAX_FILTER_LENGTH]; /**< filter history */
|
||||
} FILTER_T;
|
||||
|
||||
/** Frame statistics for a stream */
|
||||
typedef struct CLOCK_STREAM_T
|
||||
{
|
||||
uint32_t id; /**< for debug purposes */
|
||||
|
||||
MMAL_BOOL_T started; /**< TRUE at least one frame has been received */
|
||||
|
||||
TIME_T pts; /**< most recent time-stamp seen */
|
||||
TIME_T stc; /**< most recent wall-time seen */
|
||||
|
||||
TIME_T mt_off; /**< offset of the current time stamp from the
|
||||
arrival time, i.e. PTS - STC */
|
||||
TIME_T mt_off_avg; /**< rolling average of the media time offset */
|
||||
TIME_T mt_off_std; /**< approximate standard deviation of the media
|
||||
time offset */
|
||||
|
||||
FILTER_T avg_filter; /**< moving average filter */
|
||||
FILTER_T std_filter; /**< (approximate) standard deviation filter */
|
||||
} CLOCK_STREAM_T;
|
||||
|
||||
/** Clock stream events */
|
||||
typedef enum CLOCK_STREAM_EVENT_T
|
||||
{
|
||||
CLOCK_STREAM_EVENT_NONE,
|
||||
CLOCK_STREAM_EVENT_STARTED, /**< first data received */
|
||||
CLOCK_STREAM_EVENT_DISCONT, /**< discontinuity detected */
|
||||
CLOCK_STREAM_EVENT_FRAME_COMPLETE, /**< complete frame received */
|
||||
} CLOCK_STREAM_EVENT_T;
|
||||
|
||||
/** Clock port event */
|
||||
typedef struct CLOCK_PORT_EVENT_T
|
||||
{
|
||||
MMAL_LIST_ELEMENT_T link; /**< must be first */
|
||||
MMAL_PORT_T *port; /**< clock port where the event occurred */
|
||||
MMAL_CLOCK_EVENT_T event; /**< event data */
|
||||
} CLOCK_PORT_EVENT_T;
|
||||
|
||||
/** Clock component context */
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status; /**< current status of the component */
|
||||
|
||||
MMAL_BOOL_T clock_discont; /**< TRUE -> clock discontinuity detected */
|
||||
|
||||
uint32_t stream_min_id; /**< id of selected minimum stream (debugging only) */
|
||||
uint32_t stream_max_id; /**< if of selected maximum stream (debugging only) */
|
||||
|
||||
TIME_T mt_off_target; /**< target clock media time offset */
|
||||
TIME_T mt_off_clk; /**< current clock media time offset */
|
||||
|
||||
TIME_T adj_p; /**< proportional clock adjustment */
|
||||
TIME_T adj_m; /**< clock adjustment factor (between 1 and 0) */
|
||||
TIME_T adj; /**< final clock adjustment */
|
||||
|
||||
TIME_T stc_at_update; /**< the value of the STC the last time the clocks
|
||||
were updated */
|
||||
|
||||
TIME_T frame_duration; /**< one frame period (microseconds) */
|
||||
MMAL_RATIONAL_T frame_rate; /**< frame rate set by the client */
|
||||
uint32_t frame_rate_log2; /**< frame rate expressed as a power of two */
|
||||
|
||||
MMAL_RATIONAL_T scale; /**< current clock scale factor */
|
||||
MMAL_BOOL_T pending_scale; /**< TRUE -> scale change is pending */
|
||||
|
||||
MMAL_CLOCK_LATENCY_T latency;
|
||||
MMAL_CLOCK_UPDATE_THRESHOLD_T update_threshold;
|
||||
MMAL_CLOCK_DISCONT_THRESHOLD_T discont_threshold;
|
||||
MMAL_CLOCK_REQUEST_THRESHOLD_T request_threshold;
|
||||
|
||||
/** Clock port events */
|
||||
struct
|
||||
{
|
||||
MMAL_LIST_T* queue; /**< pending events */
|
||||
MMAL_LIST_T* free; /**< available event slots */
|
||||
CLOCK_PORT_EVENT_T pool[MAX_CLOCK_EVENT_SLOTS];
|
||||
} events;
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
/** Clock port context */
|
||||
typedef struct MMAL_PORT_MODULE_T
|
||||
{
|
||||
CLOCK_STREAM_T *stream; /**< stream associated with this clock port */
|
||||
} MMAL_PORT_MODULE_T;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Round x up to the next power of two */
|
||||
static uint32_t next_pow2(uint32_t x)
|
||||
{
|
||||
x--;
|
||||
x = (x >> 1) | x;
|
||||
x = (x >> 2) | x;
|
||||
x = (x >> 4) | x;
|
||||
x = (x >> 8) | x;
|
||||
x = (x >> 16) | x;
|
||||
return ++x;
|
||||
}
|
||||
|
||||
/** Given a power of 2 value, return the number of bit shifts */
|
||||
static uint32_t pow2_shift(uint32_t x)
|
||||
{
|
||||
static const uint32_t BIT_POSITIONS[32] =
|
||||
{
|
||||
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
||||
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
||||
};
|
||||
|
||||
return BIT_POSITIONS[((x & -x) * 0x077CB531U) >> 27];
|
||||
}
|
||||
|
||||
/** Add 2 values with saturation */
|
||||
static inline TIME_T saturate_add(TIME_T a, TIME_T b)
|
||||
{
|
||||
TIME_T sum = a + b;
|
||||
if (a > 0 && b > 0 && sum < 0)
|
||||
sum = MAX_TIME;
|
||||
else if (a < 0 && b < 0 && sum > 0)
|
||||
sum = MIN_TIME;
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Filter reset */
|
||||
static void filter_init(FILTER_T *filter, uint32_t length)
|
||||
{
|
||||
memset(filter, 0, sizeof(*filter));
|
||||
filter->last = length - 1;
|
||||
filter->length = length;
|
||||
};
|
||||
|
||||
/** Increment filter index modulo the length */
|
||||
static inline uint32_t filter_index_wrap(uint32_t index, uint32_t length)
|
||||
{
|
||||
return (++index < length) ? index : 0;
|
||||
}
|
||||
|
||||
/** Remove the oldest sample from the filter */
|
||||
static void filter_drop(FILTER_T *filter)
|
||||
{
|
||||
if (!filter->count)
|
||||
return;
|
||||
|
||||
filter->sum -= filter->h[filter->first];
|
||||
filter->first = filter_index_wrap(filter->first, filter->length);
|
||||
filter->count--;
|
||||
}
|
||||
|
||||
/** Add a new sample (and drop the oldest when full) */
|
||||
static void filter_insert(FILTER_T *filter, TIME_T sample)
|
||||
{
|
||||
if (filter->count == filter->length)
|
||||
filter_drop(filter);
|
||||
|
||||
filter->last = filter_index_wrap(filter->last, filter->length);
|
||||
filter->h[filter->last] = sample;
|
||||
filter->sum = saturate_add(filter->sum, sample);
|
||||
filter->count++;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Create and initialise a clock stream */
|
||||
static MMAL_BOOL_T clock_create_stream(CLOCK_STREAM_T **stream, uint32_t id, uint32_t filter_length)
|
||||
{
|
||||
CLOCK_STREAM_T *s = vcos_calloc(1, sizeof(CLOCK_STREAM_T), "clock stream");
|
||||
if (!s)
|
||||
{
|
||||
LOG_ERROR("failed to allocate stream");
|
||||
return MMAL_FALSE;
|
||||
}
|
||||
|
||||
s->id = id;
|
||||
|
||||
filter_init(&s->avg_filter, filter_length);
|
||||
filter_init(&s->std_filter, filter_length);
|
||||
|
||||
*stream = s;
|
||||
return MMAL_TRUE;
|
||||
}
|
||||
|
||||
/** Flag this stream as started */
|
||||
static void clock_start_stream(CLOCK_STREAM_T *stream, TIME_T stc, TIME_T pts)
|
||||
{
|
||||
stream->started = MMAL_TRUE;
|
||||
stream->pts = pts;
|
||||
stream->stc = stc;
|
||||
}
|
||||
|
||||
/** Reset the internal state of a stream */
|
||||
static void clock_reset_stream(CLOCK_STREAM_T *stream)
|
||||
{
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
stream->pts = 0;
|
||||
stream->stc = 0;
|
||||
stream->mt_off = 0;
|
||||
stream->mt_off_avg = 0;
|
||||
stream->mt_off_std = 0;
|
||||
stream->started = MMAL_FALSE;
|
||||
|
||||
filter_init(&stream->avg_filter, stream->avg_filter.length);
|
||||
filter_init(&stream->std_filter, stream->std_filter.length);
|
||||
}
|
||||
|
||||
/** Update the internal state of a stream */
|
||||
static CLOCK_STREAM_EVENT_T clock_update_stream(CLOCK_STREAM_T *stream, TIME_T stc, TIME_T pts,
|
||||
TIME_T discont_threshold)
|
||||
{
|
||||
CLOCK_STREAM_EVENT_T event = CLOCK_STREAM_EVENT_NONE;
|
||||
TIME_T pts_delta, stc_delta;
|
||||
|
||||
if (pts == MMAL_TIME_UNKNOWN)
|
||||
{
|
||||
LOG_TRACE("ignoring invalid timestamp received at %"PRIi64, stc);
|
||||
return CLOCK_STREAM_EVENT_NONE;
|
||||
}
|
||||
|
||||
if (!stream->started)
|
||||
{
|
||||
LOG_TRACE("stream %d started %"PRIi64" %"PRIi64, stream->id, stc, pts);
|
||||
clock_start_stream(stream, stc, pts);
|
||||
return CLOCK_STREAM_EVENT_STARTED;
|
||||
}
|
||||
|
||||
/* XXX: This should really use the buffer flags to determine if a complete
|
||||
* frame has been received. However, not all clients set MMAL buffer flags
|
||||
* correctly (if at all). */
|
||||
pts_delta = pts - stream->pts;
|
||||
stc_delta = stc - stream->stc;
|
||||
|
||||
/* Check for discontinuities. */
|
||||
if ((ABS(pts_delta) > discont_threshold) || (ABS(stc_delta) > discont_threshold))
|
||||
{
|
||||
LOG_ERROR("discontinuity detected on stream %d %"PRIi64" %"PRIi64" %"PRIi64,
|
||||
stream->id, pts_delta, stc_delta, discont_threshold);
|
||||
return CLOCK_STREAM_EVENT_DISCONT;
|
||||
}
|
||||
|
||||
if (pts_delta)
|
||||
{
|
||||
/* A complete frame has now been received, so update the stream's notion of media time */
|
||||
stream->mt_off = stream->pts - stream->stc;
|
||||
|
||||
filter_insert(&stream->avg_filter, stream->mt_off);
|
||||
stream->mt_off_avg = stream->avg_filter.sum / stream->avg_filter.count;
|
||||
|
||||
filter_insert(&stream->std_filter, ABS(stream->mt_off - stream->mt_off_avg));
|
||||
stream->mt_off_std = stream->std_filter.sum / stream->std_filter.count;
|
||||
|
||||
LOG_TRACE("stream %d %"PRIi64" %"PRIi64" %"PRIi64" %"PRIi64,
|
||||
stream->id, stream->stc, stream->pts, stream->mt_off_avg, stream->mt_off);
|
||||
|
||||
event = CLOCK_STREAM_EVENT_FRAME_COMPLETE;
|
||||
}
|
||||
|
||||
stream->pts = pts;
|
||||
stream->stc = stc;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Start all enabled clock ports, making sure all use the same thresholds */
|
||||
static void clock_start_clocks(MMAL_COMPONENT_T *component, TIME_T media_time)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
{
|
||||
MMAL_PORT_T *port = component->clock[i];
|
||||
if (port->is_enabled)
|
||||
{
|
||||
LOG_TRACE("starting clock %d with time %"PRIi64, port->index, media_time);
|
||||
mmal_port_clock_reference_set(port, MMAL_TRUE);
|
||||
mmal_port_clock_media_time_set(port, media_time);
|
||||
mmal_port_clock_update_threshold_set(port, &module->update_threshold);
|
||||
mmal_port_clock_discont_threshold_set(port, &module->discont_threshold);
|
||||
mmal_port_clock_request_threshold_set(port, &module->request_threshold);
|
||||
mmal_port_clock_active_set(port, MMAL_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Stop (and flush) all enabled clock ports */
|
||||
static void clock_stop_clocks(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
{
|
||||
MMAL_PORT_T *port = component->clock[i];
|
||||
if (port->is_enabled)
|
||||
{
|
||||
LOG_TRACE("stopping clock %d", port->index);
|
||||
mmal_port_clock_request_flush(port);
|
||||
mmal_port_clock_active_set(port, MMAL_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset the internal state of all streams in order to rebase clock
|
||||
* adjustment calculations */
|
||||
static void clock_reset_clocks(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
clock_reset_stream(component->clock[i]->priv->module->stream);
|
||||
|
||||
module->clock_discont = MMAL_TRUE;
|
||||
}
|
||||
|
||||
/** Change the media-time for all enabled clock ports */
|
||||
static void clock_set_media_time(MMAL_COMPONENT_T *component, TIME_T media_time)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
{
|
||||
MMAL_PORT_T *port = component->clock[i];
|
||||
if (port->is_enabled)
|
||||
mmal_port_clock_media_time_set(port, media_time);
|
||||
}
|
||||
}
|
||||
|
||||
/** Change the scale for all clock ports */
|
||||
static void clock_set_scale(MMAL_COMPONENT_T *component, MMAL_RATIONAL_T scale)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
mmal_port_clock_scale_set(component->clock[i], scale);
|
||||
|
||||
component->priv->module->pending_scale = 0;
|
||||
}
|
||||
|
||||
/** Update the average and standard deviation calculations for all streams
|
||||
* (dropping samples where necessary) and return the minimum and maximum
|
||||
* streams */
|
||||
static MMAL_BOOL_T clock_get_mt_off_avg(MMAL_COMPONENT_T *component, TIME_T stc,
|
||||
CLOCK_STREAM_T **minimum, CLOCK_STREAM_T **maximum)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
TIME_T drop_threshold = 6 * module->frame_duration;
|
||||
TIME_T reset_threshold = module->latency.target << 1;
|
||||
TIME_T avg_min = MAX_TIME;
|
||||
TIME_T avg_max = MIN_TIME;
|
||||
TIME_T avg_bias;
|
||||
TIME_T stc_delta;
|
||||
unsigned i;
|
||||
|
||||
*minimum = 0;
|
||||
*maximum = 0;
|
||||
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
{
|
||||
CLOCK_STREAM_T *stream = component->clock[i]->priv->module->stream;
|
||||
if (stream)
|
||||
{
|
||||
stc_delta = stc - stream->stc;
|
||||
|
||||
/* Drop samples from the moving average and standard deviation filters */
|
||||
if (stc_delta > reset_threshold)
|
||||
{
|
||||
filter_init(&stream->avg_filter, stream->avg_filter.length);
|
||||
filter_init(&stream->std_filter, stream->std_filter.length);
|
||||
LOG_TRACE("reset stream %d filters due to stc_delta %"PRIi64, stream->id, stc_delta);
|
||||
}
|
||||
else if (stc_delta > drop_threshold)
|
||||
{
|
||||
filter_drop(&stream->avg_filter);
|
||||
filter_drop(&stream->std_filter);
|
||||
LOG_TRACE("drop stream %d filter samples due to stc_delta %"PRIi64, stream->id, stc_delta);
|
||||
}
|
||||
|
||||
/* No point in continuing if filters are empty */
|
||||
if (!stream->avg_filter.count)
|
||||
continue;
|
||||
|
||||
/* Calculate new average and standard deviation for the stream */
|
||||
stream->mt_off_avg = stream->avg_filter.sum / stream->avg_filter.count;
|
||||
stream->mt_off_std = stream->std_filter.sum / stream->std_filter.count;
|
||||
|
||||
/* Select the minimum and maximum average between all active streams */
|
||||
avg_bias = (stream->avg_filter.length - stream->avg_filter.count) * ABS(stream->mt_off_avg) / stream->avg_filter.length;
|
||||
if ((stream->mt_off_avg + avg_bias) < avg_min)
|
||||
{
|
||||
avg_min = stream->mt_off_avg;
|
||||
*minimum = stream;
|
||||
LOG_TRACE("found min on %d mt_off_avg %"PRIi64" mt_off_std %"PRIi64" avg_bias %"PRIi64" count %d",
|
||||
stream->id, stream->mt_off_avg, stream->mt_off_std, avg_bias, stream->avg_filter.count);
|
||||
}
|
||||
if ((stream->mt_off_avg - avg_bias) > avg_max)
|
||||
{
|
||||
avg_max = stream->mt_off_avg;
|
||||
*maximum = stream;
|
||||
LOG_TRACE("found max on %d mt_off_avg %"PRIi64" mt_off_std %"PRIi64" avg_bias %"PRIi64" count %d",
|
||||
stream->id, stream->mt_off_avg, stream->mt_off_std, avg_bias, stream->avg_filter.count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (*minimum) && (*maximum);
|
||||
}
|
||||
|
||||
/** Adjust the media-time of the playback clocks based on current timing statistics */
|
||||
static void clock_adjust_clocks(MMAL_COMPONENT_T *component, TIME_T stc)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
CLOCK_STREAM_T *stream_min;
|
||||
CLOCK_STREAM_T *stream_max;
|
||||
TIME_T mt_off_clk;
|
||||
TIME_T stc_prev;
|
||||
|
||||
if (!clock_get_mt_off_avg(component, stc, &stream_min, &stream_max))
|
||||
return;
|
||||
|
||||
module->stream_min_id = stream_min->id;
|
||||
module->stream_max_id = stream_max->id;
|
||||
|
||||
/* Calculate the actual media-time offset seen by the clock */
|
||||
mt_off_clk = mmal_port_clock_media_time_get(component->clock[0]) - stc;
|
||||
|
||||
stc_prev = module->stc_at_update;
|
||||
module->stc_at_update = stc;
|
||||
|
||||
/* If there has been a discontinuity, restart the clock,
|
||||
* else use the clock control loop to apply a clock adjustment */
|
||||
if (module->clock_discont)
|
||||
{
|
||||
module->clock_discont = MMAL_FALSE;
|
||||
|
||||
module->mt_off_clk = stream_min->mt_off_avg - module->latency.target;
|
||||
module->mt_off_target = module->mt_off_clk;
|
||||
|
||||
clock_stop_clocks(component);
|
||||
clock_start_clocks(component, module->mt_off_clk + stc);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Determine the new clock target */
|
||||
TIME_T mt_off_target_max = stream_max->mt_off_avg - module->latency.target;
|
||||
TIME_T mt_off_target_min = stream_min->mt_off_avg - module->frame_duration;
|
||||
module->mt_off_target = MIN(mt_off_target_max, mt_off_target_min);
|
||||
|
||||
/* Calculate the proportional adjustment, capped by the attack rate
|
||||
* set by the client */
|
||||
TIME_T stc_delta = (stc > stc_prev) ? (stc - stc_prev) : 0;
|
||||
TIME_T adj_p_max = stc_delta * module->latency.attack_rate / module->latency.attack_period;
|
||||
|
||||
module->adj_p = module->mt_off_target - module->mt_off_clk;
|
||||
if (module->adj_p < -adj_p_max)
|
||||
module->adj_p = -adj_p_max;
|
||||
else if (module->adj_p > adj_p_max)
|
||||
module->adj_p = adj_p_max;
|
||||
|
||||
/* Calculate the confidence of the adjustment using the approximate
|
||||
* standard deviation for the selected stream:
|
||||
*
|
||||
* adj_m = 1.0 - STD * FPS / 4
|
||||
*
|
||||
* The adjustment factor is scaled up by 2^20 which is an approximation
|
||||
* of 1000000 (microseconds per second) and the frame rate is assumed
|
||||
* to be either 32 or 64 which are approximations for 24/25/30 and 60
|
||||
* fps to avoid divisions. This has a lower limit of 0. */
|
||||
module->adj_m =
|
||||
MAX((1 << 20) - ((stream_min->mt_off_std << module->frame_rate_log2) >> 2), 0);
|
||||
|
||||
/* Modulate the proportional adjustment by the sample confidence
|
||||
* and apply the adjustment to the current clock */
|
||||
module->adj = (module->adj_p * module->adj_m) >> 20;
|
||||
module->adj = (module->adj * (stream_min->avg_filter.count << 8) / stream_min->avg_filter.length) >> 8;
|
||||
module->mt_off_clk += module->adj;
|
||||
|
||||
clock_set_media_time(component, module->mt_off_clk + stc);
|
||||
}
|
||||
|
||||
/* Any pending clock scale changes can now be applied */
|
||||
if (component->priv->module->pending_scale)
|
||||
clock_set_scale(component, component->priv->module->scale);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void clock_process_stream_event(MMAL_COMPONENT_T *component, CLOCK_STREAM_T *stream,
|
||||
CLOCK_STREAM_EVENT_T event, TIME_T stc)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case CLOCK_STREAM_EVENT_FRAME_COMPLETE:
|
||||
clock_adjust_clocks(component, stc);
|
||||
if (clock_additional_logging)
|
||||
{
|
||||
VCOS_ALERT("STRM_%d %"PRIi64" %"PRIi64" %"PRIi64" %"PRIi64" %"PRIi64" %"PRIi64" %d %"
|
||||
PRIi64" %"PRIi64" %"PRIi64" %"PRIi64" %"PRIi64" %u %u",
|
||||
stream->id, stream->stc, stream->pts, stream->mt_off_avg, stream->mt_off,
|
||||
stream->mt_off_std, ABS(stream->mt_off - stream->mt_off_avg), stream->avg_filter.count,
|
||||
module->mt_off_clk, module->mt_off_target, module->adj_p, module->adj_m, module->adj,
|
||||
module->stream_min_id, module->stream_max_id);
|
||||
}
|
||||
break;
|
||||
case CLOCK_STREAM_EVENT_DISCONT:
|
||||
clock_reset_clocks(component);
|
||||
break;
|
||||
default:
|
||||
/* ignore all other events */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Handler for input buffer events */
|
||||
static void clock_process_input_buffer_info_event(MMAL_COMPONENT_T *component, MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_BUFFER_INFO_T *info)
|
||||
{
|
||||
CLOCK_STREAM_EVENT_T stream_event = CLOCK_STREAM_EVENT_NONE;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_MODULE_T *port_module = port->priv->module;
|
||||
TIME_T stc = (TIME_T)((uint64_t)info->arrival_time);
|
||||
TIME_T pts = info->time_stamp;
|
||||
|
||||
LOG_TRACE("port %d %"PRIi64" %"PRIi64, port->index, stc, pts);
|
||||
|
||||
if (!port_module->stream)
|
||||
{
|
||||
/* First data received for this stream */
|
||||
uint32_t filter_length = module->frame_rate.num * FILTER_DURATION /
|
||||
module->frame_rate.den;
|
||||
if (!clock_create_stream(&port_module->stream, port->index, filter_length))
|
||||
return;
|
||||
}
|
||||
|
||||
stream_event = clock_update_stream(port_module->stream, stc, pts, module->discont_threshold.threshold);
|
||||
|
||||
clock_process_stream_event(component, port_module->stream, stream_event, stc);
|
||||
}
|
||||
|
||||
/** Handler for clock scale events */
|
||||
static void clock_process_scale_event(MMAL_COMPONENT_T *component, MMAL_RATIONAL_T scale)
|
||||
{
|
||||
/* When pausing the clock (i.e. scale = 0.0), apply the scale change
|
||||
* immediately. However, when resuming the clock (i.e. scale = 1.0),
|
||||
* the scale change can only be applied the next time new buffer timing
|
||||
* information is received. This ensures that clocks resume with the
|
||||
* correct media-time. */
|
||||
if (scale.num == 0)
|
||||
{
|
||||
component->priv->module->scale = scale;
|
||||
clock_set_scale(component, scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only support scale == 1.0 */
|
||||
if (!mmal_rational_equal(component->priv->module->scale, scale) &&
|
||||
(scale.num == scale.den))
|
||||
{
|
||||
component->priv->module->scale = scale;
|
||||
component->priv->module->pending_scale = 1;
|
||||
clock_reset_clocks(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Handler for update threshold events */
|
||||
static void clock_process_update_threshold_event(MMAL_COMPONENT_T *component, const MMAL_CLOCK_UPDATE_THRESHOLD_T *threshold)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
component->priv->module->update_threshold = *threshold;
|
||||
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
mmal_port_clock_update_threshold_set(component->clock[i], threshold);
|
||||
}
|
||||
|
||||
/** Handler for discontinuity threshold events */
|
||||
static void clock_process_discont_threshold_event(MMAL_COMPONENT_T *component, const MMAL_CLOCK_DISCONT_THRESHOLD_T *threshold)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
component->priv->module->discont_threshold = *threshold;
|
||||
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
mmal_port_clock_discont_threshold_set(component->clock[i], threshold);
|
||||
}
|
||||
|
||||
/** Handler for request threshold events */
|
||||
static void clock_process_request_threshold_event(MMAL_COMPONENT_T *component, const MMAL_CLOCK_REQUEST_THRESHOLD_T *threshold)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
component->priv->module->request_threshold = *threshold;
|
||||
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
mmal_port_clock_request_threshold_set(component->clock[i], threshold);
|
||||
}
|
||||
|
||||
/** Handler for latency events */
|
||||
static void clock_process_latency_event(MMAL_COMPONENT_T *component, const MMAL_CLOCK_LATENCY_T *latency)
|
||||
{
|
||||
component->priv->module->latency = *latency;
|
||||
|
||||
clock_reset_clocks(component);
|
||||
}
|
||||
|
||||
/** Add a clock port event to the queue and trigger the action thread */
|
||||
static MMAL_STATUS_T clock_event_queue(MMAL_COMPONENT_T *component, MMAL_PORT_T *port, const MMAL_CLOCK_EVENT_T *event)
|
||||
{
|
||||
CLOCK_PORT_EVENT_T *slot = (CLOCK_PORT_EVENT_T*)mmal_list_pop_front(component->priv->module->events.free);
|
||||
if (!slot)
|
||||
{
|
||||
LOG_ERROR("no event slots available");
|
||||
return MMAL_ENOSPC;
|
||||
}
|
||||
|
||||
slot->port = port;
|
||||
slot->event = *event;
|
||||
mmal_list_push_back(component->priv->module->events.queue, &slot->link);
|
||||
|
||||
return mmal_component_action_trigger(component);
|
||||
}
|
||||
|
||||
/** Get the next clock port event in the queue */
|
||||
static MMAL_STATUS_T clock_event_dequeue(MMAL_COMPONENT_T *component, CLOCK_PORT_EVENT_T *port_event)
|
||||
{
|
||||
CLOCK_PORT_EVENT_T *slot = (CLOCK_PORT_EVENT_T*)mmal_list_pop_front(component->priv->module->events.queue);
|
||||
if (!slot)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
port_event->port = slot->port;
|
||||
port_event->event = slot->event;
|
||||
mmal_list_push_back(component->priv->module->events.free, &slot->link);
|
||||
|
||||
if (port_event->event.buffer)
|
||||
{
|
||||
port_event->event.buffer->length = 0;
|
||||
mmal_port_buffer_header_callback(port_event->port, port_event->event.buffer);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Event callback from a clock port */
|
||||
static void clock_event_cb(MMAL_PORT_T *port, const MMAL_CLOCK_EVENT_T *event)
|
||||
{
|
||||
clock_event_queue(port->component, port, event);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Actual processing function */
|
||||
static MMAL_BOOL_T clock_do_processing(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
CLOCK_PORT_EVENT_T port_event;
|
||||
|
||||
if (clock_event_dequeue(component, &port_event) != MMAL_SUCCESS)
|
||||
return MMAL_FALSE; /* No more external events to process */
|
||||
|
||||
/* Process external events (coming from clock ports) */
|
||||
switch (port_event.event.id)
|
||||
{
|
||||
case MMAL_CLOCK_EVENT_SCALE:
|
||||
clock_process_scale_event(component, port_event.event.data.scale);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_UPDATE_THRESHOLD:
|
||||
clock_process_update_threshold_event(component, &port_event.event.data.update_threshold);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_DISCONT_THRESHOLD:
|
||||
clock_process_discont_threshold_event(component, &port_event.event.data.discont_threshold);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_REQUEST_THRESHOLD:
|
||||
clock_process_request_threshold_event(component, &port_event.event.data.request_threshold);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_LATENCY:
|
||||
clock_process_latency_event(component, &port_event.event.data.latency);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_INPUT_BUFFER_INFO:
|
||||
clock_process_input_buffer_info_event(component, port_event.port, &port_event.event.data.buffer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return MMAL_TRUE;
|
||||
}
|
||||
|
||||
/** Component action thread */
|
||||
static void clock_do_processing_loop(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
while (clock_do_processing(component));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Set a parameter on the clock component's control port */
|
||||
static MMAL_STATUS_T clock_control_parameter_set(MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_STATUS_T status = MMAL_SUCCESS;
|
||||
|
||||
switch (param->id)
|
||||
{
|
||||
case MMAL_PARAMETER_CLOCK_FRAME_RATE:
|
||||
{
|
||||
const MMAL_PARAMETER_FRAME_RATE_T *p = (const MMAL_PARAMETER_FRAME_RATE_T *)param;
|
||||
module->frame_rate = p->frame_rate;
|
||||
/* XXX: take frame_rate.den into account */
|
||||
module->frame_rate_log2 = pow2_shift(next_pow2(module->frame_rate.num));
|
||||
module->frame_duration = p->frame_rate.den * 1000000 / p->frame_rate.num;
|
||||
LOG_TRACE("frame rate %d/%d (%u) duration %"PRIi64,
|
||||
module->frame_rate.num, module->frame_rate.den,
|
||||
module->frame_rate_log2, module->frame_duration);
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_LATENCY:
|
||||
{
|
||||
/* Changing the latency setting requires a reset of the clock algorithm, but
|
||||
* that can only be safely done from within the component's worker thread.
|
||||
* So, queue the new latency setting as a clock event. */
|
||||
const MMAL_PARAMETER_CLOCK_LATENCY_T *p = (const MMAL_PARAMETER_CLOCK_LATENCY_T *)param;
|
||||
MMAL_CLOCK_EVENT_T event = { MMAL_CLOCK_EVENT_LATENCY, MMAL_CLOCK_EVENT_MAGIC };
|
||||
|
||||
LOG_TRACE("latency target %"PRIi64" attack %"PRIi64"/%"PRIi64,
|
||||
p->value.target, p->value.attack_rate, p->value.attack_period);
|
||||
|
||||
event.data.latency = p->value;
|
||||
status = clock_event_queue(port->component, port, &event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("parameter not supported (0x%x)", param->id);
|
||||
status = MMAL_ENOSYS;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T clock_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
unsigned int i;
|
||||
|
||||
if (module->events.free)
|
||||
mmal_list_destroy(module->events.free);
|
||||
|
||||
if (module->events.queue)
|
||||
mmal_list_destroy(module->events.queue);
|
||||
|
||||
if (component->clock_num)
|
||||
{
|
||||
for (i = 0; i < component->clock_num; ++i)
|
||||
vcos_free(component->clock[i]->priv->module->stream);
|
||||
|
||||
mmal_ports_clock_free(component->clock, component->clock_num);
|
||||
}
|
||||
|
||||
vcos_free(module);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create an instance of a clock component */
|
||||
static MMAL_STATUS_T mmal_component_create_clock(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
int i;
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
MMAL_PARAM_UNUSED(name);
|
||||
|
||||
/* Allocate the context for our module */
|
||||
component->priv->module = module = vcos_malloc(sizeof(*module), "mmal module");
|
||||
if (!module)
|
||||
return MMAL_ENOMEM;
|
||||
memset(module, 0, sizeof(*module));
|
||||
|
||||
component->priv->pf_destroy = clock_component_destroy;
|
||||
|
||||
/* Create the clock ports (clock ports are managed by the framework) */
|
||||
component->clock = mmal_ports_clock_alloc(component, CLOCK_PORTS_NUM,
|
||||
sizeof(MMAL_PORT_MODULE_T), clock_event_cb);
|
||||
if (!component->clock)
|
||||
goto error;
|
||||
component->clock_num = CLOCK_PORTS_NUM;
|
||||
|
||||
component->control->priv->pf_parameter_set = clock_control_parameter_set;
|
||||
|
||||
/* Setup event slots */
|
||||
module->events.free = mmal_list_create();
|
||||
module->events.queue = mmal_list_create();
|
||||
if (!module->events.free || !module->events.queue)
|
||||
{
|
||||
LOG_ERROR("failed to create list %p %p", module->events.free, module->events.queue);
|
||||
goto error;
|
||||
}
|
||||
for (i = 0; i < MAX_CLOCK_EVENT_SLOTS; ++i)
|
||||
mmal_list_push_back(module->events.free, &module->events.pool[i].link);
|
||||
|
||||
component->priv->priority = VCOS_THREAD_PRI_REALTIME;
|
||||
status = mmal_component_action_register(component, clock_do_processing_loop);
|
||||
|
||||
module->clock_discont = MMAL_TRUE;
|
||||
module->frame_rate.num = DEFAULT_FRAME_RATE;
|
||||
module->frame_rate.den = 1;
|
||||
|
||||
module->scale = mmal_port_clock_scale_get(component->clock[0]);
|
||||
|
||||
memset(&module->latency, 0, sizeof(module->latency));
|
||||
module->latency.target = DEFAULT_CLOCK_LATENCY;
|
||||
|
||||
mmal_port_clock_update_threshold_get(component->clock[0], &module->update_threshold);
|
||||
mmal_port_clock_discont_threshold_get(component->clock[0], &module->discont_threshold);
|
||||
mmal_port_clock_request_threshold_get(component->clock[0], &module->request_threshold);
|
||||
|
||||
return status;
|
||||
|
||||
error:
|
||||
clock_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_clock);
|
||||
void mmal_register_component_clock(void)
|
||||
{
|
||||
mmal_component_supplier_register("clock", mmal_component_create_clock);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,327 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status; /**< current status of the component */
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
typedef struct MMAL_PORT_MODULE_T
|
||||
{
|
||||
MMAL_QUEUE_T *queue; /**< queue for the buffers sent to the ports */
|
||||
MMAL_BOOL_T needs_configuring; /**< port is waiting for a format commit */
|
||||
|
||||
} MMAL_PORT_MODULE_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Actual processing function */
|
||||
static MMAL_BOOL_T copy_do_processing(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *port_in = component->input[0];
|
||||
MMAL_PORT_T *port_out = component->output[0];
|
||||
MMAL_BUFFER_HEADER_T *in, *out;
|
||||
|
||||
if (port_out->priv->module->needs_configuring)
|
||||
return 0;
|
||||
|
||||
in = mmal_queue_get(port_in->priv->module->queue);
|
||||
if (!in)
|
||||
return 0;
|
||||
|
||||
/* Handle event buffers */
|
||||
if (in->cmd)
|
||||
{
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(in);
|
||||
if (event)
|
||||
{
|
||||
module->status = mmal_format_full_copy(port_in->format, event->format);
|
||||
if (module->status == MMAL_SUCCESS)
|
||||
module->status = port_in->priv->pf_set_format(port_in);
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("format not set on port %s %p (%i)", port_in->name, port_in, module->status);
|
||||
if (mmal_event_error_send(component, module->status) != MMAL_SUCCESS)
|
||||
LOG_ERROR("unable to send an error event buffer");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("discarding event %i on port %s %p", (int)in->cmd, port_in->name, port_in);
|
||||
}
|
||||
|
||||
in->length = 0;
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Don't do anything if we've already seen an error */
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
mmal_queue_put_back(port_in->priv->module->queue, in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
out = mmal_queue_get(port_out->priv->module->queue);
|
||||
if (!out)
|
||||
{
|
||||
mmal_queue_put_back(port_in->priv->module->queue, in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sanity check the output buffer is big enough */
|
||||
if (out->alloc_size < in->length)
|
||||
{
|
||||
module->status = MMAL_EINVAL;
|
||||
if (mmal_event_error_send(component, module->status) != MMAL_SUCCESS)
|
||||
LOG_ERROR("unable to send an error event buffer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mmal_buffer_header_mem_lock(out);
|
||||
mmal_buffer_header_mem_lock(in);
|
||||
memcpy(out->data, in->data + in->offset, in->length);
|
||||
mmal_buffer_header_mem_unlock(in);
|
||||
mmal_buffer_header_mem_unlock(out);
|
||||
out->length = in->length;
|
||||
out->offset = 0;
|
||||
out->flags = in->flags;
|
||||
out->pts = in->pts;
|
||||
out->dts = in->dts;
|
||||
*out->type = *in->type;
|
||||
|
||||
/* Send buffers back */
|
||||
in->length = 0;
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
mmal_port_buffer_header_callback(port_out, out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void copy_do_processing_loop(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
while (copy_do_processing(component));
|
||||
}
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T copy_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < component->input_num; i++)
|
||||
if(component->input[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->input[i]->priv->module->queue);
|
||||
if(component->input_num)
|
||||
mmal_ports_free(component->input, component->input_num);
|
||||
|
||||
for(i = 0; i < component->output_num; i++)
|
||||
if(component->output[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->output[i]->priv->module->queue);
|
||||
if(component->output_num)
|
||||
mmal_ports_free(component->output, component->output_num);
|
||||
|
||||
vcos_free(component->priv->module);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T copy_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
|
||||
/* We need to propagate the buffer requirements when the input port is
|
||||
* enabled */
|
||||
if (port->type == MMAL_PORT_TYPE_INPUT)
|
||||
return port->priv->pf_set_format(port);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T copy_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PORT_MODULE_T *port_module = port->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/* Flush buffers that our component is holding on to */
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
while(buffer)
|
||||
{
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T copy_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
/* We just need to flush our internal queue */
|
||||
return copy_port_flush(port);
|
||||
}
|
||||
|
||||
/** Send a buffer header to a port */
|
||||
static MMAL_STATUS_T copy_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
mmal_queue_put(port->priv->module->queue, buffer);
|
||||
mmal_component_action_trigger(port->component);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on input port */
|
||||
static MMAL_STATUS_T copy_input_port_format_commit(MMAL_PORT_T *in)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = in->component;
|
||||
MMAL_PORT_T *out = component->output[0];
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
/* Check if there's anything to propagate to the output port */
|
||||
/* The format of the output port needs to match the input port */
|
||||
if (!mmal_format_compare(in->format, out->format) &&
|
||||
out->buffer_size_min == out->buffer_size_recommended &&
|
||||
out->buffer_size_min == MMAL_MAX(in->buffer_size_min, in->buffer_size))
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
/* If the output port is not enabled we just need to update its format.
|
||||
* Otherwise we'll have to trigger a format changed event for it. */
|
||||
if (!out->is_enabled)
|
||||
{
|
||||
out->buffer_size_min = out->buffer_size_recommended =
|
||||
MMAL_MAX(in->buffer_size, in->buffer_size_min);
|
||||
return mmal_format_full_copy(out->format, in->format);
|
||||
}
|
||||
|
||||
/* Send an event on the output port */
|
||||
status = mmal_port_event_get(out, &buffer, MMAL_EVENT_FORMAT_CHANGED);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("unable to get an event buffer");
|
||||
return status;
|
||||
}
|
||||
|
||||
event = mmal_event_format_changed_get(buffer);
|
||||
mmal_format_copy(event->format, in->format); /* FIXME: can full copy be done ? */
|
||||
|
||||
/* Pass on the buffer requirements */
|
||||
event->buffer_num_min = out->buffer_num_min;
|
||||
event->buffer_num_recommended = out->buffer_num_recommended;
|
||||
event->buffer_size_min = event->buffer_size_recommended =
|
||||
MMAL_MAX(in->buffer_size_min, in->buffer_size);
|
||||
|
||||
out->priv->module->needs_configuring = 1;
|
||||
mmal_port_event_send(out, buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Set format on output port */
|
||||
static MMAL_STATUS_T copy_output_port_format_commit(MMAL_PORT_T *out)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = out->component;
|
||||
MMAL_PORT_T *in = component->input[0];
|
||||
|
||||
/* The format of the output port needs to match the input port */
|
||||
if (mmal_format_compare(out->format, in->format))
|
||||
return MMAL_EINVAL;
|
||||
|
||||
out->priv->module->needs_configuring = 0;
|
||||
mmal_component_action_trigger(out->component);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_copy(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
MMAL_PARAM_UNUSED(name);
|
||||
|
||||
/* Allocate the context for our module */
|
||||
component->priv->module = module = vcos_malloc(sizeof(*module), "mmal module");
|
||||
if (!module)
|
||||
return MMAL_ENOMEM;
|
||||
memset(module, 0, sizeof(*module));
|
||||
|
||||
component->priv->pf_destroy = copy_component_destroy;
|
||||
|
||||
/* Allocate and initialise all the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->input)
|
||||
goto error;
|
||||
component->input_num = 1;
|
||||
component->input[0]->priv->pf_enable = copy_port_enable;
|
||||
component->input[0]->priv->pf_disable = copy_port_disable;
|
||||
component->input[0]->priv->pf_flush = copy_port_flush;
|
||||
component->input[0]->priv->pf_send = copy_port_send;
|
||||
component->input[0]->priv->pf_set_format = copy_input_port_format_commit;
|
||||
component->input[0]->buffer_num_min = 1;
|
||||
component->input[0]->buffer_num_recommended = 0;
|
||||
component->input[0]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->input[0]->priv->module->queue)
|
||||
goto error;
|
||||
|
||||
component->output = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_OUTPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->output)
|
||||
goto error;
|
||||
component->output_num = 1;
|
||||
component->output[0]->priv->pf_enable = copy_port_enable;
|
||||
component->output[0]->priv->pf_disable = copy_port_disable;
|
||||
component->output[0]->priv->pf_flush = copy_port_flush;
|
||||
component->output[0]->priv->pf_send = copy_port_send;
|
||||
component->output[0]->priv->pf_set_format = copy_output_port_format_commit;
|
||||
component->output[0]->buffer_num_min = 1;
|
||||
component->output[0]->buffer_num_recommended = 0;
|
||||
component->output[0]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->output[0]->priv->module->queue)
|
||||
goto error;
|
||||
|
||||
status = mmal_component_action_register(component, copy_do_processing_loop);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
copy_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_copy);
|
||||
void mmal_register_component_copy(void)
|
||||
{
|
||||
mmal_component_supplier_register("copy", mmal_component_create_copy);
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#define NULLSINK_PORTS_NUM 1
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T null_sink_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
if(component->input_num)
|
||||
mmal_ports_free(component->input, component->input_num);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T null_sink_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T null_sink_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T null_sink_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Send a buffer header to a port */
|
||||
static MMAL_STATUS_T null_sink_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_BOOL_T eos = buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
|
||||
/* Send buffer back */
|
||||
buffer->length = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
|
||||
/* Generate EOS events */
|
||||
if(eos)
|
||||
return mmal_event_eos_send(port);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T null_sink_port_format_commit(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_null_sink(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
unsigned int i;
|
||||
MMAL_PARAM_UNUSED(name);
|
||||
|
||||
component->priv->pf_destroy = null_sink_component_destroy;
|
||||
|
||||
/* Allocate all the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, NULLSINK_PORTS_NUM, MMAL_PORT_TYPE_INPUT, 0);
|
||||
if(!component->input)
|
||||
goto error;
|
||||
component->input_num = NULLSINK_PORTS_NUM;
|
||||
|
||||
for(i = 0; i < component->input_num; i++)
|
||||
{
|
||||
component->input[i]->priv->pf_enable = null_sink_port_enable;
|
||||
component->input[i]->priv->pf_disable = null_sink_port_disable;
|
||||
component->input[i]->priv->pf_flush = null_sink_port_flush;
|
||||
component->input[i]->priv->pf_send = null_sink_port_send;
|
||||
component->input[i]->priv->pf_set_format = null_sink_port_format_commit;
|
||||
component->input[i]->buffer_num_min = 1;
|
||||
component->input[i]->buffer_num_recommended = 1;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
null_sink_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_null_sink);
|
||||
void mmal_register_component_null_sink(void)
|
||||
{
|
||||
mmal_component_supplier_register("null_sink", mmal_component_create_null_sink);
|
||||
}
|
@ -1,284 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#define PASSTHROUGH_PORTS_NUM 1
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_BOOL_T error; /**< Error state */
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
typedef struct MMAL_PORT_MODULE_T
|
||||
{
|
||||
MMAL_QUEUE_T *queue; /**< queue for the buffers sent to the ports */
|
||||
|
||||
} MMAL_PORT_MODULE_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T passthrough_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < component->input_num; i++)
|
||||
if(component->input[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->input[i]->priv->module->queue);
|
||||
if(component->input_num)
|
||||
mmal_ports_free(component->input, component->input_num);
|
||||
|
||||
for(i = 0; i < component->output_num; i++)
|
||||
if(component->output[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->output[i]->priv->module->queue);
|
||||
if(component->output_num)
|
||||
mmal_ports_free(component->output, component->output_num);
|
||||
|
||||
vcos_free(component->priv->module);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T passthrough_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T passthrough_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PORT_MODULE_T *port_module = port->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/* Flush buffers that our component is holding on to */
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
while(buffer)
|
||||
{
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T passthrough_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
/* We just need to flush our internal queue */
|
||||
return passthrough_port_flush(port);
|
||||
}
|
||||
|
||||
/** Send a buffer header to a port */
|
||||
static MMAL_STATUS_T passthrough_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T **other_port, *in_port, *out_port;
|
||||
MMAL_BUFFER_HEADER_T **other_buffer, *in = 0, *out = 0;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
if (module->error)
|
||||
{
|
||||
mmal_queue_put(port->priv->module->queue, buffer);
|
||||
return MMAL_SUCCESS; /* Just do nothing */
|
||||
}
|
||||
|
||||
in_port = port->component->input[port->index];
|
||||
out_port = port->component->output[port->index];
|
||||
|
||||
if (port->type == MMAL_PORT_TYPE_INPUT)
|
||||
{
|
||||
other_port = &out_port;
|
||||
other_buffer = &out;
|
||||
in = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
other_port = &in_port;
|
||||
other_buffer = ∈
|
||||
out = buffer;
|
||||
}
|
||||
|
||||
/* Get a buffer header from the matching port */
|
||||
*other_buffer = mmal_queue_get((*other_port)->priv->module->queue);
|
||||
if (!*other_buffer)
|
||||
{
|
||||
/* None available. Just queue the buffer header for now. */
|
||||
mmal_queue_put(port->priv->module->queue, buffer);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Copy our input buffer header */
|
||||
status = mmal_buffer_header_replicate(out, in);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
/* Consume the input buffer */
|
||||
in->length = 0;
|
||||
|
||||
/* Send buffers back */
|
||||
mmal_port_buffer_header_callback(in_port, in);
|
||||
mmal_port_buffer_header_callback(out_port, out);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
mmal_queue_put(in_port->priv->module->queue, in);
|
||||
mmal_queue_put(out_port->priv->module->queue, out);
|
||||
status = mmal_event_error_send(port->component, status);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("unable to send an error event buffer (%i)", (int)status);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
module->error = 1;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T passthrough_port_format_commit(MMAL_PORT_T *port)
|
||||
{
|
||||
/* Sanity check */
|
||||
if (port->type == MMAL_PORT_TYPE_OUTPUT)
|
||||
{
|
||||
LOG_ERROR("output port is read-only");
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
return mmal_format_full_copy(port->component->output[port->index]->format, port->format);
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T passthrough_port_parameter_set(MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_PORT_T *in = component->input[port->index], *out = component->input[port->index];
|
||||
|
||||
switch (param->id)
|
||||
{
|
||||
case MMAL_PARAMETER_BUFFER_REQUIREMENTS:
|
||||
{
|
||||
/* Propagate the requirements to the matching input and output the ports */
|
||||
const MMAL_PARAMETER_BUFFER_REQUIREMENTS_T *req = (const MMAL_PARAMETER_BUFFER_REQUIREMENTS_T *)param;
|
||||
uint32_t buffer_num_min = MMAL_MAX(port->buffer_num_min, req->buffer_num_min);
|
||||
uint32_t buffer_num_recommended = MMAL_MAX(port->buffer_num_recommended, req->buffer_num_recommended);
|
||||
uint32_t buffer_size_min = MMAL_MAX(port->buffer_size_min, req->buffer_size_min);
|
||||
uint32_t buffer_size_recommended = MMAL_MAX(port->buffer_size_recommended, req->buffer_size_recommended);
|
||||
|
||||
in->buffer_num_min = buffer_num_min;
|
||||
in->buffer_num_recommended = buffer_num_recommended;
|
||||
in->buffer_size_min = buffer_size_min;
|
||||
in->buffer_size_recommended = buffer_size_recommended;
|
||||
out->buffer_num_min = buffer_num_min;
|
||||
out->buffer_num_recommended = buffer_num_recommended;
|
||||
out->buffer_size_min = buffer_size_min;
|
||||
out->buffer_size_recommended = buffer_size_recommended;
|
||||
}
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
default:
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_passthrough(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
unsigned int i;
|
||||
MMAL_PARAM_UNUSED(name);
|
||||
|
||||
/* Allocate the context for our module */
|
||||
component->priv->module = module = vcos_malloc(sizeof(*module), "mmal module");
|
||||
if (!module)
|
||||
return MMAL_ENOMEM;
|
||||
memset(module, 0, sizeof(*module));
|
||||
|
||||
component->priv->pf_destroy = passthrough_component_destroy;
|
||||
|
||||
/* Allocate and initialise all the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, PASSTHROUGH_PORTS_NUM,
|
||||
MMAL_PORT_TYPE_INPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->input)
|
||||
goto error;
|
||||
component->input_num = PASSTHROUGH_PORTS_NUM;
|
||||
for(i = 0; i < component->input_num; i++)
|
||||
{
|
||||
component->input[i]->priv->pf_enable = passthrough_port_enable;
|
||||
component->input[i]->priv->pf_disable = passthrough_port_disable;
|
||||
component->input[i]->priv->pf_flush = passthrough_port_flush;
|
||||
component->input[i]->priv->pf_send = passthrough_port_send;
|
||||
component->input[i]->priv->pf_set_format = passthrough_port_format_commit;
|
||||
component->input[i]->priv->pf_parameter_set = passthrough_port_parameter_set;
|
||||
component->input[i]->buffer_num_min = 1;
|
||||
component->input[i]->buffer_num_recommended = 0;
|
||||
component->input[i]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->input[i]->priv->module->queue)
|
||||
goto error;
|
||||
}
|
||||
|
||||
component->output = mmal_ports_alloc(component, PASSTHROUGH_PORTS_NUM,
|
||||
MMAL_PORT_TYPE_OUTPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->output)
|
||||
goto error;
|
||||
component->output_num = PASSTHROUGH_PORTS_NUM;
|
||||
for(i = 0; i < component->output_num; i++)
|
||||
{
|
||||
component->output[i]->priv->pf_enable = passthrough_port_enable;
|
||||
component->output[i]->priv->pf_disable = passthrough_port_disable;
|
||||
component->output[i]->priv->pf_flush = passthrough_port_flush;
|
||||
component->output[i]->priv->pf_send = passthrough_port_send;
|
||||
component->output[i]->priv->pf_set_format = passthrough_port_format_commit;
|
||||
component->output[i]->priv->pf_parameter_set = passthrough_port_parameter_set;
|
||||
component->output[i]->buffer_num_min = 1;
|
||||
component->output[i]->buffer_num_recommended = 0;
|
||||
component->output[i]->capabilities = MMAL_PORT_CAPABILITY_PASSTHROUGH;
|
||||
component->output[i]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->output[i]->priv->module->queue)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
passthrough_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_passthrough);
|
||||
void mmal_register_component_passthrough(void)
|
||||
{
|
||||
mmal_component_supplier_register("passthrough", mmal_component_create_passthrough);
|
||||
}
|
@ -1,485 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "mmal_logging.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_clock_private.h"
|
||||
|
||||
#define SCHEDULER_CLOCK_PORTS_NUM 1
|
||||
#define SCHEDULER_INPUT_PORTS_NUM 1
|
||||
#define SCHEDULER_OUTPUT_PORTS_NUM 1
|
||||
|
||||
#define SCHEDULER_REQUEST_SLOTS 16
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status; /**< current status of the component */
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
|
||||
typedef struct MMAL_PORT_MODULE_T
|
||||
{
|
||||
MMAL_QUEUE_T *queue; /**< queue for the buffers sent to the port */
|
||||
int64_t last_ts; /***< Last timestamp seen on the input port */
|
||||
} MMAL_PORT_MODULE_T;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Process an event buffer */
|
||||
static MMAL_STATUS_T scheduler_event_process(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_EINVAL;
|
||||
|
||||
if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED)
|
||||
{
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event =
|
||||
mmal_event_format_changed_get(buffer);
|
||||
if (!event)
|
||||
goto end;
|
||||
|
||||
status = mmal_format_full_copy(port->format, event->format);
|
||||
if (status == MMAL_SUCCESS)
|
||||
status = mmal_port_format_commit(port);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("format commit failed on port %s (%i)",
|
||||
port->name, status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = MMAL_SUCCESS;
|
||||
}
|
||||
/* Forward any other event as is to the next component */
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("forwarding unknown event %4.4s", (char *)&buffer->cmd);
|
||||
status = mmal_event_forward(buffer, port->component->output[port->index]);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("unable to forward event %4.4s", (char *)&buffer->cmd);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
buffer->length = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Invoked when a clock request has been serviced */
|
||||
static void scheduler_component_clock_port_request_cb(MMAL_PORT_T *port, int64_t media_time, void *cb_data)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;;
|
||||
MMAL_PORT_T *port_in = component->input[0];
|
||||
MMAL_PORT_T *port_out = component->output[0];
|
||||
MMAL_BUFFER_HEADER_T *buffer = (MMAL_BUFFER_HEADER_T*)cb_data;
|
||||
|
||||
LOG_TRACE("media-time %"PRIi64" pts %"PRIi64" delta %"PRIi64,
|
||||
media_time, buffer->pts, media_time - buffer->pts);
|
||||
|
||||
if (buffer->cmd)
|
||||
scheduler_event_process(port_in, buffer);
|
||||
else
|
||||
/* Forward the buffer to the next component */
|
||||
mmal_port_buffer_header_callback(port_out, buffer);
|
||||
}
|
||||
|
||||
/** Process buffers on the input and output ports */
|
||||
static MMAL_BOOL_T scheduler_component_process_buffers(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *port_in = component->input[0];
|
||||
MMAL_PORT_T *port_out = component->output[0];
|
||||
MMAL_QUEUE_T *queue_in = port_in->priv->module->queue;
|
||||
MMAL_QUEUE_T *queue_out = port_out->priv->module->queue;
|
||||
MMAL_BUFFER_HEADER_T *in, *out;
|
||||
MMAL_STATUS_T cb_status = MMAL_EINVAL;
|
||||
|
||||
/* Don't do anything if we've already seen an error */
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("module failure");
|
||||
return MMAL_FALSE;
|
||||
}
|
||||
|
||||
in = mmal_queue_get(queue_in);
|
||||
|
||||
/* Special case for dealing with event buffers */
|
||||
if (in && in->cmd)
|
||||
{
|
||||
/* We normally schedule cmds so they come out in the right order,
|
||||
* except when we don't know when to schedule them, which will only
|
||||
* happen at the start of the stream.
|
||||
* The fudge factor added to the last timestamp here is because the
|
||||
* cmd really applies to the next buffer so we want to make sure
|
||||
* we leave enough time to the next component to process the previous
|
||||
* buffer before forwarding the event. */
|
||||
in->pts = port_in->priv->module->last_ts + 1000;
|
||||
if (in->pts != MMAL_TIME_UNKNOWN)
|
||||
cb_status = mmal_port_clock_request_add(component->clock[0],
|
||||
in->pts, scheduler_component_clock_port_request_cb, in);
|
||||
if (cb_status != MMAL_SUCCESS)
|
||||
{
|
||||
if (in->pts != MMAL_TIME_UNKNOWN)
|
||||
LOG_ERROR("failed to add request for cmd");
|
||||
scheduler_event_process(port_in, in);
|
||||
}
|
||||
return MMAL_TRUE;
|
||||
}
|
||||
|
||||
/* Need both an input and output buffer to be able to go any further */
|
||||
out = mmal_queue_get(queue_out);
|
||||
if (!in || !out)
|
||||
goto end;
|
||||
|
||||
if (port_out->capabilities & MMAL_PORT_CAPABILITY_PASSTHROUGH)
|
||||
{
|
||||
/* Just need to keep a reference to the input buffer */
|
||||
module->status = mmal_buffer_header_replicate(out, in);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make a full copy of the input payload */
|
||||
if (out->alloc_size < in->length)
|
||||
{
|
||||
LOG_ERROR("output buffer too small");
|
||||
|
||||
module->status = MMAL_EINVAL;
|
||||
if (mmal_event_error_send(component, module->status) != MMAL_SUCCESS)
|
||||
LOG_ERROR("unable to send an error event buffer");
|
||||
goto end;
|
||||
}
|
||||
mmal_buffer_header_mem_lock(out);
|
||||
mmal_buffer_header_mem_lock(in);
|
||||
memcpy(out->data, in->data + in->offset, in->length);
|
||||
mmal_buffer_header_mem_unlock(in);
|
||||
mmal_buffer_header_mem_unlock(out);
|
||||
out->length = in->length;
|
||||
out->offset = 0;
|
||||
out->flags = in->flags;
|
||||
out->pts = in->pts;
|
||||
out->dts = in->dts;
|
||||
*out->type = *in->type;
|
||||
}
|
||||
|
||||
/* Finished with the input buffer, so return it */
|
||||
in->length = 0;
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
in = 0;
|
||||
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("failed to replicate buffer");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Request a clock callback when media-time >= pts */
|
||||
LOG_TRACE("requesting callback at %"PRIi64,out->pts);
|
||||
port_in->priv->module->last_ts = out->pts;
|
||||
|
||||
cb_status = mmal_port_clock_request_add(component->clock[0], out->pts,
|
||||
scheduler_component_clock_port_request_cb, out);
|
||||
if (cb_status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("failed to add request");
|
||||
out->length = 0;
|
||||
mmal_port_buffer_header_callback(port_out, out);
|
||||
if (cb_status != MMAL_ECORRUPT)
|
||||
module->status = cb_status;
|
||||
}
|
||||
out = 0;
|
||||
|
||||
end:
|
||||
if (in)
|
||||
mmal_queue_put_back(queue_in, in);
|
||||
if (out)
|
||||
mmal_queue_put_back(queue_out, out);
|
||||
|
||||
return mmal_queue_length(queue_in) && mmal_queue_length(queue_out);
|
||||
}
|
||||
|
||||
/** Main processing action */
|
||||
static void scheduler_component_action(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
/* Send requests to the clock */
|
||||
while (scheduler_component_process_buffers(component));
|
||||
}
|
||||
|
||||
/** Destroy a scheduler component */
|
||||
static MMAL_STATUS_T scheduler_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < component->input_num; i++)
|
||||
if (component->input[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->input[i]->priv->module->queue);
|
||||
if (component->input_num)
|
||||
mmal_ports_free(component->input, component->input_num);
|
||||
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
if (component->output[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->output[i]->priv->module->queue);
|
||||
if (component->output_num)
|
||||
mmal_ports_free(component->output, component->output_num);
|
||||
|
||||
if (component->clock_num)
|
||||
mmal_ports_clock_free(component->clock, component->clock_num);
|
||||
|
||||
vcos_free(component->priv->module);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T scheduler_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T scheduler_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PORT_MODULE_T *port_module = port->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/* Flush buffers associated with pending clock requests */
|
||||
mmal_port_clock_request_flush(port->component->clock[0]);
|
||||
|
||||
/* Flush buffers that our component is holding on to */
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
while (buffer)
|
||||
{
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
}
|
||||
|
||||
port->priv->module->last_ts = MMAL_TIME_UNKNOWN;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T scheduler_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
/* We just need to flush our internal queue */
|
||||
return scheduler_port_flush(port);
|
||||
}
|
||||
|
||||
/** Send a buffer header to a port */
|
||||
static MMAL_STATUS_T scheduler_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
|
||||
/* notify the clock port */
|
||||
if (port->type == MMAL_PORT_TYPE_INPUT && !buffer->cmd)
|
||||
{
|
||||
MMAL_CLOCK_BUFFER_INFO_T info = { buffer->pts, vcos_getmicrosecs() };
|
||||
mmal_port_clock_input_buffer_info(port->component->clock[0], &info);
|
||||
}
|
||||
|
||||
mmal_queue_put(port->priv->module->queue, buffer);
|
||||
return mmal_component_action_trigger(component);
|
||||
}
|
||||
|
||||
/** Set format on an input port */
|
||||
static MMAL_STATUS_T scheduler_input_port_format_commit(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event;
|
||||
MMAL_PORT_T *output = component->output[0];
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
/* If the output port is not enabled we just need to update its format.
|
||||
* Otherwise we'll have to trigger a format changed event for it. */
|
||||
if (!output->is_enabled)
|
||||
{
|
||||
status = mmal_format_full_copy(output->format, port->format);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Send an event on the output port */
|
||||
status = mmal_port_event_get(output, &buffer, MMAL_EVENT_FORMAT_CHANGED);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("unable to get an event buffer");
|
||||
return status;
|
||||
}
|
||||
event = mmal_event_format_changed_get(buffer);
|
||||
if (!event)
|
||||
{
|
||||
mmal_buffer_header_release(buffer);
|
||||
LOG_ERROR("failed to set format");
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
mmal_format_copy(event->format, port->format);
|
||||
|
||||
/* Pass on the buffer requirements */
|
||||
event->buffer_num_min = port->buffer_num_min;
|
||||
event->buffer_size_min = port->buffer_size_min;
|
||||
event->buffer_num_recommended = port->buffer_num_recommended;
|
||||
event->buffer_size_recommended = port->buffer_size_recommended;
|
||||
|
||||
mmal_port_event_send(component->output[port->index], buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Set format on an output port */
|
||||
static MMAL_STATUS_T scheduler_output_port_format_commit(MMAL_PORT_T *port)
|
||||
{
|
||||
/* The format of the output port needs to match the input port */
|
||||
if (mmal_format_compare(port->format, port->component->input[port->index]->format))
|
||||
LOG_DEBUG("output port format different from input port");
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T scheduler_port_parameter_set(MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_PORT_T *in = component->input[port->index], *out = component->input[port->index];
|
||||
|
||||
switch (param->id)
|
||||
{
|
||||
case MMAL_PARAMETER_BUFFER_REQUIREMENTS:
|
||||
{
|
||||
/* Propagate the requirements to the matching input and output the ports */
|
||||
const MMAL_PARAMETER_BUFFER_REQUIREMENTS_T *req = (const MMAL_PARAMETER_BUFFER_REQUIREMENTS_T *)param;
|
||||
uint32_t buffer_num_min = MMAL_MAX(port->buffer_num_min, req->buffer_num_min);
|
||||
uint32_t buffer_num_recommended = MMAL_MAX(port->buffer_num_recommended, req->buffer_num_recommended);
|
||||
uint32_t buffer_size_min = MMAL_MAX(port->buffer_size_min, req->buffer_size_min);
|
||||
uint32_t buffer_size_recommended = MMAL_MAX(port->buffer_size_recommended, req->buffer_size_recommended);
|
||||
|
||||
in->buffer_num_min = buffer_num_min;
|
||||
in->buffer_num_recommended = buffer_num_recommended;
|
||||
in->buffer_size_min = buffer_size_min;
|
||||
in->buffer_size_recommended = buffer_size_recommended;
|
||||
out->buffer_num_min = buffer_num_min;
|
||||
out->buffer_num_recommended = buffer_num_recommended;
|
||||
out->buffer_size_min = buffer_size_min;
|
||||
out->buffer_size_recommended = buffer_size_recommended;
|
||||
}
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
default:
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_scheduler(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
int disable_passthrough = 0;
|
||||
unsigned int i;
|
||||
|
||||
/* Allocate the context for our module */
|
||||
component->priv->module = module = vcos_calloc(1, sizeof(*module), "mmal module");
|
||||
if (!module)
|
||||
return MMAL_ENOMEM;
|
||||
|
||||
component->priv->pf_destroy = scheduler_component_destroy;
|
||||
|
||||
/* Allocate and initialise all the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, SCHEDULER_INPUT_PORTS_NUM,
|
||||
MMAL_PORT_TYPE_INPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if (!component->input)
|
||||
goto error;
|
||||
component->input_num = SCHEDULER_INPUT_PORTS_NUM;
|
||||
for (i = 0; i < component->input_num; i++)
|
||||
{
|
||||
component->input[i]->priv->pf_enable = scheduler_port_enable;
|
||||
component->input[i]->priv->pf_disable = scheduler_port_disable;
|
||||
component->input[i]->priv->pf_flush = scheduler_port_flush;
|
||||
component->input[i]->priv->pf_send = scheduler_port_send;
|
||||
component->input[i]->priv->pf_set_format = scheduler_input_port_format_commit;
|
||||
component->input[i]->priv->pf_parameter_set = scheduler_port_parameter_set;
|
||||
component->input[i]->buffer_num_min = 1;
|
||||
component->input[i]->buffer_num_recommended = 0;
|
||||
component->input[i]->capabilities = MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE;
|
||||
component->input[i]->priv->module->queue = mmal_queue_create();
|
||||
if (!component->input[i]->priv->module->queue)
|
||||
goto error;
|
||||
component->input[i]->priv->module->last_ts = MMAL_TIME_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Override passthrough behaviour */
|
||||
if (strstr(name, ".copy"))
|
||||
{
|
||||
LOG_TRACE("disable passthrough on output ports");
|
||||
disable_passthrough = 1;
|
||||
}
|
||||
|
||||
component->output = mmal_ports_alloc(component, SCHEDULER_OUTPUT_PORTS_NUM,
|
||||
MMAL_PORT_TYPE_OUTPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if (!component->output)
|
||||
goto error;
|
||||
component->output_num = SCHEDULER_OUTPUT_PORTS_NUM;
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
{
|
||||
component->output[i]->priv->pf_enable = scheduler_port_enable;
|
||||
component->output[i]->priv->pf_disable = scheduler_port_disable;
|
||||
component->output[i]->priv->pf_flush = scheduler_port_flush;
|
||||
component->output[i]->priv->pf_send = scheduler_port_send;
|
||||
component->output[i]->priv->pf_set_format = scheduler_output_port_format_commit;
|
||||
component->output[i]->priv->pf_parameter_set = scheduler_port_parameter_set;
|
||||
component->output[i]->buffer_num_min = 1;
|
||||
component->output[i]->buffer_num_recommended = 0;
|
||||
component->output[i]->capabilities = disable_passthrough ? 0 : MMAL_PORT_CAPABILITY_PASSTHROUGH;
|
||||
component->output[i]->priv->module->queue = mmal_queue_create();
|
||||
if (!component->output[i]->priv->module->queue)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Create the clock port (clock ports are managed by the framework) */
|
||||
component->clock = mmal_ports_clock_alloc(component, SCHEDULER_CLOCK_PORTS_NUM, 0, NULL);
|
||||
if (!component->clock)
|
||||
goto error;
|
||||
component->clock_num = SCHEDULER_CLOCK_PORTS_NUM;
|
||||
|
||||
status = mmal_component_action_register(component, scheduler_component_action);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
scheduler_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_scheduler);
|
||||
void mmal_register_component_scheduler(void)
|
||||
{
|
||||
mmal_component_supplier_register("scheduler", mmal_component_create_scheduler);
|
||||
}
|
||||
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "mmal_logging.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#define FRAME_LENGTH 2048
|
||||
|
||||
/* Buffering requirements */
|
||||
#define INPUT_MIN_BUFFER_NUM 4
|
||||
#define INPUT_RECOMMENDED_BUFFER_NUM 8
|
||||
|
||||
/****************************/
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
MMAL_QUEUE_T *queue;
|
||||
MMAL_BOOL_T audio_opened;
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T sdl_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
if (module->audio_opened)
|
||||
SDL_CloseAudio();
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
|
||||
if(component->input_num) mmal_ports_free(component->input, 1);
|
||||
if(module->queue) mmal_queue_destroy(module->queue);
|
||||
vcos_free(module);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static void sdl_callback( void *ctx, uint8_t *stream, int size )
|
||||
{
|
||||
MMAL_PORT_T *port = (MMAL_PORT_T *)ctx;
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
unsigned int i, bytes;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
buffer = mmal_queue_get(module->queue);
|
||||
if (!buffer)
|
||||
{
|
||||
LOG_ERROR("audio underrun");
|
||||
return;
|
||||
}
|
||||
|
||||
if (port->format->encoding == MMAL_ENCODING_PCM_SIGNED &&
|
||||
port->format->es->audio.bits_per_sample == 16)
|
||||
{
|
||||
bytes = buffer->length;
|
||||
if (bytes > (unsigned int)size) bytes = size;
|
||||
memcpy(stream, buffer->data + buffer->offset, bytes);
|
||||
buffer->offset += bytes;
|
||||
buffer->length -= bytes;
|
||||
stream += bytes;
|
||||
size -= bytes;
|
||||
}
|
||||
else if (port->format->es->audio.bits_per_sample == 32)
|
||||
{
|
||||
bytes = buffer->length;
|
||||
if (bytes > 2 * (unsigned int)size) bytes = 2 * size;
|
||||
vcos_assert(!(bytes&0x3));
|
||||
|
||||
if (port->format->encoding == MMAL_ENCODING_PCM_FLOAT)
|
||||
{
|
||||
float *in = (float *)(buffer->data + buffer->offset);
|
||||
int16_t *out = (int16_t *)stream;
|
||||
for (i = 0; i < bytes / 4; i++)
|
||||
{
|
||||
if (*in >= 1.0) *out = 32767;
|
||||
else if (*in < -1.0) *out = -32768;
|
||||
else *out = *in * 32768.0;
|
||||
in++; out++;
|
||||
}
|
||||
}
|
||||
else if (port->format->encoding == MMAL_ENCODING_PCM_SIGNED)
|
||||
{
|
||||
int32_t *in = (int32_t *)(buffer->data + buffer->offset);
|
||||
int16_t *out = (int16_t *)stream;
|
||||
for (i = 0; i < bytes / 4; i++)
|
||||
*out++ = (*in++) >> 16;
|
||||
}
|
||||
buffer->offset += bytes;
|
||||
buffer->length -= bytes;
|
||||
stream += bytes / 2;
|
||||
size -= bytes / 2;
|
||||
}
|
||||
|
||||
if (buffer->length)
|
||||
{
|
||||
/* We still have some data left for next time */
|
||||
mmal_queue_put_back(module->queue, buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle the EOS */
|
||||
if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS)
|
||||
mmal_event_eos_send(port);
|
||||
|
||||
buffer->offset = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T sdl_port_set_format(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
SDL_AudioSpec desired, obtained;
|
||||
|
||||
if (port->format->encoding != MMAL_ENCODING_PCM_SIGNED &&
|
||||
port->format->encoding != MMAL_ENCODING_PCM_FLOAT &&
|
||||
port->format->es->audio.bits_per_sample != 16 &&
|
||||
port->format->es->audio.bits_per_sample != 32)
|
||||
{
|
||||
LOG_ERROR("port does not support '%4.4s' at %ibps",
|
||||
(char *)&port->format->encoding, port->format->es->audio.bits_per_sample);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
if (module->audio_opened)
|
||||
SDL_CloseAudio();
|
||||
module->audio_opened = MMAL_FALSE;
|
||||
|
||||
desired.freq = port->format->es->audio.sample_rate;
|
||||
desired.format = AUDIO_S16SYS;
|
||||
desired.channels = port->format->es->audio.channels;
|
||||
desired.callback = sdl_callback;
|
||||
desired.userdata = port;
|
||||
desired.samples = FRAME_LENGTH;
|
||||
|
||||
/* Open the sound device. */
|
||||
if (SDL_OpenAudio( &desired, &obtained ) < 0)
|
||||
return MMAL_ENOSYS;
|
||||
module->audio_opened = MMAL_TRUE;
|
||||
|
||||
/* Now have a look at what we got. */
|
||||
if (obtained.format != AUDIO_S16SYS)
|
||||
return MMAL_ENOSYS;
|
||||
|
||||
port->format->es->audio.sample_rate = obtained.freq;
|
||||
port->format->es->audio.channels = obtained.channels;
|
||||
port->buffer_size_min = obtained.samples * port->format->es->audio.channels * 2;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T sdl_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
SDL_PauseAudio( 0 );
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T sdl_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
SDL_PauseAudio( 1 );
|
||||
|
||||
while((buffer = mmal_queue_get(module->queue)))
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T sdl_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
/* Handle event buffers */
|
||||
if (buffer->cmd)
|
||||
{
|
||||
LOG_ERROR("discarding event %i on port %p", (int)buffer->cmd, port);
|
||||
buffer->length = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
return module->status;
|
||||
|
||||
mmal_queue_put(module->queue, buffer);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_sdl(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
|
||||
/* Check we're the requested component */
|
||||
if(strcmp(name, "sdl." MMAL_AUDIO_RENDER))
|
||||
return MMAL_ENOENT;
|
||||
|
||||
if( SDL_WasInit(SDL_INIT_AUDIO) )
|
||||
return MMAL_ENXIO;
|
||||
|
||||
/* Allocate our module context */
|
||||
component->priv->module = module = vcos_calloc(1, sizeof(*module), "mmal module");
|
||||
if(!module)
|
||||
return MMAL_ENOMEM;
|
||||
|
||||
if(SDL_Init(SDL_INIT_AUDIO|SDL_INIT_NOPARACHUTE) < 0)
|
||||
return MMAL_ENXIO;
|
||||
|
||||
/* Allocate the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, 0);
|
||||
if(!component->input)
|
||||
goto error;
|
||||
component->input_num = 1;
|
||||
|
||||
module->queue = mmal_queue_create();
|
||||
if(!module->queue)
|
||||
goto error;
|
||||
|
||||
component->input[0]->priv->pf_set_format = sdl_port_set_format;
|
||||
component->input[0]->priv->pf_enable = sdl_port_enable;
|
||||
component->input[0]->priv->pf_disable = sdl_port_disable;
|
||||
component->input[0]->priv->pf_send = sdl_port_send;
|
||||
component->input[0]->buffer_num_min = INPUT_MIN_BUFFER_NUM;
|
||||
component->input[0]->buffer_num_recommended = INPUT_RECOMMENDED_BUFFER_NUM;
|
||||
|
||||
component->priv->pf_destroy = sdl_component_destroy;
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
sdl_component_destroy(component);
|
||||
return MMAL_ENOMEM;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_sdl_audio);
|
||||
void mmal_register_component_sdl_audio(void)
|
||||
{
|
||||
mmal_component_supplier_register("sdl", mmal_component_create_sdl);
|
||||
}
|
@ -1,394 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "mmal_logging.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#define NUM_PORTS_INPUT 1
|
||||
#define SDL_WIDTH 800
|
||||
#define SDL_HEIGHT 600
|
||||
|
||||
/* Buffering requirements */
|
||||
#define INPUT_MIN_BUFFER_NUM 1
|
||||
#define INPUT_RECOMMENDED_BUFFER_NUM 4
|
||||
|
||||
/****************************/
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
SDL_Overlay *sdl_overlay;
|
||||
SDL_Surface *sdl_surface;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
MMAL_STATUS_T status;
|
||||
MMAL_RECT_T display_region;
|
||||
|
||||
MMAL_QUEUE_T *queue;
|
||||
|
||||
SDL_Thread *thread;
|
||||
MMAL_BOOL_T quit;
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
static MMAL_STATUS_T sdl_port_parameter_set(MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_ENOSYS;
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
switch (param->id)
|
||||
{
|
||||
case MMAL_PARAMETER_DISPLAYREGION:
|
||||
{
|
||||
/* We only support setting the destination rectangle */
|
||||
const MMAL_DISPLAYREGION_T *display = (const MMAL_DISPLAYREGION_T *)param;
|
||||
if (display->set & MMAL_DISPLAY_SET_DEST_RECT)
|
||||
module->display_region = display->dest_rect;
|
||||
status = MMAL_SUCCESS;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T sdl_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
SDL_Event event = {SDL_QUIT};
|
||||
|
||||
module->quit = MMAL_TRUE;
|
||||
SDL_PushEvent(&event);
|
||||
if(module->thread)
|
||||
SDL_WaitThread(module->thread, NULL);
|
||||
if(module->sdl_overlay)
|
||||
SDL_FreeYUVOverlay(module->sdl_overlay);
|
||||
if(module->sdl_surface)
|
||||
SDL_FreeSurface(module->sdl_surface);
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
if(component->input_num) mmal_ports_free(component->input, 1);
|
||||
if(module->queue) mmal_queue_destroy(module->queue);
|
||||
vcos_free(module);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_sdl_create_surface(MMAL_COMPONENT_MODULE_T *module)
|
||||
{
|
||||
uint32_t flags;
|
||||
int bpp;
|
||||
int w = module->display_region.width;
|
||||
int h = module->display_region.height;
|
||||
|
||||
flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE;
|
||||
bpp = SDL_VideoModeOK(w, h, 16, flags);
|
||||
if(!bpp)
|
||||
{
|
||||
LOG_ERROR("no SDL video mode available");
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
module->sdl_surface = SDL_SetVideoMode(w, h, bpp, flags);
|
||||
if(!module->sdl_surface)
|
||||
{
|
||||
LOG_ERROR("cannot create SDL surface");
|
||||
return MMAL_ENOMEM;
|
||||
}
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T sdl_port_set_format(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
if ((status=mmal_sdl_create_surface(module)) != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* We only support I420 */
|
||||
if (port->format->encoding != MMAL_ENCODING_I420)
|
||||
return MMAL_ENOSYS;
|
||||
|
||||
/* Check if we need to re-create an overlay */
|
||||
if (module->sdl_overlay &&
|
||||
module->width == port->format->es->video.width &&
|
||||
module->height == port->format->es->video.height)
|
||||
return MMAL_SUCCESS; /* Nothing to do */
|
||||
|
||||
if (module->sdl_overlay)
|
||||
SDL_FreeYUVOverlay(module->sdl_overlay);
|
||||
|
||||
/* Create overlay */
|
||||
module->sdl_overlay =
|
||||
SDL_CreateYUVOverlay(port->format->es->video.width,
|
||||
port->format->es->video.height,
|
||||
SDL_YV12_OVERLAY, module->sdl_surface);
|
||||
if (!module->sdl_overlay)
|
||||
{
|
||||
LOG_ERROR("cannot create SDL overlay");
|
||||
return MMAL_ENOSPC;
|
||||
}
|
||||
module->width = port->format->es->video.width;
|
||||
module->height = port->format->es->video.height;
|
||||
|
||||
port->buffer_size_min = module->width * module->height * 3 / 2;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T sdl_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T sdl_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T sdl_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/* Flush buffers that our component is holding on to.
|
||||
* If the reading thread is holding onto a buffer it will send it back ASAP as well
|
||||
* so no need to care about that. */
|
||||
while((buffer = mmal_queue_get(module->queue)))
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_BOOL_T sdl_do_processing(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_PORT_T *port = component->input[0];
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
unsigned int width = port->format->es->video.width;
|
||||
unsigned int height = port->format->es->video.height;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
uint8_t *src_plane[3];
|
||||
uint32_t *src_pitch;
|
||||
unsigned int i, line;
|
||||
MMAL_BOOL_T eos;
|
||||
SDL_Rect rect;
|
||||
|
||||
buffer = mmal_queue_get(module->queue);
|
||||
if (!buffer)
|
||||
return 0;
|
||||
|
||||
eos = buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
|
||||
/* Handle event buffers */
|
||||
if (buffer->cmd)
|
||||
{
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(buffer);
|
||||
if (event)
|
||||
{
|
||||
mmal_format_copy(port->format, event->format);
|
||||
module->status = port->priv->pf_set_format(port);
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("format not set on port %p", port);
|
||||
if (mmal_event_error_send(port->component, module->status) != MMAL_SUCCESS)
|
||||
LOG_ERROR("unable to send an error event buffer");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("discarding event %i on port %p", (int)buffer->cmd, port);
|
||||
}
|
||||
|
||||
buffer->length = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
return 1;
|
||||
|
||||
/* Ignore empty buffers */
|
||||
if (!buffer->length)
|
||||
goto end;
|
||||
|
||||
// FIXME: sanity check the size of the buffer
|
||||
|
||||
/* Blit the buffer onto the overlay. */
|
||||
src_pitch = buffer->type->video.pitch;
|
||||
src_plane[0] = buffer->data + buffer->type->video.offset[0];
|
||||
src_plane[1] = buffer->data + buffer->type->video.offset[2];
|
||||
src_plane[2] = buffer->data + buffer->type->video.offset[1];
|
||||
|
||||
SDL_LockYUVOverlay(module->sdl_overlay);
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
uint8_t *src = src_plane[i];
|
||||
uint8_t *dst = module->sdl_overlay->pixels[i];
|
||||
|
||||
if(i == 1) {width /= 2; height /= 2;}
|
||||
for(line = 0; line < height; line++)
|
||||
{
|
||||
memcpy(dst, src, width);
|
||||
src += src_pitch[i];
|
||||
dst += module->sdl_overlay->pitches[i];
|
||||
}
|
||||
}
|
||||
SDL_UnlockYUVOverlay(module->sdl_overlay);
|
||||
|
||||
width = port->format->es->video.width;
|
||||
height = port->format->es->video.height;
|
||||
rect.x = module->display_region.x;
|
||||
rect.w = module->display_region.width;
|
||||
height = rect.w * height / width;
|
||||
rect.y = module->display_region.y + (module->display_region.height - height) / 2;
|
||||
rect.h = height;
|
||||
|
||||
SDL_DisplayYUVOverlay(module->sdl_overlay, &rect);
|
||||
|
||||
end:
|
||||
buffer->offset = buffer->length = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
|
||||
/* Generate EOS events */
|
||||
if (eos)
|
||||
mmal_event_eos_send(port);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void sdl_do_processing_loop(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
while (sdl_do_processing(component));
|
||||
}
|
||||
|
||||
/** Buffer sending */
|
||||
static MMAL_STATUS_T sdl_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
|
||||
mmal_queue_put(module->queue, buffer);
|
||||
mmal_component_action_trigger(port->component);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** SDL event thread */
|
||||
static int sdl_event_thread(void *arg)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = (MMAL_COMPONENT_T *)arg;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_WaitEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
if (!module->quit)
|
||||
mmal_event_error_send(component, MMAL_SUCCESS);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_sdl(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
|
||||
/* Check we're the requested component */
|
||||
if(strcmp(name, "sdl." MMAL_VIDEO_RENDER))
|
||||
return MMAL_ENOENT;
|
||||
|
||||
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_EVENTTHREAD|SDL_INIT_NOPARACHUTE) < 0)
|
||||
return MMAL_ENXIO;
|
||||
|
||||
/* Allocate our module context */
|
||||
component->priv->module = module = vcos_calloc(1, sizeof(*module), "mmal module");
|
||||
if(!module) return MMAL_ENOMEM;
|
||||
|
||||
module->queue = mmal_queue_create();
|
||||
if(!module->queue) goto error;
|
||||
|
||||
/* Allocate the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, 0);
|
||||
if(!component->input) goto error;
|
||||
component->input_num = 1;
|
||||
module->display_region.width = SDL_WIDTH;
|
||||
module->display_region.height = SDL_HEIGHT;
|
||||
|
||||
/************/
|
||||
|
||||
component->input[0]->priv->pf_set_format = sdl_port_set_format;
|
||||
component->input[0]->priv->pf_enable = sdl_port_enable;
|
||||
component->input[0]->priv->pf_disable = sdl_port_disable;
|
||||
component->input[0]->priv->pf_flush = sdl_port_flush;
|
||||
component->input[0]->priv->pf_send = sdl_port_send;
|
||||
component->input[0]->priv->pf_parameter_set = sdl_port_parameter_set;
|
||||
component->input[0]->buffer_num_min = INPUT_MIN_BUFFER_NUM;
|
||||
component->input[0]->buffer_num_recommended = INPUT_RECOMMENDED_BUFFER_NUM;
|
||||
|
||||
component->priv->pf_destroy = sdl_component_destroy;
|
||||
|
||||
/* Create a thread to monitor SDL events */
|
||||
module->thread = SDL_CreateThread(sdl_event_thread, component);
|
||||
|
||||
status = mmal_component_action_register(component, sdl_do_processing_loop);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
sdl_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_sdl);
|
||||
void mmal_register_component_sdl(void)
|
||||
{
|
||||
mmal_component_supplier_register("sdl", mmal_component_create_sdl);
|
||||
}
|
@ -1,496 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#define SPDIF_AC3_FRAME_SIZE 6144
|
||||
#define SPDIF_EAC3_FRAME_SIZE (6144*4)
|
||||
#define SPDIF_FRAME_SIZE SPDIF_EAC3_FRAME_SIZE
|
||||
|
||||
/* Buffering requirements */
|
||||
#define INPUT_MIN_BUFFER_SIZE SPDIF_FRAME_SIZE
|
||||
#define INPUT_MIN_BUFFER_NUM 2
|
||||
#define OUTPUT_MIN_BUFFER_SIZE SPDIF_FRAME_SIZE
|
||||
#define OUTPUT_MIN_BUFFER_NUM 2
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
MMAL_STATUS_T status; /**< current status of the component */
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
typedef struct MMAL_PORT_MODULE_T
|
||||
{
|
||||
MMAL_QUEUE_T *queue; /**< queue for the buffers sent to the ports */
|
||||
MMAL_BOOL_T needs_configuring; /**< port is waiting for a format commit */
|
||||
|
||||
} MMAL_PORT_MODULE_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static MMAL_STATUS_T spdif_send_event_format_changed(MMAL_COMPONENT_T *component, MMAL_PORT_T *port,
|
||||
MMAL_ES_FORMAT_T *format)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer = NULL;
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event;
|
||||
|
||||
/* Get an event buffer */
|
||||
module->status = mmal_port_event_get(port, &buffer, MMAL_EVENT_FORMAT_CHANGED);
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("unable to get an event buffer");
|
||||
return module->status;
|
||||
}
|
||||
/* coverity[returned_null] Can't return null or call above would have failed */
|
||||
event = mmal_event_format_changed_get(buffer);
|
||||
|
||||
/* Fill in the new format */
|
||||
if (port->format->encoding == MMAL_ENCODING_PCM_SIGNED)
|
||||
mmal_format_copy(event->format, port->format);
|
||||
else
|
||||
mmal_format_copy(event->format, format);
|
||||
|
||||
event->format->es->audio.sample_rate = format->es->audio.sample_rate;
|
||||
|
||||
/* Pass on the buffer requirements */
|
||||
event->buffer_num_min = port->buffer_num_min;
|
||||
event->buffer_size_min = port->buffer_size_min;
|
||||
event->buffer_size_recommended = event->buffer_size_min;
|
||||
event->buffer_num_recommended = port->buffer_num_recommended;
|
||||
|
||||
port->priv->module->needs_configuring = 1;
|
||||
mmal_port_event_send(port, buffer);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Actual processing function */
|
||||
static MMAL_BOOL_T spdif_do_processing(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
static const uint8_t ac3_spdif_header[6] = {0x72,0xF8,0x1F,0x4E,0x1, 0};
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *port_in = component->input[0];
|
||||
MMAL_PORT_T *port_out = component->output[0];
|
||||
MMAL_BUFFER_HEADER_T *in, *out;
|
||||
unsigned int i, sample_rate, frame_size, spdif_frame_size;
|
||||
uint8_t *in_data;
|
||||
|
||||
if (port_out->priv->module->needs_configuring)
|
||||
return 0;
|
||||
|
||||
in = mmal_queue_get(port_in->priv->module->queue);
|
||||
if (!in)
|
||||
return 0;
|
||||
|
||||
/* Handle event buffers */
|
||||
if (in->cmd)
|
||||
{
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(in);
|
||||
if (event)
|
||||
{
|
||||
module->status = mmal_format_full_copy(port_in->format, event->format);
|
||||
if (module->status == MMAL_SUCCESS)
|
||||
module->status = port_in->priv->pf_set_format(port_in);
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("format not set on port %s %p (%i)", port_in->name, port_in, module->status);
|
||||
if (mmal_event_error_send(component, module->status) != MMAL_SUCCESS)
|
||||
LOG_ERROR("unable to send an error event buffer");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("discarding event %i on port %s %p", (int)in->cmd, port_in->name, port_in);
|
||||
}
|
||||
|
||||
in->length = 0;
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Don't do anything if we've already seen an error */
|
||||
if (module->status != MMAL_SUCCESS)
|
||||
{
|
||||
mmal_queue_put_back(port_in->priv->module->queue, in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Discard empty buffers */
|
||||
if (!in->length && !in->flags)
|
||||
{
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
return 1;
|
||||
}
|
||||
/* Discard codec config data as it's not needed */
|
||||
if (in->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG)
|
||||
{
|
||||
LOG_DEBUG("config buffer %ibytes", in->length);
|
||||
in->length = 0;
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
out = mmal_queue_get(port_out->priv->module->queue);
|
||||
if (!out)
|
||||
{
|
||||
mmal_queue_put_back(port_in->priv->module->queue, in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spdif_frame_size = SPDIF_AC3_FRAME_SIZE;
|
||||
if (port_out->format->encoding == MMAL_ENCODING_EAC3)
|
||||
spdif_frame_size = SPDIF_EAC3_FRAME_SIZE;
|
||||
|
||||
/* Sanity check the output buffer is big enough */
|
||||
if (out->alloc_size < spdif_frame_size)
|
||||
{
|
||||
module->status = MMAL_EINVAL;
|
||||
if (mmal_event_error_send(component, module->status) != MMAL_SUCCESS)
|
||||
LOG_ERROR("unable to send an error event buffer");
|
||||
mmal_queue_put_back(port_in->priv->module->queue, in);
|
||||
mmal_queue_put_back(port_out->priv->module->queue, out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Special case for empty buffers carrying a flag */
|
||||
if (!in->length && in->flags)
|
||||
{
|
||||
out->length = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
LOG_DEBUG("frame: %lld, size %i", in->pts, in->length);
|
||||
mmal_buffer_header_mem_lock(out);
|
||||
mmal_buffer_header_mem_lock(in);
|
||||
in_data = in->data + in->offset;
|
||||
|
||||
/* Sanity check we're dealing with an AC3 frame */
|
||||
if (in->length < 5)
|
||||
{
|
||||
LOG_ERROR("invalid data size (%i bytes)", in->length);
|
||||
goto discard;
|
||||
}
|
||||
|
||||
if (!(in_data[0] == 0x0B || in_data[1] == 0x77) &&
|
||||
!(in_data[0] == 0x77 || in_data[1] == 0x0B))
|
||||
{
|
||||
LOG_ERROR("invalid data (%i bytes): %2.2x,%2.2x,%2.2x,%2.2x",
|
||||
in->length, in_data[0], in_data[1], in_data[2], in_data[3]);
|
||||
goto discard;
|
||||
}
|
||||
|
||||
/* We need to make sure we use the right sample rate
|
||||
* to be able to play this at the right rate */
|
||||
if ((in_data[4] & 0xC0) == 0x40) sample_rate = 44100;
|
||||
else if ((in_data[4] & 0xC0) == 0x80) sample_rate = 32000;
|
||||
else sample_rate = 48000;
|
||||
|
||||
/* If the sample rate changes, stop everything we're doing
|
||||
* and signal the format change. */
|
||||
if (sample_rate != port_out->format->es->audio.sample_rate)
|
||||
{
|
||||
LOG_INFO("format change: %i->%i",
|
||||
port_out->format->es->audio.sample_rate, sample_rate);
|
||||
port_in->format->es->audio.sample_rate = sample_rate;
|
||||
spdif_send_event_format_changed(component, port_out, port_in->format);
|
||||
mmal_buffer_header_mem_unlock(in);
|
||||
mmal_buffer_header_mem_unlock(out);
|
||||
mmal_queue_put_back(port_in->priv->module->queue, in);
|
||||
mmal_queue_put_back(port_out->priv->module->queue, out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Build our S/PDIF frame. We assume that we need to send
|
||||
* little endian S/PDIF data. */
|
||||
if (in->length > spdif_frame_size - 8)
|
||||
LOG_ERROR("frame too big, truncating (%i/%i bytes)",
|
||||
in->length, spdif_frame_size - 8);
|
||||
frame_size = MMAL_MIN(in->length, spdif_frame_size - 8) / 2;
|
||||
memcpy(out->data, ac3_spdif_header, sizeof(ac3_spdif_header));
|
||||
out->data[5] = in_data[5] & 0x7; /* bsmod */
|
||||
out->data[6] = frame_size & 0xFF;
|
||||
out->data[7] = frame_size >> 8;
|
||||
|
||||
/* Copy the AC3 data, reverting the endianness if required */
|
||||
if (in_data[0] == 0x0B)
|
||||
{
|
||||
for (i = 0; i < frame_size; i++)
|
||||
{
|
||||
out->data[8+i*2] = in_data[in->offset+i*2+1];
|
||||
out->data[8+i*2+1] = in_data[in->offset+i*2];
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(out->data + 8, in_data, in->length);
|
||||
|
||||
/* The S/PDIF frame needs to be padded */
|
||||
memset(out->data + 8 + frame_size * 2, 0,
|
||||
spdif_frame_size - frame_size * 2 - 8);
|
||||
mmal_buffer_header_mem_unlock(in);
|
||||
mmal_buffer_header_mem_unlock(out);
|
||||
out->length = spdif_frame_size;
|
||||
end:
|
||||
out->offset = 0;
|
||||
out->flags = in->flags;
|
||||
out->pts = in->pts;
|
||||
out->dts = in->dts;
|
||||
|
||||
/* Send buffers back */
|
||||
in->length = 0;
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
mmal_port_buffer_header_callback(port_out, out);
|
||||
return 1;
|
||||
|
||||
discard:
|
||||
mmal_buffer_header_mem_unlock(in);
|
||||
mmal_buffer_header_mem_unlock(out);
|
||||
in->length = 0;
|
||||
mmal_queue_put_back(port_out->priv->module->queue, out);
|
||||
mmal_port_buffer_header_callback(port_in, in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void spdif_do_processing_loop(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
while (spdif_do_processing(component));
|
||||
}
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T spdif_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < component->input_num; i++)
|
||||
if(component->input[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->input[i]->priv->module->queue);
|
||||
if(component->input_num)
|
||||
mmal_ports_free(component->input, component->input_num);
|
||||
|
||||
for(i = 0; i < component->output_num; i++)
|
||||
if(component->output[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->output[i]->priv->module->queue);
|
||||
if(component->output_num)
|
||||
mmal_ports_free(component->output, component->output_num);
|
||||
|
||||
vcos_free(component->priv->module);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T spdif_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
|
||||
/* We need to propagate the buffer requirements when the input port is
|
||||
* enabled */
|
||||
if (port->type == MMAL_PORT_TYPE_INPUT)
|
||||
return port->priv->pf_set_format(port);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T spdif_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PORT_MODULE_T *port_module = port->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/* Flush buffers that our component is holding on to */
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
while(buffer)
|
||||
{
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T spdif_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
/* We just need to flush our internal queue */
|
||||
return spdif_port_flush(port);
|
||||
}
|
||||
|
||||
/** Send a buffer header to a port */
|
||||
static MMAL_STATUS_T spdif_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
mmal_queue_put(port->priv->module->queue, buffer);
|
||||
mmal_component_action_trigger(port->component);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on input port */
|
||||
static MMAL_STATUS_T spdif_input_port_format_commit(MMAL_PORT_T *in)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = in->component;
|
||||
MMAL_PORT_T *out = component->output[0];
|
||||
|
||||
/* Sanity check we cope with this format */
|
||||
if (in->format->encoding != MMAL_ENCODING_AC3 &&
|
||||
in->format->encoding != MMAL_ENCODING_EAC3)
|
||||
return MMAL_ENXIO;
|
||||
|
||||
LOG_INFO("%4.4s, %iHz, %ichan, %ibps", (char *)&in->format->encoding,
|
||||
in->format->es->audio.sample_rate, in->format->es->audio.channels,
|
||||
in->format->bitrate);
|
||||
|
||||
/* TODO: should we check the bitrate to see if that fits in an S/PDIF
|
||||
* frame? */
|
||||
|
||||
/* Check if there's anything to propagate to the output port */
|
||||
if (!mmal_format_compare(in->format, out->format))
|
||||
return MMAL_SUCCESS;
|
||||
if (out->format->encoding == MMAL_ENCODING_PCM_SIGNED &&
|
||||
in->format->es->audio.sample_rate ==
|
||||
out->format->es->audio.sample_rate)
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
/* If the output port is not enabled we just need to update its format.
|
||||
* Otherwise we'll have to trigger a format changed event for it. */
|
||||
if (!out->is_enabled)
|
||||
{
|
||||
if (out->format->encoding != MMAL_ENCODING_PCM_SIGNED)
|
||||
mmal_format_copy(out->format, in->format);
|
||||
out->format->es->audio.sample_rate = in->format->es->audio.sample_rate;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Send an event on the output port */
|
||||
return spdif_send_event_format_changed(component, out, in->format);
|
||||
}
|
||||
|
||||
/** Set format on output port */
|
||||
static MMAL_STATUS_T spdif_output_port_format_commit(MMAL_PORT_T *out)
|
||||
{
|
||||
int supported = 0;
|
||||
|
||||
if (out->format->type == MMAL_ES_TYPE_AUDIO &&
|
||||
out->format->encoding == MMAL_ENCODING_PCM_SIGNED &&
|
||||
out->format->es->audio.channels == 2 &&
|
||||
out->format->es->audio.bits_per_sample == 16)
|
||||
supported = 1;
|
||||
if (out->format->type == MMAL_ES_TYPE_AUDIO &&
|
||||
(out->format->encoding == MMAL_ENCODING_AC3 ||
|
||||
out->format->encoding == MMAL_ENCODING_EAC3))
|
||||
supported = 1;
|
||||
|
||||
if (!supported)
|
||||
{
|
||||
LOG_ERROR("invalid format %4.4s, %ichan, %ibps",
|
||||
(char *)&out->format->encoding, out->format->es->audio.channels,
|
||||
out->format->es->audio.bits_per_sample);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
out->priv->module->needs_configuring = 0;
|
||||
mmal_component_action_trigger(out->component);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_spdif(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
MMAL_PARAM_UNUSED(name);
|
||||
|
||||
/* Allocate the context for our module */
|
||||
component->priv->module = module = vcos_malloc(sizeof(*module), "mmal module");
|
||||
if (!module)
|
||||
return MMAL_ENOMEM;
|
||||
memset(module, 0, sizeof(*module));
|
||||
|
||||
component->priv->pf_destroy = spdif_component_destroy;
|
||||
|
||||
/* Allocate and initialise all the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->input)
|
||||
goto error;
|
||||
component->input_num = 1;
|
||||
component->input[0]->priv->pf_enable = spdif_port_enable;
|
||||
component->input[0]->priv->pf_disable = spdif_port_disable;
|
||||
component->input[0]->priv->pf_flush = spdif_port_flush;
|
||||
component->input[0]->priv->pf_send = spdif_port_send;
|
||||
component->input[0]->priv->pf_set_format = spdif_input_port_format_commit;
|
||||
component->input[0]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->input[0]->priv->module->queue)
|
||||
goto error;
|
||||
|
||||
component->output = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_OUTPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->output)
|
||||
goto error;
|
||||
component->output_num = 1;
|
||||
component->output[0]->priv->pf_enable = spdif_port_enable;
|
||||
component->output[0]->priv->pf_disable = spdif_port_disable;
|
||||
component->output[0]->priv->pf_flush = spdif_port_flush;
|
||||
component->output[0]->priv->pf_send = spdif_port_send;
|
||||
component->output[0]->priv->pf_set_format = spdif_output_port_format_commit;
|
||||
component->output[0]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->output[0]->priv->module->queue)
|
||||
goto error;
|
||||
|
||||
status = mmal_component_action_register(component, spdif_do_processing_loop);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
component->input[0]->format->type = MMAL_ES_TYPE_AUDIO;
|
||||
component->input[0]->format->encoding = MMAL_ENCODING_AC3;
|
||||
component->input[0]->buffer_size_min =
|
||||
component->input[0]->buffer_size_recommended = INPUT_MIN_BUFFER_SIZE;
|
||||
component->input[0]->buffer_num_min =
|
||||
component->input[0]->buffer_num_recommended = INPUT_MIN_BUFFER_NUM;
|
||||
|
||||
component->output[0]->format->type = MMAL_ES_TYPE_AUDIO;
|
||||
component->output[0]->format->encoding = MMAL_ENCODING_AC3;
|
||||
component->output[0]->format->es->audio.channels = 2;
|
||||
component->output[0]->format->es->audio.bits_per_sample = 16;
|
||||
component->output[0]->buffer_size_min =
|
||||
component->output[0]->buffer_size_recommended = OUTPUT_MIN_BUFFER_SIZE;
|
||||
component->output[0]->buffer_num_min =
|
||||
component->output[0]->buffer_num_recommended = OUTPUT_MIN_BUFFER_NUM;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
spdif_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_spdif);
|
||||
void mmal_register_component_spdif(void)
|
||||
{
|
||||
mmal_component_supplier_register("spdif", mmal_component_create_spdif);
|
||||
}
|
@ -1,345 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#define SPLITTER_OUTPUT_PORTS_NUM 4 /* 4 should do for now */
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef struct MMAL_COMPONENT_MODULE_T
|
||||
{
|
||||
uint32_t enabled_flags; /**< Flags indicating which output port is enabled */
|
||||
uint32_t sent_flags; /**< Flags indicating which output port we've already sent data to */
|
||||
MMAL_BOOL_T error; /**< Error state */
|
||||
|
||||
} MMAL_COMPONENT_MODULE_T;
|
||||
|
||||
typedef struct MMAL_PORT_MODULE_T
|
||||
{
|
||||
MMAL_QUEUE_T *queue; /**< queue for the buffers sent to the ports */
|
||||
|
||||
} MMAL_PORT_MODULE_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T splitter_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < component->input_num; i++)
|
||||
if(component->input[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->input[i]->priv->module->queue);
|
||||
if(component->input_num)
|
||||
mmal_ports_free(component->input, component->input_num);
|
||||
|
||||
for(i = 0; i < component->output_num; i++)
|
||||
if(component->output[i]->priv->module->queue)
|
||||
mmal_queue_destroy(component->output[i]->priv->module->queue);
|
||||
if(component->output_num)
|
||||
mmal_ports_free(component->output, component->output_num);
|
||||
|
||||
vcos_free(component->priv->module);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Enable processing on a port */
|
||||
static MMAL_STATUS_T splitter_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
#if 0
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
uint32_t buffer_num, buffer_size;
|
||||
unsigned int i;
|
||||
|
||||
/* Find the max and apply that to all ports */
|
||||
buffer_num = component->input[0]->buffer_num;
|
||||
buffer_size = component->input[0]->buffer_size;
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
{
|
||||
buffer_num = MMAL_MAX(buffer_num, component->output[i]->buffer_num);
|
||||
buffer_size = MMAL_MAX(buffer_num, component->output[i]->buffer_size);
|
||||
}
|
||||
component->input[0]->buffer_num = buffer_num;
|
||||
component->input[0]->buffer_size = buffer_size;
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
{
|
||||
component->output[i]->buffer_num = buffer_num;
|
||||
component->output[i]->buffer_size = buffer_num;
|
||||
}
|
||||
#endif
|
||||
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
if (port->buffer_size)
|
||||
if (port->type == MMAL_PORT_TYPE_OUTPUT)
|
||||
port->component->priv->module->enabled_flags |= (1<<port->index);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Flush a port */
|
||||
static MMAL_STATUS_T splitter_port_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PORT_MODULE_T *port_module = port->priv->module;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/* Flush buffers that our component is holding on to */
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
while(buffer)
|
||||
{
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
buffer = mmal_queue_get(port_module->queue);
|
||||
}
|
||||
|
||||
if (port->type == MMAL_PORT_TYPE_INPUT)
|
||||
port->component->priv->module->sent_flags = 0;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Disable processing on a port */
|
||||
static MMAL_STATUS_T splitter_port_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
if (port->type == MMAL_PORT_TYPE_OUTPUT)
|
||||
port->component->priv->module->enabled_flags &= ~(1<<port->index);
|
||||
|
||||
/* We just need to flush our internal queue */
|
||||
return splitter_port_flush(port);
|
||||
}
|
||||
|
||||
/** Send a buffer header to a port */
|
||||
static MMAL_STATUS_T splitter_send_output(MMAL_BUFFER_HEADER_T *buffer, MMAL_PORT_T *out_port)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *out;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
/* Get a buffer header from output port */
|
||||
out = mmal_queue_get(out_port->priv->module->queue);
|
||||
if (!out)
|
||||
return MMAL_EAGAIN;
|
||||
|
||||
/* Copy our input buffer header */
|
||||
status = mmal_buffer_header_replicate(out, buffer);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
/* Send buffer back */
|
||||
mmal_port_buffer_header_callback(out_port, out);
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
mmal_queue_put_back(out_port->priv->module->queue, out);
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Send a buffer header to a port */
|
||||
static MMAL_STATUS_T splitter_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_MODULE_T *module = component->priv->module;
|
||||
MMAL_PORT_T *in_port, *out_port;
|
||||
MMAL_BUFFER_HEADER_T *in;
|
||||
MMAL_STATUS_T status;
|
||||
unsigned int i;
|
||||
|
||||
mmal_queue_put(port->priv->module->queue, buffer);
|
||||
|
||||
if (module->error)
|
||||
return MMAL_SUCCESS; /* Just do nothing */
|
||||
|
||||
/* Get input buffer header */
|
||||
in_port = component->input[0];
|
||||
in = mmal_queue_get(in_port->priv->module->queue);
|
||||
if (!in)
|
||||
return MMAL_SUCCESS; /* Nothing to do */
|
||||
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
{
|
||||
out_port = component->output[i];
|
||||
status = splitter_send_output(in, out_port);
|
||||
|
||||
if (status != MMAL_SUCCESS && status != MMAL_EAGAIN)
|
||||
goto error;
|
||||
|
||||
if (status == MMAL_SUCCESS)
|
||||
module->sent_flags |= (1<<i);
|
||||
}
|
||||
|
||||
/* Check if we're done with the input buffer */
|
||||
if ((module->sent_flags & module->enabled_flags) == module->enabled_flags)
|
||||
{
|
||||
in->length = 0; /* Consume the input buffer */
|
||||
mmal_port_buffer_header_callback(in_port, in);
|
||||
module->sent_flags = 0;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* We're not done yet so put the buffer back in the queue */
|
||||
mmal_queue_put(in_port->priv->module->queue, in);
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
mmal_queue_put(in_port->priv->module->queue, in);
|
||||
|
||||
status = mmal_event_error_send(port->component, status);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("unable to send an error event buffer (%i)", (int)status);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
module->error = 1;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set format on a port */
|
||||
static MMAL_STATUS_T splitter_port_format_commit(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_STATUS_T status;
|
||||
unsigned int i;
|
||||
|
||||
/* Sanity check */
|
||||
if (port->type == MMAL_PORT_TYPE_OUTPUT)
|
||||
{
|
||||
LOG_ERROR("output port is read-only");
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
/* Commit the format on all output ports */
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
{
|
||||
status = mmal_format_full_copy(component->output[i]->format, port->format);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T splitter_port_parameter_set(MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
unsigned int i;
|
||||
|
||||
switch (param->id)
|
||||
{
|
||||
case MMAL_PARAMETER_BUFFER_REQUIREMENTS:
|
||||
{
|
||||
/* Propagate the requirements to all the ports */
|
||||
const MMAL_PARAMETER_BUFFER_REQUIREMENTS_T *req = (const MMAL_PARAMETER_BUFFER_REQUIREMENTS_T *)param;
|
||||
uint32_t buffer_num_min = MMAL_MAX(port->buffer_num_min, req->buffer_num_min);
|
||||
uint32_t buffer_num_recommended = MMAL_MAX(port->buffer_num_recommended, req->buffer_num_recommended);
|
||||
uint32_t buffer_size_min = MMAL_MAX(port->buffer_size_min, req->buffer_size_min);
|
||||
uint32_t buffer_size_recommended = MMAL_MAX(port->buffer_size_recommended, req->buffer_size_recommended);
|
||||
|
||||
component->input[0]->buffer_num_min = buffer_num_min;
|
||||
component->input[0]->buffer_num_recommended = buffer_num_recommended;
|
||||
component->input[0]->buffer_size_min = buffer_size_min;
|
||||
component->input[0]->buffer_size_recommended = buffer_size_recommended;
|
||||
for (i = 0; i < component->output_num; i++)
|
||||
{
|
||||
component->output[i]->buffer_num_min = buffer_num_min;
|
||||
component->output[i]->buffer_num_recommended = buffer_num_recommended;
|
||||
component->output[i]->buffer_size_min = buffer_size_min;
|
||||
component->output[i]->buffer_size_recommended = buffer_size_recommended;
|
||||
}
|
||||
|
||||
}
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
default:
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_splitter(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_MODULE_T *module;
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
unsigned int i;
|
||||
MMAL_PARAM_UNUSED(name);
|
||||
|
||||
/* Allocate the context for our module */
|
||||
component->priv->module = module = vcos_malloc(sizeof(*module), "mmal module");
|
||||
if (!module)
|
||||
return MMAL_ENOMEM;
|
||||
memset(module, 0, sizeof(*module));
|
||||
|
||||
component->priv->pf_destroy = splitter_component_destroy;
|
||||
|
||||
/* Allocate and initialise all the ports for this component */
|
||||
component->input = mmal_ports_alloc(component, 1, MMAL_PORT_TYPE_INPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->input)
|
||||
goto error;
|
||||
component->input_num = 1;
|
||||
component->input[0]->priv->pf_enable = splitter_port_enable;
|
||||
component->input[0]->priv->pf_disable = splitter_port_disable;
|
||||
component->input[0]->priv->pf_flush = splitter_port_flush;
|
||||
component->input[0]->priv->pf_send = splitter_port_send;
|
||||
component->input[0]->priv->pf_set_format = splitter_port_format_commit;
|
||||
component->input[0]->priv->pf_parameter_set = splitter_port_parameter_set;
|
||||
component->input[0]->buffer_num_min = 1;
|
||||
component->input[0]->buffer_num_recommended = 0;
|
||||
component->input[0]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->input[0]->priv->module->queue)
|
||||
goto error;
|
||||
|
||||
component->output = mmal_ports_alloc(component, SPLITTER_OUTPUT_PORTS_NUM,
|
||||
MMAL_PORT_TYPE_OUTPUT, sizeof(MMAL_PORT_MODULE_T));
|
||||
if(!component->output)
|
||||
goto error;
|
||||
component->output_num = SPLITTER_OUTPUT_PORTS_NUM;
|
||||
for(i = 0; i < component->output_num; i++)
|
||||
{
|
||||
component->output[i]->priv->pf_enable = splitter_port_enable;
|
||||
component->output[i]->priv->pf_disable = splitter_port_disable;
|
||||
component->output[i]->priv->pf_flush = splitter_port_flush;
|
||||
component->output[i]->priv->pf_send = splitter_port_send;
|
||||
component->output[i]->priv->pf_set_format = splitter_port_format_commit;
|
||||
component->output[i]->priv->pf_parameter_set = splitter_port_parameter_set;
|
||||
component->output[i]->buffer_num_min = 1;
|
||||
component->output[i]->buffer_num_recommended = 0;
|
||||
component->output[i]->capabilities = MMAL_PORT_CAPABILITY_PASSTHROUGH;
|
||||
component->output[i]->priv->module->queue = mmal_queue_create();
|
||||
if(!component->output[i]->priv->module->queue)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
splitter_component_destroy(component);
|
||||
return status;
|
||||
}
|
||||
|
||||
MMAL_CONSTRUCTOR(mmal_register_component_splitter);
|
||||
void mmal_register_component_splitter(void)
|
||||
{
|
||||
mmal_component_supplier_register("splitter", mmal_component_create_splitter);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
add_library (mmal_core ${LIBRARY_TYPE}
|
||||
mmal_format.c
|
||||
mmal_port.c
|
||||
mmal_port_clock.c
|
||||
mmal_component.c
|
||||
mmal_buffer.c
|
||||
mmal_queue.c
|
||||
mmal_pool.c
|
||||
mmal_events.c
|
||||
mmal_logging.c
|
||||
mmal_clock.c
|
||||
)
|
||||
|
||||
target_link_libraries (mmal_core vcos)
|
||||
|
||||
install(TARGETS mmal_core DESTINATION lib)
|
||||
install(FILES
|
||||
mmal_buffer_private.h
|
||||
mmal_clock_private.h
|
||||
mmal_component_private.h
|
||||
mmal_core_private.h
|
||||
mmal_port_private.h
|
||||
DESTINATION include/interface/mmal/core
|
||||
)
|
@ -1,188 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "mmal_buffer.h"
|
||||
#include "core/mmal_buffer_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
#define ROUND_UP(s,align) ((((unsigned long)(s)) & ~((align)-1)) + (align))
|
||||
#define DEFAULT_COMMAND_SIZE 256 /**< 256 bytes of space for commands */
|
||||
#define ALIGN 8
|
||||
|
||||
/** Acquire a buffer header */
|
||||
void mmal_buffer_header_acquire(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
#ifdef ENABLE_MMAL_EXTRA_LOGGING
|
||||
LOG_TRACE("%p (%i)", header, (int)header->priv->refcount+1);
|
||||
#endif
|
||||
header->priv->refcount++;
|
||||
}
|
||||
|
||||
/** Reset a buffer header */
|
||||
void mmal_buffer_header_reset(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
header->length = 0;
|
||||
header->offset = 0;
|
||||
header->flags = 0;
|
||||
header->pts = MMAL_TIME_UNKNOWN;
|
||||
header->dts = MMAL_TIME_UNKNOWN;
|
||||
}
|
||||
|
||||
/** Release a buffer header */
|
||||
void mmal_buffer_header_release(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
#ifdef ENABLE_MMAL_EXTRA_LOGGING
|
||||
LOG_TRACE("%p (%i)", header, (int)header->priv->refcount-1);
|
||||
#endif
|
||||
|
||||
if(--header->priv->refcount != 0)
|
||||
return;
|
||||
|
||||
if (header->priv->pf_pre_release)
|
||||
{
|
||||
if (header->priv->pf_pre_release(header, header->priv->pre_release_userdata))
|
||||
return; /* delay releasing the buffer */
|
||||
}
|
||||
mmal_buffer_header_release_continue(header);
|
||||
}
|
||||
|
||||
/** Finalise buffer release following a pre-release event */
|
||||
void mmal_buffer_header_release_continue(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
mmal_buffer_header_reset(header);
|
||||
if (header->priv->reference)
|
||||
mmal_buffer_header_release(header->priv->reference);
|
||||
header->priv->reference = 0;
|
||||
header->priv->pf_release(header);
|
||||
}
|
||||
|
||||
/** Replicate a buffer header */
|
||||
MMAL_STATUS_T mmal_buffer_header_replicate(MMAL_BUFFER_HEADER_T *dest,
|
||||
MMAL_BUFFER_HEADER_T *src)
|
||||
{
|
||||
#ifdef ENABLE_MMAL_EXTRA_LOGGING
|
||||
LOG_TRACE("dest: %p src: %p", dest, src);
|
||||
#endif
|
||||
|
||||
if (!dest || !src || dest->priv->reference)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
mmal_buffer_header_acquire(src);
|
||||
dest->priv->reference = src;
|
||||
|
||||
/* Copy all the relevant fields */
|
||||
dest->cmd = src->cmd;
|
||||
dest->alloc_size = src->alloc_size;
|
||||
dest->data = src->data;
|
||||
dest->offset = src->offset;
|
||||
dest->length = src->length;
|
||||
dest->flags = src->flags;
|
||||
dest->pts = src->pts;
|
||||
dest->dts = src->dts;
|
||||
*dest->type = *src->type;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Get the size in bytes of a fully initialised MMAL_BUFFER_HEADER_T */
|
||||
unsigned int mmal_buffer_header_size(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
unsigned int header_size;
|
||||
|
||||
header_size = ROUND_UP(sizeof(*header), ALIGN);
|
||||
header_size += ROUND_UP(sizeof(*header->type), ALIGN);
|
||||
header_size += ROUND_UP(DEFAULT_COMMAND_SIZE, ALIGN);
|
||||
header_size += ROUND_UP(sizeof(*header->priv), ALIGN);
|
||||
return header_size;
|
||||
}
|
||||
|
||||
/** Initialise a MMAL_BUFFER_HEADER_T */
|
||||
MMAL_BUFFER_HEADER_T *mmal_buffer_header_initialise(void *mem, unsigned int length)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *header;
|
||||
unsigned int header_size = mmal_buffer_header_size(0);
|
||||
|
||||
if(length < header_size)
|
||||
return 0;
|
||||
|
||||
memset(mem, 0, header_size);
|
||||
|
||||
header = (MMAL_BUFFER_HEADER_T *)mem;
|
||||
header->type = (void *)&header[1];
|
||||
header->priv = (MMAL_BUFFER_HEADER_PRIVATE_T *)&header->type[1];
|
||||
return header;
|
||||
}
|
||||
|
||||
/** Return a pointer to the area reserved for the driver */
|
||||
MMAL_DRIVER_BUFFER_T *mmal_buffer_header_driver_data(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
return (MMAL_DRIVER_BUFFER_T *)header->priv->driver_area;
|
||||
}
|
||||
|
||||
/** Return a pointer to a referenced buffer header */
|
||||
MMAL_BUFFER_HEADER_T *mmal_buffer_header_reference(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
return header->priv->reference;
|
||||
}
|
||||
|
||||
#ifdef __VIDEOCORE__
|
||||
# include "vcfw/rtos/common/rtos_common_mem.h"
|
||||
#endif
|
||||
|
||||
/** Lock the data buffer contained in the buffer header */
|
||||
MMAL_STATUS_T mmal_buffer_header_mem_lock(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
#ifdef __VIDEOCORE__
|
||||
uint8_t *data = mem_lock((MEM_HANDLE_T)header->data);
|
||||
if (!data)
|
||||
return MMAL_EINVAL;
|
||||
header->priv->payload_handle = (void *)header->data;
|
||||
header->data = data;
|
||||
#else
|
||||
MMAL_PARAM_UNUSED(header);
|
||||
#endif
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Unlock the data buffer contained in the buffer header */
|
||||
void mmal_buffer_header_mem_unlock(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
#ifdef __VIDEOCORE__
|
||||
mem_unlock((MEM_HANDLE_T)header->priv->payload_handle);
|
||||
header->data = header->priv->payload_handle;
|
||||
#else
|
||||
MMAL_PARAM_UNUSED(header);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Set a pre-release callback for a buffer header */
|
||||
void mmal_buffer_header_pre_release_cb_set(MMAL_BUFFER_HEADER_T *header, MMAL_BH_PRE_RELEASE_CB_T cb, void *userdata)
|
||||
{
|
||||
header->priv->pf_pre_release = cb;
|
||||
header->priv->pre_release_userdata = userdata;
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_BUFFER_PRIVATE_H
|
||||
#define MMAL_BUFFER_PRIVATE_H
|
||||
|
||||
/** Typedef for the private area the framework reserves for the driver / communication layer */
|
||||
typedef struct MMAL_DRIVER_BUFFER_T MMAL_DRIVER_BUFFER_T;
|
||||
|
||||
/** Size of the private area the framework reserves for the driver / communication layer */
|
||||
#define MMAL_DRIVER_BUFFER_SIZE 32
|
||||
|
||||
/** Typedef for the framework's private area in the buffer header */
|
||||
typedef struct MMAL_BUFFER_HEADER_PRIVATE_T
|
||||
{
|
||||
/** Callback invoked just prior to actually releasing the buffer header. Returns TRUE if
|
||||
* release should be delayed. */
|
||||
MMAL_BH_PRE_RELEASE_CB_T pf_pre_release;
|
||||
void *pre_release_userdata;
|
||||
|
||||
/** Callback used to release / recycle the buffer header. This needs to be set by
|
||||
* whoever allocates the buffer header. */
|
||||
void (*pf_release)(struct MMAL_BUFFER_HEADER_T *header);
|
||||
void *owner; /**< Context set by the allocator of the buffer header and passed
|
||||
during the release callback */
|
||||
|
||||
int32_t refcount; /**< Reference count of the buffer header. When it reaches 0,
|
||||
the release callback will be called. */
|
||||
|
||||
MMAL_BUFFER_HEADER_T *reference; /**< Reference to another acquired buffer header. */
|
||||
|
||||
/** Callback used to free the payload associated with this buffer header. This is only
|
||||
* used if the buffer header was created by MMAL with a payload associated with it. */
|
||||
void (*pf_payload_free)(void *payload_context, void *payload);
|
||||
void *payload; /**< Pointer / handle to the allocated payload buffer */
|
||||
void *payload_context; /**< Pointer to the context of the payload allocator */
|
||||
uint32_t payload_size; /**< Allocated size in bytes of payload buffer */
|
||||
|
||||
void *component_data; /**< Field reserved for use by the component */
|
||||
void *payload_handle; /**< Field reserved for mmal_buffer_header_mem_lock */
|
||||
|
||||
uint8_t driver_area[MMAL_DRIVER_BUFFER_SIZE];
|
||||
|
||||
} MMAL_BUFFER_HEADER_PRIVATE_T;
|
||||
|
||||
/** Get the size in bytes of a fully initialised MMAL_BUFFER_HEADER_T */
|
||||
unsigned int mmal_buffer_header_size(MMAL_BUFFER_HEADER_T *header);
|
||||
|
||||
/** Initialise a MMAL_BUFFER_HEADER_T */
|
||||
MMAL_BUFFER_HEADER_T *mmal_buffer_header_initialise(void *mem, unsigned int length);
|
||||
|
||||
/** Return a pointer to the area reserved for the driver.
|
||||
*/
|
||||
MMAL_DRIVER_BUFFER_T *mmal_buffer_header_driver_data(MMAL_BUFFER_HEADER_T *);
|
||||
|
||||
/** Return a pointer to a referenced buffer header.
|
||||
* It is the caller's responsibility to ensure that the reference is still
|
||||
* valid when using it.
|
||||
*/
|
||||
MMAL_BUFFER_HEADER_T *mmal_buffer_header_reference(MMAL_BUFFER_HEADER_T *header);
|
||||
|
||||
#endif /* MMAL_BUFFER_PRIVATE_H */
|
@ -1,892 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
#include "interface/mmal/mmal_logging.h"
|
||||
#include "interface/mmal/util/mmal_list.h"
|
||||
#include "interface/mmal/util/mmal_util_rational.h"
|
||||
#include "interface/mmal/core/mmal_clock_private.h"
|
||||
|
||||
#ifdef __VIDEOCORE__
|
||||
/* Use RTOS timer for improved accuracy */
|
||||
# include "vcfw/rtos/rtos.h"
|
||||
# define USE_RTOS_TIMER
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
#ifdef USE_RTOS_TIMER
|
||||
# define MIN_TIMER_DELAY 1 /* microseconds */
|
||||
#else
|
||||
# define MIN_TIMER_DELAY 10000 /* microseconds */
|
||||
#endif
|
||||
|
||||
/* 1.0 in Q16 format */
|
||||
#define Q16_ONE (1 << 16)
|
||||
|
||||
/* Maximum number of pending requests */
|
||||
#define CLOCK_REQUEST_SLOTS 32
|
||||
|
||||
/* Number of microseconds the clock tries to service requests early
|
||||
* to account for processing overhead */
|
||||
#define CLOCK_TARGET_OFFSET 20
|
||||
|
||||
/* Default wait time (in microseconds) when the clock is paused. */
|
||||
#define CLOCK_WAIT_TIME 200000LL
|
||||
|
||||
/* In order to prevent unnecessary clock jitter when updating the local media-time of the
|
||||
* clock, an upper and lower threshold is used. If the difference between the reference
|
||||
* media-time and local media-time is greater than the upper threshold, local media-time
|
||||
* is set to the reference time. Below this threshold, a weighted moving average is applied
|
||||
* to the difference. If this is greater than the lower threshold, the local media-time is
|
||||
* adjusted by the average. Anything below the lower threshold is ignored. */
|
||||
#define CLOCK_UPDATE_THRESHOLD_LOWER 8000 /* microseconds */
|
||||
#define CLOCK_UPDATE_THRESHOLD_UPPER 50000 /* microseconds */
|
||||
|
||||
/* Default threshold after which backward jumps in media time are treated as a discontinuity. */
|
||||
#define CLOCK_DISCONT_THRESHOLD 1000000 /* microseconds */
|
||||
|
||||
/* Default duration for which a discontinuity applies. Used for wall time duration for which
|
||||
* a discontinuity continues to cause affected requests to fire immediately, and as the media
|
||||
* time span for detecting discontinuous requests. */
|
||||
#define CLOCK_DISCONT_DURATION 1000000 /* microseconds */
|
||||
|
||||
/* Absolute value macro */
|
||||
#define ABS_VALUE(v) (((v) < 0) ? -(v) : (v))
|
||||
|
||||
/* Macros used to make clock access thread-safe */
|
||||
#define LOCK(p) vcos_mutex_lock(&(p)->lock);
|
||||
#define UNLOCK(p) vcos_mutex_unlock(&(p)->lock);
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
#ifdef USE_RTOS_TIMER
|
||||
typedef RTOS_TIMER_T MMAL_TIMER_T;
|
||||
#else
|
||||
typedef VCOS_TIMER_T MMAL_TIMER_T;
|
||||
#endif
|
||||
|
||||
typedef struct MMAL_CLOCK_REQUEST_T
|
||||
{
|
||||
MMAL_LIST_ELEMENT_T link; /**< must be first */
|
||||
MMAL_CLOCK_VOID_FP priv; /**< client-supplied function pointer */
|
||||
MMAL_CLOCK_REQUEST_CB cb; /**< client-supplied callback to invoke */
|
||||
void *cb_data; /**< client-supplied callback data */
|
||||
int64_t media_time; /**< media-time requested by the client (microseconds) */
|
||||
int64_t media_time_adj; /**< adjusted media-time at which the request will
|
||||
be serviced in microseconds (this takes
|
||||
CLOCK_TARGET_OFFSET into account) */
|
||||
} MMAL_CLOCK_REQUEST_T;
|
||||
|
||||
typedef struct MMAL_CLOCK_PRIVATE_T
|
||||
{
|
||||
MMAL_CLOCK_T clock; /**< must be first */
|
||||
|
||||
MMAL_BOOL_T is_active; /**< TRUE -> media-time is advancing */
|
||||
|
||||
MMAL_BOOL_T scheduling; /**< TRUE -> client request scheduling is enabled */
|
||||
MMAL_BOOL_T stop_thread;
|
||||
VCOS_SEMAPHORE_T event;
|
||||
VCOS_THREAD_T thread; /**< processing thread for client requests */
|
||||
MMAL_TIMER_T timer; /**< used for scheduling client requests */
|
||||
|
||||
VCOS_MUTEX_T lock; /**< lock access to the request lists */
|
||||
|
||||
int32_t scale; /**< media-time scale factor (Q16 format) */
|
||||
int32_t scale_inv; /**< 1/scale (Q16 format) */
|
||||
MMAL_RATIONAL_T scale_rational;
|
||||
/**< clock scale as a rational number; keep a copy since
|
||||
converting from Q16 will result in precision errors */
|
||||
|
||||
int64_t average_ref_diff; /**< media-time moving average adjustment */
|
||||
int64_t media_time; /**< current local media-time in microseconds */
|
||||
uint32_t media_time_frac; /**< media-time fraction in microseconds (Q24 format) */
|
||||
int64_t wall_time; /**< current local wall-time (microseconds) */
|
||||
uint32_t rtc_at_update; /**< real-time clock value at local time update (microseconds) */
|
||||
int64_t media_time_at_timer;
|
||||
/**< media-time when the timer was last set */
|
||||
|
||||
int64_t discont_expiry; /**< wall-time when discontinuity expires; 0 = no discontinuity
|
||||
in effect */
|
||||
int64_t discont_start; /**< media-time at start of discontinuity
|
||||
(n/a if discont_expiry = 0) */
|
||||
int64_t discont_end; /**< media-time at end of discontinuity
|
||||
(n/a if discont_expiry = 0) */
|
||||
int64_t discont_threshold;/**< Threshold after which backward jumps in media time are treated
|
||||
as a discontinuity (microseconds) */
|
||||
int64_t discont_duration; /**< Duration (wall-time) for which a discontinuity applies */
|
||||
|
||||
int64_t request_threshold;/**< Threshold after which frames exceeding the media-time are
|
||||
dropped (microseconds) */
|
||||
MMAL_BOOL_T request_threshold_enable;/**< Enable the request threshold */
|
||||
int64_t update_threshold_lower;
|
||||
/**< Time differences below this threshold are ignored */
|
||||
int64_t update_threshold_upper;
|
||||
/**< Time differences above this threshold reset media time */
|
||||
|
||||
/* Client requests */
|
||||
struct
|
||||
{
|
||||
MMAL_LIST_T* list_free;
|
||||
MMAL_LIST_T* list_pending;
|
||||
MMAL_CLOCK_REQUEST_T pool[CLOCK_REQUEST_SLOTS];
|
||||
} request;
|
||||
|
||||
} MMAL_CLOCK_PRIVATE_T;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
static void mmal_clock_wake_thread(MMAL_CLOCK_PRIVATE_T *private);
|
||||
|
||||
/*****************************************************************************
|
||||
* Timer-specific functions
|
||||
*****************************************************************************/
|
||||
/* Callback invoked when timer expires */
|
||||
#ifdef USE_RTOS_TIMER
|
||||
static void mmal_clock_timer_cb(MMAL_TIMER_T *timer, void *ctx)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(timer);
|
||||
/* Notify the worker thread */
|
||||
mmal_clock_wake_thread((MMAL_CLOCK_PRIVATE_T*)ctx);
|
||||
}
|
||||
#else
|
||||
static void mmal_clock_timer_cb(void *ctx)
|
||||
{
|
||||
/* Notify the worker thread */
|
||||
mmal_clock_wake_thread((MMAL_CLOCK_PRIVATE_T*)ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create a timer */
|
||||
static inline MMAL_BOOL_T mmal_clock_timer_create(MMAL_TIMER_T *timer, void *ctx)
|
||||
{
|
||||
#ifdef USE_RTOS_TIMER
|
||||
return (rtos_timer_init(timer, mmal_clock_timer_cb, ctx) == 0);
|
||||
#else
|
||||
return (vcos_timer_create(timer, "mmal-clock timer", mmal_clock_timer_cb, ctx) == VCOS_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Destroy a timer */
|
||||
static inline void mmal_clock_timer_destroy(MMAL_TIMER_T *timer)
|
||||
{
|
||||
#ifdef USE_RTOS_TIMER
|
||||
/* Nothing to do */
|
||||
#else
|
||||
vcos_timer_delete(timer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set the timer. Delay is in microseconds. */
|
||||
static inline void mmal_clock_timer_set(MMAL_TIMER_T *timer, int64_t delay_us)
|
||||
{
|
||||
#ifdef USE_RTOS_TIMER
|
||||
rtos_timer_set(timer, (RTOS_TIMER_TIME_T)delay_us);
|
||||
#else
|
||||
/* VCOS timer only provides millisecond accuracy */
|
||||
vcos_timer_set(timer, (VCOS_UNSIGNED)(delay_us / 1000));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Stop the timer. */
|
||||
static inline void mmal_clock_timer_cancel(MMAL_TIMER_T *timer)
|
||||
{
|
||||
#ifdef USE_RTOS_TIMER
|
||||
rtos_timer_cancel(timer);
|
||||
#else
|
||||
vcos_timer_cancel(timer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Clock module private functions
|
||||
*****************************************************************************/
|
||||
/* Update the internal wall-time and media-time */
|
||||
static void mmal_clock_update_local_time_locked(MMAL_CLOCK_PRIVATE_T *private)
|
||||
{
|
||||
uint32_t time_now = vcos_getmicrosecs();
|
||||
uint32_t time_diff = (time_now > private->rtc_at_update) ? (time_now - private->rtc_at_update) : 0;
|
||||
|
||||
private->wall_time += time_diff;
|
||||
|
||||
/* For small clock scale values (i.e. slow motion), the media-time increment
|
||||
* could potentially be rounded down when doing lots of updates, so also keep
|
||||
* track of the fractional increment. */
|
||||
int64_t media_diff = ((int64_t)time_diff) * (int64_t)(private->scale << 8) + private->media_time_frac;
|
||||
|
||||
private->media_time += media_diff >> 24;
|
||||
private->media_time_frac = media_diff & ((1<<24)-1);
|
||||
|
||||
private->rtc_at_update = time_now;
|
||||
}
|
||||
|
||||
/* Return the current local media-time */
|
||||
static int64_t mmal_clock_media_time_get_locked(MMAL_CLOCK_PRIVATE_T *private)
|
||||
{
|
||||
mmal_clock_update_local_time_locked(private);
|
||||
return private->media_time;
|
||||
}
|
||||
|
||||
/* Comparison function used for inserting a request into
|
||||
* the list of pending requests when clock scale is positive. */
|
||||
static int mmal_clock_request_compare_pos(MMAL_LIST_ELEMENT_T *lhs, MMAL_LIST_ELEMENT_T *rhs)
|
||||
{
|
||||
return ((MMAL_CLOCK_REQUEST_T*)lhs)->media_time_adj < ((MMAL_CLOCK_REQUEST_T*)rhs)->media_time_adj;
|
||||
}
|
||||
|
||||
/* Comparison function used for inserting a request into
|
||||
* the list of pending requests when clock scale is negative. */
|
||||
static int mmal_clock_request_compare_neg(MMAL_LIST_ELEMENT_T *lhs, MMAL_LIST_ELEMENT_T *rhs)
|
||||
{
|
||||
return ((MMAL_CLOCK_REQUEST_T*)lhs)->media_time_adj > ((MMAL_CLOCK_REQUEST_T*)rhs)->media_time_adj;
|
||||
}
|
||||
|
||||
/* Insert a new request into the list of pending requests */
|
||||
static MMAL_BOOL_T mmal_clock_request_insert(MMAL_CLOCK_PRIVATE_T *private, MMAL_CLOCK_REQUEST_T *request)
|
||||
{
|
||||
MMAL_LIST_T *list = private->request.list_pending;
|
||||
MMAL_CLOCK_REQUEST_T *pending;
|
||||
|
||||
if (private->stop_thread)
|
||||
return MMAL_FALSE; /* the clock is being destroyed */
|
||||
|
||||
if (list->length == 0)
|
||||
{
|
||||
mmal_list_push_front(list, &request->link);
|
||||
return MMAL_TRUE;
|
||||
}
|
||||
|
||||
/* It is more likely for requests to be received in sequence,
|
||||
* so try adding to the back of the list first before doing
|
||||
* a more expensive list insert. */
|
||||
pending = (MMAL_CLOCK_REQUEST_T*)list->last;
|
||||
if ((private->scale >= 0 && (request->media_time_adj >= pending->media_time_adj)) ||
|
||||
(private->scale < 0 && (request->media_time_adj <= pending->media_time_adj)))
|
||||
{
|
||||
mmal_list_push_back(list, &request->link);
|
||||
}
|
||||
else
|
||||
{
|
||||
mmal_list_insert(list, &request->link,
|
||||
(private->scale >= 0) ? mmal_clock_request_compare_pos : mmal_clock_request_compare_neg);
|
||||
}
|
||||
return MMAL_TRUE;
|
||||
}
|
||||
|
||||
/* Flush all pending requests */
|
||||
static MMAL_STATUS_T mmal_clock_request_flush_locked(MMAL_CLOCK_PRIVATE_T *private,
|
||||
int64_t media_time)
|
||||
{
|
||||
MMAL_LIST_T *pending = private->request.list_pending;
|
||||
MMAL_LIST_T *list_free = private->request.list_free;
|
||||
MMAL_CLOCK_REQUEST_T *request;
|
||||
|
||||
while ((request = (MMAL_CLOCK_REQUEST_T *)mmal_list_pop_front(pending)) != NULL)
|
||||
{
|
||||
/* Inform the client */
|
||||
request->cb(&private->clock, media_time, request->cb_data, request->priv);
|
||||
/* Recycle request slot */
|
||||
mmal_list_push_back(list_free, &request->link);
|
||||
}
|
||||
|
||||
private->media_time_at_timer = 0;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Process all pending requests */
|
||||
static void mmal_clock_process_requests(MMAL_CLOCK_PRIVATE_T *private)
|
||||
{
|
||||
int64_t media_time_now;
|
||||
MMAL_LIST_T* free = private->request.list_free;
|
||||
MMAL_LIST_T* pending = private->request.list_pending;
|
||||
MMAL_CLOCK_REQUEST_T *next;
|
||||
|
||||
if (pending->length == 0 || !private->is_active)
|
||||
return;
|
||||
|
||||
LOCK(private);
|
||||
|
||||
/* Detect discontinuity */
|
||||
if (private->media_time_at_timer != 0)
|
||||
{
|
||||
media_time_now = mmal_clock_media_time_get_locked(private);
|
||||
/* Currently only applied to forward speeds */
|
||||
if (private->scale > 0 &&
|
||||
media_time_now + private->discont_threshold < private->media_time_at_timer)
|
||||
{
|
||||
LOG_INFO("discontinuity: was=%" PRIi64 " now=%" PRIi64 " pending=%d",
|
||||
private->media_time_at_timer, media_time_now, pending->length);
|
||||
|
||||
/* It's likely that packets from before the discontinuity will continue to arrive for
|
||||
* a short time. Ensure these are detected and the requests fired immediately. */
|
||||
private->discont_start = private->media_time_at_timer;
|
||||
private->discont_end = private->discont_start + private->discont_duration;
|
||||
private->discont_expiry = private->wall_time + private->discont_duration;
|
||||
|
||||
/* Fire all pending requests */
|
||||
mmal_clock_request_flush_locked(private, media_time_now);
|
||||
}
|
||||
}
|
||||
|
||||
/* Earliest request is always at the front */
|
||||
next = (MMAL_CLOCK_REQUEST_T*)mmal_list_pop_front(pending);
|
||||
while (next)
|
||||
{
|
||||
media_time_now = mmal_clock_media_time_get_locked(private);
|
||||
|
||||
if (private->discont_expiry != 0 && private->wall_time > private->discont_expiry)
|
||||
private->discont_expiry = 0;
|
||||
|
||||
/* Fire the request if it matches the pending discontinuity or if its requested media time
|
||||
* has been reached. */
|
||||
if ((private->discont_expiry != 0 &&
|
||||
next->media_time_adj >= private->discont_start &&
|
||||
next->media_time_adj < private->discont_end) ||
|
||||
(private->scale > 0 && ((media_time_now + MIN_TIMER_DELAY) >= next->media_time_adj)) ||
|
||||
(private->scale < 0 && ((media_time_now - MIN_TIMER_DELAY) <= next->media_time_adj)))
|
||||
{
|
||||
LOG_TRACE("servicing request: next %"PRIi64" now %"PRIi64, next->media_time_adj, media_time_now);
|
||||
/* Inform the client */
|
||||
next->cb(&private->clock, media_time_now, next->cb_data, next->priv);
|
||||
/* Recycle the request slot */
|
||||
mmal_list_push_back(free, &next->link);
|
||||
/* Move onto next pending request */
|
||||
next = (MMAL_CLOCK_REQUEST_T*)mmal_list_pop_front(pending);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The next request is in the future, so re-schedule the
|
||||
* timer based on the current clock scale and media-time diff */
|
||||
int64_t media_time_delay = ABS_VALUE(media_time_now - next->media_time_adj);
|
||||
int64_t wall_time_delay = ABS_VALUE(((int64_t)private->scale_inv * media_time_delay) >> 16);
|
||||
|
||||
if (private->scale == 0)
|
||||
wall_time_delay = CLOCK_WAIT_TIME; /* Clock is paused */
|
||||
|
||||
/* Put next request back into pending list */
|
||||
mmal_list_push_front(pending, &next->link);
|
||||
next = NULL;
|
||||
|
||||
/* Set the timer */
|
||||
private->media_time_at_timer = media_time_now;
|
||||
mmal_clock_timer_set(&private->timer, wall_time_delay);
|
||||
|
||||
LOG_TRACE("re-schedule timer: now %"PRIi64" delay %"PRIi64, media_time_now, wall_time_delay);
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK(private);
|
||||
}
|
||||
|
||||
/* Trigger the worker thread (if present) */
|
||||
static void mmal_clock_wake_thread(MMAL_CLOCK_PRIVATE_T *private)
|
||||
{
|
||||
if (private->scheduling)
|
||||
vcos_semaphore_post(&private->event);
|
||||
}
|
||||
|
||||
/* Stop the worker thread */
|
||||
static void mmal_clock_stop_thread(MMAL_CLOCK_PRIVATE_T *private)
|
||||
{
|
||||
private->stop_thread = MMAL_TRUE;
|
||||
mmal_clock_wake_thread(private);
|
||||
vcos_thread_join(&private->thread, NULL);
|
||||
}
|
||||
|
||||
/* Main processing thread */
|
||||
static void* mmal_clock_worker_thread(void *ctx)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)ctx;
|
||||
|
||||
while (1)
|
||||
{
|
||||
vcos_semaphore_wait(&private->event);
|
||||
|
||||
/* Either the timer has expired or a new request is pending */
|
||||
mmal_clock_timer_cancel(&private->timer);
|
||||
|
||||
if (private->stop_thread)
|
||||
break;
|
||||
|
||||
mmal_clock_process_requests(private);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create scheduling resources */
|
||||
static MMAL_STATUS_T mmal_clock_create_scheduling(MMAL_CLOCK_PRIVATE_T *private)
|
||||
{
|
||||
unsigned int i;
|
||||
MMAL_BOOL_T timer_status = MMAL_FALSE;
|
||||
VCOS_STATUS_T event_status = VCOS_EINVAL;
|
||||
VCOS_UNSIGNED priority;
|
||||
|
||||
timer_status = mmal_clock_timer_create(&private->timer, private);
|
||||
if (!timer_status)
|
||||
{
|
||||
LOG_ERROR("failed to create timer %p", private);
|
||||
goto error;
|
||||
}
|
||||
|
||||
event_status = vcos_semaphore_create(&private->event, "mmal-clock sema", 0);
|
||||
if (event_status != VCOS_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("failed to create event semaphore %d", event_status);
|
||||
goto error;
|
||||
}
|
||||
|
||||
private->request.list_free = mmal_list_create();
|
||||
private->request.list_pending = mmal_list_create();
|
||||
if (!private->request.list_free || !private->request.list_pending)
|
||||
{
|
||||
LOG_ERROR("failed to create list %p %p", private->request.list_free, private->request.list_pending);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Populate the list of available request slots */
|
||||
for (i = 0; i < CLOCK_REQUEST_SLOTS; ++i)
|
||||
mmal_list_push_back(private->request.list_free, &private->request.pool[i].link);
|
||||
|
||||
if (vcos_thread_create(&private->thread, "mmal-clock thread", NULL,
|
||||
mmal_clock_worker_thread, private) != VCOS_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("failed to create worker thread");
|
||||
goto error;
|
||||
}
|
||||
priority = vcos_thread_get_priority(&private->thread);
|
||||
vcos_thread_set_priority(&private->thread, 1 | (priority & VCOS_AFFINITY_MASK));
|
||||
|
||||
private->scheduling = MMAL_TRUE;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
if (event_status == VCOS_SUCCESS) vcos_semaphore_delete(&private->event);
|
||||
if (timer_status) mmal_clock_timer_destroy(&private->timer);
|
||||
if (private->request.list_free) mmal_list_destroy(private->request.list_free);
|
||||
if (private->request.list_pending) mmal_list_destroy(private->request.list_pending);
|
||||
return MMAL_ENOSPC;
|
||||
}
|
||||
|
||||
/* Destroy all scheduling resources */
|
||||
static void mmal_clock_destroy_scheduling(MMAL_CLOCK_PRIVATE_T *private)
|
||||
{
|
||||
mmal_clock_stop_thread(private);
|
||||
|
||||
mmal_clock_request_flush(&private->clock);
|
||||
|
||||
mmal_list_destroy(private->request.list_free);
|
||||
mmal_list_destroy(private->request.list_pending);
|
||||
|
||||
vcos_semaphore_delete(&private->event);
|
||||
|
||||
mmal_clock_timer_destroy(&private->timer);
|
||||
}
|
||||
|
||||
/* Start the media-time */
|
||||
static void mmal_clock_start(MMAL_CLOCK_T *clock)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
|
||||
private->is_active = MMAL_TRUE;
|
||||
|
||||
mmal_clock_wake_thread(private);
|
||||
}
|
||||
|
||||
/* Stop the media-time */
|
||||
static void mmal_clock_stop(MMAL_CLOCK_T *clock)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
|
||||
private->is_active = MMAL_FALSE;
|
||||
|
||||
mmal_clock_wake_thread(private);
|
||||
}
|
||||
|
||||
static int mmal_clock_is_paused(MMAL_CLOCK_T *clock)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
return private->scale == 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Clock module public functions
|
||||
*****************************************************************************/
|
||||
/* Create new clock instance */
|
||||
MMAL_STATUS_T mmal_clock_create(MMAL_CLOCK_T **clock)
|
||||
{
|
||||
unsigned int size = sizeof(MMAL_CLOCK_PRIVATE_T);
|
||||
MMAL_RATIONAL_T scale = { 1, 1 };
|
||||
MMAL_CLOCK_PRIVATE_T *private;
|
||||
|
||||
/* Sanity checking */
|
||||
if (clock == NULL)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
private = vcos_calloc(1, size, "mmal-clock");
|
||||
if (!private)
|
||||
{
|
||||
LOG_ERROR("failed to allocate memory");
|
||||
return MMAL_ENOMEM;
|
||||
}
|
||||
|
||||
if (vcos_mutex_create(&private->lock, "mmal-clock lock") != VCOS_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("failed to create lock mutex");
|
||||
vcos_free(private);
|
||||
return MMAL_ENOSPC;
|
||||
}
|
||||
|
||||
/* Set the default threshold values */
|
||||
private->update_threshold_lower = CLOCK_UPDATE_THRESHOLD_LOWER;
|
||||
private->update_threshold_upper = CLOCK_UPDATE_THRESHOLD_UPPER;
|
||||
private->discont_threshold = CLOCK_DISCONT_THRESHOLD;
|
||||
private->discont_duration = CLOCK_DISCONT_DURATION;
|
||||
private->request_threshold = 0;
|
||||
private->request_threshold_enable = MMAL_FALSE;
|
||||
|
||||
/* Default scale = 1.0, i.e. normal playback speed */
|
||||
mmal_clock_scale_set(&private->clock, scale);
|
||||
|
||||
*clock = &private->clock;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Destroy a clock instance */
|
||||
MMAL_STATUS_T mmal_clock_destroy(MMAL_CLOCK_T *clock)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
|
||||
if (private->scheduling)
|
||||
mmal_clock_destroy_scheduling(private);
|
||||
|
||||
vcos_mutex_delete(&private->lock);
|
||||
|
||||
vcos_free(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Add new client request to list of pending requests */
|
||||
MMAL_STATUS_T mmal_clock_request_add(MMAL_CLOCK_T *clock, int64_t media_time,
|
||||
MMAL_CLOCK_REQUEST_CB cb, void *cb_data, MMAL_CLOCK_VOID_FP priv)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
MMAL_CLOCK_REQUEST_T *request;
|
||||
MMAL_BOOL_T wake_thread = MMAL_FALSE;
|
||||
int64_t media_time_now;
|
||||
|
||||
LOG_TRACE("media time %"PRIi64, media_time);
|
||||
|
||||
LOCK(private);
|
||||
|
||||
media_time_now = mmal_clock_media_time_get_locked(private);
|
||||
|
||||
/* Drop the request if request_threshold_enable and the frame exceeds the request threshold */
|
||||
if (private->request_threshold_enable && (media_time > (media_time_now + private->request_threshold)))
|
||||
{
|
||||
LOG_TRACE("dropping request: media time %"PRIi64" now %"PRIi64, media_time, media_time_now);
|
||||
UNLOCK(private);
|
||||
return MMAL_ECORRUPT;
|
||||
}
|
||||
|
||||
/* The clock module is usually only used for time-keeping, so all the
|
||||
* objects needed to process client requests are not allocated by default
|
||||
* and need to be created on the first client request received */
|
||||
if (!private->scheduling)
|
||||
{
|
||||
if (mmal_clock_create_scheduling(private) != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("failed to create scheduling objects");
|
||||
UNLOCK(private);
|
||||
return MMAL_ENOSPC;
|
||||
}
|
||||
}
|
||||
|
||||
request = (MMAL_CLOCK_REQUEST_T*)mmal_list_pop_front(private->request.list_free);
|
||||
if (request == NULL)
|
||||
{
|
||||
LOG_ERROR("no more free clock request slots");
|
||||
UNLOCK(private);
|
||||
return MMAL_ENOSPC;
|
||||
}
|
||||
|
||||
request->cb = cb;
|
||||
request->cb_data = cb_data;
|
||||
request->priv = priv;
|
||||
request->media_time = media_time;
|
||||
request->media_time_adj = media_time - (int64_t)(private->scale * CLOCK_TARGET_OFFSET >> 16);
|
||||
|
||||
if (mmal_clock_request_insert(private, request))
|
||||
wake_thread = private->is_active;
|
||||
|
||||
UNLOCK(private);
|
||||
|
||||
/* Notify the worker thread */
|
||||
if (wake_thread)
|
||||
mmal_clock_wake_thread(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Flush all pending requests */
|
||||
MMAL_STATUS_T mmal_clock_request_flush(MMAL_CLOCK_T *clock)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
|
||||
LOCK(private);
|
||||
if (private->scheduling)
|
||||
mmal_clock_request_flush_locked(private, MMAL_TIME_UNKNOWN);
|
||||
UNLOCK(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Update the local media-time with the given reference */
|
||||
MMAL_STATUS_T mmal_clock_media_time_set(MMAL_CLOCK_T *clock, int64_t media_time)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
MMAL_BOOL_T wake_thread = MMAL_TRUE;
|
||||
int64_t time_diff;
|
||||
|
||||
LOCK(private);
|
||||
|
||||
if (!private->is_active)
|
||||
{
|
||||
uint32_t time_now = vcos_getmicrosecs();
|
||||
private->wall_time = time_now;
|
||||
private->media_time = media_time;
|
||||
private->media_time_frac = 0;
|
||||
private->rtc_at_update = time_now;
|
||||
|
||||
UNLOCK(private);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (mmal_clock_is_paused(clock))
|
||||
{
|
||||
LOG_TRACE("clock is paused; ignoring update");
|
||||
UNLOCK(private);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Reset the local media-time with the given time reference */
|
||||
mmal_clock_update_local_time_locked(private);
|
||||
|
||||
time_diff = private->media_time - media_time;
|
||||
if (time_diff > private->update_threshold_upper ||
|
||||
time_diff < -private->update_threshold_upper)
|
||||
{
|
||||
LOG_TRACE("cur:%"PRIi64" new:%"PRIi64" diff:%"PRIi64, private->media_time, media_time, time_diff);
|
||||
private->media_time = media_time;
|
||||
private->average_ref_diff = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
private->average_ref_diff = ((private->average_ref_diff << 6) - private->average_ref_diff + time_diff) >> 6;
|
||||
if(private->average_ref_diff > private->update_threshold_lower ||
|
||||
private->average_ref_diff < -private->update_threshold_lower)
|
||||
{
|
||||
LOG_TRACE("cur:%"PRIi64" new:%"PRIi64" ave:%"PRIi64, private->media_time,
|
||||
private->media_time - private->average_ref_diff, private->average_ref_diff);
|
||||
private->media_time -= private->average_ref_diff;
|
||||
private->average_ref_diff = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't update the media-time */
|
||||
wake_thread = MMAL_FALSE;
|
||||
LOG_TRACE("cur:%"PRIi64" new:%"PRIi64" diff:%"PRIi64" ave:%"PRIi64" ignored", private->media_time,
|
||||
media_time, private->media_time - media_time, private->average_ref_diff);
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK(private);
|
||||
|
||||
if (wake_thread)
|
||||
mmal_clock_wake_thread(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Change the clock scale */
|
||||
MMAL_STATUS_T mmal_clock_scale_set(MMAL_CLOCK_T *clock, MMAL_RATIONAL_T scale)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
|
||||
LOG_TRACE("new scale %d/%d", scale.num, scale.den);
|
||||
|
||||
LOCK(private);
|
||||
|
||||
mmal_clock_update_local_time_locked(private);
|
||||
|
||||
private->scale_rational = scale;
|
||||
private->scale = mmal_rational_to_fixed_16_16(scale);
|
||||
|
||||
if (private->scale)
|
||||
private->scale_inv = (int32_t)((1LL << 32) / (int64_t)private->scale);
|
||||
else
|
||||
private->scale_inv = Q16_ONE; /* clock is paused */
|
||||
|
||||
UNLOCK(private);
|
||||
|
||||
mmal_clock_wake_thread(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Set the clock state */
|
||||
MMAL_STATUS_T mmal_clock_active_set(MMAL_CLOCK_T *clock, MMAL_BOOL_T active)
|
||||
{
|
||||
if (active)
|
||||
mmal_clock_start(clock);
|
||||
else
|
||||
mmal_clock_stop(clock);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get the clock's scale */
|
||||
MMAL_RATIONAL_T mmal_clock_scale_get(MMAL_CLOCK_T *clock)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
MMAL_RATIONAL_T scale;
|
||||
|
||||
LOCK(private);
|
||||
scale = private->scale_rational;
|
||||
UNLOCK(private);
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
/* Return the current local media-time */
|
||||
int64_t mmal_clock_media_time_get(MMAL_CLOCK_T *clock)
|
||||
{
|
||||
int64_t media_time;
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T*)clock;
|
||||
|
||||
LOCK(private);
|
||||
media_time = mmal_clock_media_time_get_locked(private);
|
||||
UNLOCK(private);
|
||||
|
||||
return media_time;
|
||||
}
|
||||
|
||||
/* Get the clock's state */
|
||||
MMAL_BOOL_T mmal_clock_is_active(MMAL_CLOCK_T *clock)
|
||||
{
|
||||
return ((MMAL_CLOCK_PRIVATE_T*)clock)->is_active;
|
||||
}
|
||||
|
||||
/* Get the clock's media-time update threshold values */
|
||||
MMAL_STATUS_T mmal_clock_update_threshold_get(MMAL_CLOCK_T *clock, MMAL_CLOCK_UPDATE_THRESHOLD_T *update_threshold)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T *)clock;
|
||||
|
||||
LOCK(private);
|
||||
update_threshold->threshold_lower = private->update_threshold_lower;
|
||||
update_threshold->threshold_upper = private->update_threshold_upper;
|
||||
UNLOCK(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Set the clock's media-time update threshold values */
|
||||
MMAL_STATUS_T mmal_clock_update_threshold_set(MMAL_CLOCK_T *clock, const MMAL_CLOCK_UPDATE_THRESHOLD_T *update_threshold)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T *)clock;
|
||||
|
||||
LOG_TRACE("new clock update thresholds: upper %"PRIi64", lower %"PRIi64,
|
||||
update_threshold->threshold_lower, update_threshold->threshold_upper);
|
||||
|
||||
LOCK(private);
|
||||
private->update_threshold_lower = update_threshold->threshold_lower;
|
||||
private->update_threshold_upper = update_threshold->threshold_upper;
|
||||
UNLOCK(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get the clock's discontinuity threshold values */
|
||||
MMAL_STATUS_T mmal_clock_discont_threshold_get(MMAL_CLOCK_T *clock, MMAL_CLOCK_DISCONT_THRESHOLD_T *discont)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T *)clock;
|
||||
|
||||
LOCK(private);
|
||||
discont->threshold = private->discont_threshold;
|
||||
discont->duration = private->discont_duration;
|
||||
UNLOCK(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Set the clock's discontinuity threshold values */
|
||||
MMAL_STATUS_T mmal_clock_discont_threshold_set(MMAL_CLOCK_T *clock, const MMAL_CLOCK_DISCONT_THRESHOLD_T *discont)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T *)clock;
|
||||
|
||||
LOG_TRACE("new clock discontinuity values: threshold %"PRIi64", duration %"PRIi64,
|
||||
discont->threshold, discont->duration);
|
||||
|
||||
LOCK(private);
|
||||
private->discont_threshold = discont->threshold;
|
||||
private->discont_duration = discont->duration;
|
||||
UNLOCK(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get the clock's request threshold values */
|
||||
MMAL_STATUS_T mmal_clock_request_threshold_get(MMAL_CLOCK_T *clock, MMAL_CLOCK_REQUEST_THRESHOLD_T *req)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T *)clock;
|
||||
|
||||
LOCK(private);
|
||||
req->threshold = private->request_threshold;
|
||||
req->threshold_enable = private->request_threshold_enable;
|
||||
UNLOCK(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Set the clock's request threshold values */
|
||||
MMAL_STATUS_T mmal_clock_request_threshold_set(MMAL_CLOCK_T *clock, const MMAL_CLOCK_REQUEST_THRESHOLD_T *req)
|
||||
{
|
||||
MMAL_CLOCK_PRIVATE_T *private = (MMAL_CLOCK_PRIVATE_T *)clock;
|
||||
|
||||
LOG_TRACE("new clock request values: threshold %"PRIi64,
|
||||
req->threshold);
|
||||
|
||||
LOCK(private);
|
||||
private->request_threshold = req->threshold;
|
||||
private->request_threshold_enable = req->threshold_enable;
|
||||
UNLOCK(private);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_CLOCK_PRIVATE_H
|
||||
#define MMAL_CLOCK_PRIVATE_H
|
||||
|
||||
#include "interface/mmal/mmal.h"
|
||||
#include "interface/mmal/mmal_clock.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** Handle to a clock. */
|
||||
typedef struct MMAL_CLOCK_T
|
||||
{
|
||||
void *user_data; /**< Client-supplied data (not used by the clock). */
|
||||
} MMAL_CLOCK_T;
|
||||
|
||||
/** Create a new instance of a clock.
|
||||
*
|
||||
* @param clock Returned clock
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_create(MMAL_CLOCK_T **clock);
|
||||
|
||||
/** Destroy a previously created clock.
|
||||
*
|
||||
* @param clock The clock to destroy
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_destroy(MMAL_CLOCK_T *clock);
|
||||
|
||||
/** Definition of a clock request callback.
|
||||
* This is invoked when the media-time requested by the client is reached.
|
||||
*
|
||||
* @param clock The clock which serviced the request
|
||||
* @param media_time The current media-time
|
||||
* @param cb_data Client-supplied data
|
||||
* @param priv Function pointer used by the framework
|
||||
*/
|
||||
typedef void (*MMAL_CLOCK_VOID_FP)(void);
|
||||
typedef void (*MMAL_CLOCK_REQUEST_CB)(MMAL_CLOCK_T *clock, int64_t media_time, void *cb_data, MMAL_CLOCK_VOID_FP priv);
|
||||
|
||||
/** Register a request with the clock.
|
||||
* When the specified media-time is reached, the clock will invoke the supplied callback.
|
||||
*
|
||||
* @param clock The clock
|
||||
* @param media_time The media-time at which the callback should be invoked (microseconds)
|
||||
* @param cb Callback to invoke
|
||||
* @param cb_data Client-supplied callback data
|
||||
* @param priv Function pointer used by the framework
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_request_add(MMAL_CLOCK_T *clock, int64_t media_time,
|
||||
MMAL_CLOCK_REQUEST_CB cb, void *cb_data, MMAL_CLOCK_VOID_FP priv);
|
||||
|
||||
/** Remove all previously registered clock requests.
|
||||
*
|
||||
* @param clock The clock
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_request_flush(MMAL_CLOCK_T *clock);
|
||||
|
||||
/** Update the clock's media-time.
|
||||
*
|
||||
* @param clock The clock to update
|
||||
* @param media_time New media-time to be applied (microseconds)
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_media_time_set(MMAL_CLOCK_T *clock, int64_t media_time);
|
||||
|
||||
/** Set the clock's scale.
|
||||
*
|
||||
* @param clock The clock
|
||||
* @param scale Scale factor
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_scale_set(MMAL_CLOCK_T *clock, MMAL_RATIONAL_T scale);
|
||||
|
||||
/** Set the clock state.
|
||||
*
|
||||
* @param clock The clock
|
||||
* @param active TRUE -> clock is active and media-time is advancing
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_active_set(MMAL_CLOCK_T *clock, MMAL_BOOL_T active);
|
||||
|
||||
/** Get the clock's scale.
|
||||
*
|
||||
* @param clock The clock
|
||||
*
|
||||
* @return Current clock scale
|
||||
*/
|
||||
MMAL_RATIONAL_T mmal_clock_scale_get(MMAL_CLOCK_T *clock);
|
||||
|
||||
/** Get the clock's current media-time.
|
||||
* This takes the clock scale and media-time offset into account.
|
||||
*
|
||||
* @param clock The clock to query
|
||||
*
|
||||
* @return Current media-time in microseconds
|
||||
*/
|
||||
int64_t mmal_clock_media_time_get(MMAL_CLOCK_T *clock);
|
||||
|
||||
/** Get the clock's state.
|
||||
*
|
||||
* @param clock The clock to query
|
||||
*
|
||||
* @return TRUE if clock is running (i.e. local media-time is advancing)
|
||||
*/
|
||||
MMAL_BOOL_T mmal_clock_is_active(MMAL_CLOCK_T *clock);
|
||||
|
||||
/** Get the clock's media-time update threshold values.
|
||||
*
|
||||
* @param clock The clock
|
||||
* @param update_threshold Pointer to clock update threshold values to fill
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_update_threshold_get(MMAL_CLOCK_T *clock, MMAL_CLOCK_UPDATE_THRESHOLD_T *update_threshold);
|
||||
|
||||
/** Set the clock's media-time update threshold values.
|
||||
*
|
||||
* @param clock The clock
|
||||
* @param update_threshold Pointer to new clock update threshold values
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_update_threshold_set(MMAL_CLOCK_T *clock, const MMAL_CLOCK_UPDATE_THRESHOLD_T *update_threshold);
|
||||
|
||||
/** Get the clock's discontinuity threshold values.
|
||||
*
|
||||
* @param clock The clock
|
||||
* @param discont Pointer to clock discontinuity threshold values to fill
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_discont_threshold_get(MMAL_CLOCK_T *clock, MMAL_CLOCK_DISCONT_THRESHOLD_T *discont);
|
||||
|
||||
/** Set the clock's discontinuity threshold values.
|
||||
*
|
||||
* @param clock The clock
|
||||
* @param discont Pointer to new clock discontinuity threshold values
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_discont_threshold_set(MMAL_CLOCK_T *clock, const MMAL_CLOCK_DISCONT_THRESHOLD_T *discont);
|
||||
|
||||
/** Get the clock's request threshold values.
|
||||
*
|
||||
* @param clock The clock
|
||||
* @param future Pointer to clock request threshold values to fill
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_request_threshold_get(MMAL_CLOCK_T *clock, MMAL_CLOCK_REQUEST_THRESHOLD_T *req);
|
||||
|
||||
/** Set the clock's request threshold values.
|
||||
*
|
||||
* @param clock The clock
|
||||
* @param discont Pointer to new clock request threshold values
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_clock_request_threshold_set(MMAL_CLOCK_T *clock, const MMAL_CLOCK_REQUEST_THRESHOLD_T *req);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_CLOCK_PRIVATE_H */
|
@ -1,780 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "core/mmal_component_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "core/mmal_core_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
/* Minimum number of buffers that will be available on the control port */
|
||||
#define MMAL_CONTROL_PORT_BUFFERS_MIN 4
|
||||
|
||||
/** Definition of the core private context. */
|
||||
typedef struct
|
||||
{
|
||||
MMAL_COMPONENT_PRIVATE_T private;
|
||||
|
||||
/** Action registered by component and run when buffers are received by any of the ports */
|
||||
void (*pf_action)(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Action thread */
|
||||
VCOS_THREAD_T action_thread;
|
||||
VCOS_EVENT_T action_event;
|
||||
VCOS_MUTEX_T action_mutex;
|
||||
MMAL_BOOL_T action_quit;
|
||||
|
||||
VCOS_MUTEX_T lock; /**< Used to lock access to the component */
|
||||
MMAL_BOOL_T destruction_pending;
|
||||
|
||||
} MMAL_COMPONENT_CORE_PRIVATE_T;
|
||||
|
||||
/*****************************************************************************/
|
||||
static void mmal_core_init(void);
|
||||
static void mmal_core_deinit(void);
|
||||
|
||||
static MMAL_STATUS_T mmal_component_supplier_create(const char *name, MMAL_COMPONENT_T *component);
|
||||
static void mmal_component_init_control_port(MMAL_PORT_T *port);
|
||||
|
||||
static MMAL_STATUS_T mmal_component_destroy_internal(MMAL_COMPONENT_T *component);
|
||||
static MMAL_STATUS_T mmal_component_release_internal(MMAL_COMPONENT_T *component);
|
||||
|
||||
/*****************************************************************************/
|
||||
static VCOS_MUTEX_T mmal_core_lock;
|
||||
/** Used to generate a unique id for each MMAL component in this context. */
|
||||
static unsigned int mmal_core_instance_count;
|
||||
static unsigned int mmal_core_refcount;
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_create_core(const char *name,
|
||||
MMAL_STATUS_T (*constructor)(const char *name, MMAL_COMPONENT_T *),
|
||||
struct MMAL_COMPONENT_MODULE_T *constructor_private,
|
||||
MMAL_COMPONENT_T **component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private;
|
||||
MMAL_STATUS_T status = MMAL_ENOMEM;
|
||||
unsigned int size = sizeof(MMAL_COMPONENT_T) + sizeof(MMAL_COMPONENT_CORE_PRIVATE_T);
|
||||
unsigned int i, name_length = strlen(name) + 1;
|
||||
unsigned int port_index;
|
||||
char *component_name;
|
||||
|
||||
if(!component)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
mmal_core_init();
|
||||
|
||||
*component = vcos_calloc(1, size + name_length, "mmal component");
|
||||
if(!*component)
|
||||
return MMAL_ENOMEM;
|
||||
|
||||
private = (MMAL_COMPONENT_CORE_PRIVATE_T *)&(*component)[1];
|
||||
(*component)->priv = (MMAL_COMPONENT_PRIVATE_T *)private;
|
||||
(*component)->name = component_name= (char *)&((MMAL_COMPONENT_CORE_PRIVATE_T *)(*component)->priv)[1];
|
||||
memcpy(component_name, name, name_length);
|
||||
/* coverity[missing_lock] Component and mutex have just been created. No need to lock yet */
|
||||
(*component)->priv->refcount = 1;
|
||||
(*component)->priv->priority = VCOS_THREAD_PRI_NORMAL;
|
||||
|
||||
if(vcos_mutex_create(&private->lock, "mmal component lock") != VCOS_SUCCESS)
|
||||
{
|
||||
vcos_free(*component);
|
||||
return MMAL_ENOMEM;
|
||||
}
|
||||
|
||||
vcos_mutex_lock(&mmal_core_lock);
|
||||
(*component)->id=mmal_core_instance_count++;
|
||||
vcos_mutex_unlock(&mmal_core_lock);
|
||||
|
||||
/* Create the control port */
|
||||
(*component)->control = mmal_port_alloc(*component, MMAL_PORT_TYPE_CONTROL, 0);
|
||||
if(!(*component)->control)
|
||||
goto error;
|
||||
mmal_component_init_control_port((*component)->control);
|
||||
|
||||
/* Create the actual component */
|
||||
(*component)->priv->module = constructor_private;
|
||||
if (!constructor)
|
||||
constructor = mmal_component_supplier_create;
|
||||
status = constructor(name, *component);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
if (status == MMAL_ENOSYS)
|
||||
LOG_ERROR("could not find component '%s'", name);
|
||||
else
|
||||
LOG_ERROR("could not create component '%s' (%i)", name, status);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Make sure we have enough space for at least a MMAL_EVENT_FORMAT_CHANGED */
|
||||
if ((*component)->control->buffer_size_min <
|
||||
sizeof(MMAL_ES_FORMAT_T) + sizeof(MMAL_ES_SPECIFIC_FORMAT_T) + sizeof(MMAL_EVENT_FORMAT_CHANGED_T))
|
||||
(*component)->control->buffer_size_min = sizeof(MMAL_ES_FORMAT_T) +
|
||||
sizeof(MMAL_ES_SPECIFIC_FORMAT_T) + sizeof(MMAL_EVENT_FORMAT_CHANGED_T);
|
||||
/* Make sure we have enough events */
|
||||
if ((*component)->control->buffer_num_min < MMAL_CONTROL_PORT_BUFFERS_MIN)
|
||||
(*component)->control->buffer_num_min = MMAL_CONTROL_PORT_BUFFERS_MIN;
|
||||
|
||||
/* Create the event pool */
|
||||
(*component)->priv->event_pool = mmal_pool_create((*component)->control->buffer_num_min,
|
||||
(*component)->control->buffer_size_min);
|
||||
if (!(*component)->priv->event_pool)
|
||||
{
|
||||
status = MMAL_ENOMEM;
|
||||
LOG_ERROR("could not create event pool (%d, %d)", (*component)->control->buffer_num_min,
|
||||
(*component)->control->buffer_size_min);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Build the list of all the ports */
|
||||
(*component)->port_num = (*component)->input_num + (*component)->output_num + (*component)->clock_num + 1;
|
||||
(*component)->port = vcos_malloc((*component)->port_num * sizeof(MMAL_PORT_T *), "mmal ports");
|
||||
if (!(*component)->port)
|
||||
{
|
||||
status = MMAL_ENOMEM;
|
||||
LOG_ERROR("could not create list of ports");
|
||||
goto error;
|
||||
}
|
||||
port_index = 0;
|
||||
(*component)->port[port_index++] = (*component)->control;
|
||||
for (i = 0; i < (*component)->input_num; i++)
|
||||
(*component)->port[port_index++] = (*component)->input[i];
|
||||
for (i = 0; i < (*component)->output_num; i++)
|
||||
(*component)->port[port_index++] = (*component)->output[i];
|
||||
for (i = 0; i < (*component)->clock_num; i++)
|
||||
(*component)->port[port_index++] = (*component)->clock[i];
|
||||
for (i = 0; i < (*component)->port_num; i++)
|
||||
(*component)->port[i]->index_all = i;
|
||||
|
||||
LOG_INFO("created '%s' %d %p", name, (*component)->id, *component);
|
||||
|
||||
/* Make sure the port types, indexes and buffer sizes are set correctly */
|
||||
(*component)->control->type = MMAL_PORT_TYPE_CONTROL;
|
||||
(*component)->control->index = 0;
|
||||
for (i = 0; i < (*component)->input_num; i++)
|
||||
{
|
||||
MMAL_PORT_T *port = (*component)->input[i];
|
||||
port->type = MMAL_PORT_TYPE_INPUT;
|
||||
port->index = i;
|
||||
}
|
||||
for (i = 0; i < (*component)->output_num; i++)
|
||||
{
|
||||
MMAL_PORT_T *port = (*component)->output[i];
|
||||
port->type = MMAL_PORT_TYPE_OUTPUT;
|
||||
port->index = i;
|
||||
}
|
||||
for (i = 0; i < (*component)->clock_num; i++)
|
||||
{
|
||||
MMAL_PORT_T *port = (*component)->clock[i];
|
||||
port->type = MMAL_PORT_TYPE_CLOCK;
|
||||
port->index = i;
|
||||
}
|
||||
for (i = 0; i < (*component)->port_num; i++)
|
||||
{
|
||||
MMAL_PORT_T *port = (*component)->port[i];
|
||||
if (port->buffer_size < port->buffer_size_min)
|
||||
port->buffer_size = port->buffer_size_min;
|
||||
if (port->buffer_num < port->buffer_num_min)
|
||||
port->buffer_num = port->buffer_num_min;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
error:
|
||||
mmal_component_destroy_internal(*component);
|
||||
*component = 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
MMAL_STATUS_T mmal_component_create(const char *name,
|
||||
MMAL_COMPONENT_T **component)
|
||||
{
|
||||
LOG_TRACE("%s", name);
|
||||
return mmal_component_create_core(name, 0, 0, component);
|
||||
}
|
||||
|
||||
/** Create an instance of a component */
|
||||
MMAL_STATUS_T mmal_component_create_with_constructor(const char *name,
|
||||
MMAL_STATUS_T (*constructor)(const char *name, MMAL_COMPONENT_T *),
|
||||
struct MMAL_COMPONENT_MODULE_T *constructor_private,
|
||||
MMAL_COMPONENT_T **component)
|
||||
{
|
||||
LOG_TRACE("%s", name);
|
||||
return mmal_component_create_core(name, constructor, constructor_private, component);
|
||||
}
|
||||
|
||||
/** Destroy a previously created component */
|
||||
static MMAL_STATUS_T mmal_component_destroy_internal(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
LOG_TRACE("%s %d", component->name, component->id);
|
||||
|
||||
mmal_component_action_deregister(component);
|
||||
|
||||
/* Should pf_destroy be allowed to fail ?
|
||||
* If so, what do we do if it fails ?
|
||||
*/
|
||||
if (component->priv->pf_destroy)
|
||||
{
|
||||
status = component->priv->pf_destroy(component);
|
||||
if(!vcos_verify(status == MMAL_SUCCESS))
|
||||
return status;
|
||||
}
|
||||
|
||||
if (component->priv->event_pool)
|
||||
mmal_pool_destroy(component->priv->event_pool);
|
||||
|
||||
if (component->control)
|
||||
mmal_port_free(component->control);
|
||||
|
||||
if (component->port)
|
||||
vcos_free(component->port);
|
||||
|
||||
vcos_mutex_delete(&private->lock);
|
||||
vcos_free(component);
|
||||
mmal_core_deinit();
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Release a reference to a component */
|
||||
static MMAL_STATUS_T mmal_component_release_internal(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
unsigned int i;
|
||||
|
||||
if (!vcos_verify(component->priv->refcount > 0))
|
||||
return MMAL_EINVAL;
|
||||
|
||||
vcos_mutex_lock(&private->lock);
|
||||
if (--component->priv->refcount)
|
||||
{
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
private->destruction_pending = 1;
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
|
||||
LOG_TRACE("%s %d preparing for destruction", component->name, component->id);
|
||||
|
||||
/* Make sure the ports are all disabled */
|
||||
for(i = 0; i < component->input_num; i++)
|
||||
if(component->input[i]->is_enabled)
|
||||
mmal_port_disable(component->input[i]);
|
||||
for(i = 0; i < component->output_num; i++)
|
||||
if(component->output[i]->is_enabled)
|
||||
mmal_port_disable(component->output[i]);
|
||||
for(i = 0; i < component->clock_num; i++)
|
||||
if(component->clock[i]->is_enabled)
|
||||
mmal_port_disable(component->clock[i]);
|
||||
if(component->control->is_enabled)
|
||||
mmal_port_disable(component->control);
|
||||
|
||||
/* Make sure all the ports are disconnected. This is necessary to prevent
|
||||
* connected ports from referencing destroyed components */
|
||||
for(i = 0; i < component->input_num; i++)
|
||||
mmal_port_disconnect(component->input[i]);
|
||||
for(i = 0; i < component->output_num; i++)
|
||||
mmal_port_disconnect(component->output[i]);
|
||||
for(i = 0; i < component->clock_num; i++)
|
||||
mmal_port_disconnect(component->clock[i]);
|
||||
|
||||
/* If there is any reference pending on the ports we will delay the actual destruction */
|
||||
vcos_mutex_lock(&private->lock);
|
||||
if (component->priv->refcount_ports)
|
||||
{
|
||||
private->destruction_pending = 0;
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
LOG_TRACE("%s %d delaying destruction", component->name, component->id);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
|
||||
return mmal_component_destroy_internal(component);
|
||||
}
|
||||
|
||||
/** Destroy a component */
|
||||
MMAL_STATUS_T mmal_component_destroy(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
if(!component)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
LOG_TRACE("%s %d", component->name, component->id);
|
||||
|
||||
return mmal_component_release_internal(component);
|
||||
}
|
||||
|
||||
/** Acquire a reference to a component */
|
||||
void mmal_component_acquire(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
|
||||
LOG_TRACE("component %s(%d), refcount %i", component->name, component->id,
|
||||
component->priv->refcount);
|
||||
|
||||
vcos_mutex_lock(&private->lock);
|
||||
component->priv->refcount++;
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
}
|
||||
|
||||
/** Release a reference to a component */
|
||||
MMAL_STATUS_T mmal_component_release(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
if(!component)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
LOG_TRACE("component %s(%d), refcount %i", component->name, component->id,
|
||||
component->priv->refcount);
|
||||
|
||||
return mmal_component_release_internal(component);
|
||||
}
|
||||
|
||||
/** Enable processing on a component */
|
||||
MMAL_STATUS_T mmal_component_enable(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private;
|
||||
MMAL_STATUS_T status = MMAL_ENOSYS;
|
||||
unsigned int i;
|
||||
|
||||
if(!component)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
|
||||
LOG_TRACE("%s %d", component->name, component->id);
|
||||
|
||||
vcos_mutex_lock(&private->lock);
|
||||
|
||||
/* Check we have anything to do */
|
||||
if (component->is_enabled)
|
||||
{
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (component->priv->pf_enable)
|
||||
status = component->priv->pf_enable(component);
|
||||
|
||||
/* If the component does not support enable/disable, we handle that
|
||||
* in the core itself */
|
||||
if (status == MMAL_ENOSYS)
|
||||
{
|
||||
status = MMAL_SUCCESS;
|
||||
|
||||
/* Resume all input / output ports */
|
||||
for (i = 0; status == MMAL_SUCCESS && i < component->input_num; i++)
|
||||
status = mmal_port_pause(component->input[i], MMAL_FALSE);
|
||||
for (i = 0; status == MMAL_SUCCESS && i < component->output_num; i++)
|
||||
status = mmal_port_pause(component->output[i], MMAL_FALSE);
|
||||
}
|
||||
|
||||
if (status == MMAL_SUCCESS)
|
||||
component->is_enabled = 1;
|
||||
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Disable processing on a component */
|
||||
MMAL_STATUS_T mmal_component_disable(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private;
|
||||
MMAL_STATUS_T status = MMAL_ENOSYS;
|
||||
unsigned int i;
|
||||
|
||||
if (!component)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
|
||||
LOG_TRACE("%s %d", component->name, component->id);
|
||||
|
||||
vcos_mutex_lock(&private->lock);
|
||||
|
||||
/* Check we have anything to do */
|
||||
if (!component->is_enabled)
|
||||
{
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (component->priv->pf_disable)
|
||||
status = component->priv->pf_disable(component);
|
||||
|
||||
/* If the component does not support enable/disable, we handle that
|
||||
* in the core itself */
|
||||
if (status == MMAL_ENOSYS)
|
||||
{
|
||||
status = MMAL_SUCCESS;
|
||||
|
||||
/* Pause all input / output ports */
|
||||
for (i = 0; status == MMAL_SUCCESS && i < component->input_num; i++)
|
||||
status = mmal_port_pause(component->input[i], MMAL_TRUE);
|
||||
for (i = 0; status == MMAL_SUCCESS && i < component->output_num; i++)
|
||||
status = mmal_port_pause(component->output[i], MMAL_TRUE);
|
||||
}
|
||||
|
||||
if (status == MMAL_SUCCESS)
|
||||
component->is_enabled = 0;
|
||||
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_component_enable_control_port(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
(void)port;
|
||||
(void)cb;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_component_disable_control_port(MMAL_PORT_T *port)
|
||||
{
|
||||
(void)port;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
MMAL_STATUS_T mmal_component_parameter_set(MMAL_PORT_T *control_port,
|
||||
const MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
(void)control_port;
|
||||
(void)param;
|
||||
/* No generic component control parameters */
|
||||
LOG_ERROR("parameter id 0x%08x not supported", param->id);
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
MMAL_STATUS_T mmal_component_parameter_get(MMAL_PORT_T *control_port,
|
||||
MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
(void)control_port;
|
||||
(void)param;
|
||||
/* No generic component control parameters */
|
||||
LOG_ERROR("parameter id 0x%08x not supported", param->id);
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
static void mmal_component_init_control_port(MMAL_PORT_T *port)
|
||||
{
|
||||
port->format->type = MMAL_ES_TYPE_CONTROL;
|
||||
port->buffer_num_min = MMAL_CONTROL_PORT_BUFFERS_MIN;
|
||||
port->buffer_num = port->buffer_num_min;
|
||||
port->buffer_size_min = sizeof(MMAL_ES_FORMAT_T) + sizeof(MMAL_ES_SPECIFIC_FORMAT_T);
|
||||
port->buffer_size = port->buffer_size_min;
|
||||
|
||||
/* Default to generic handling */
|
||||
port->priv->pf_enable = mmal_component_enable_control_port;
|
||||
port->priv->pf_disable = mmal_component_disable_control_port;
|
||||
port->priv->pf_parameter_set = mmal_component_parameter_set;
|
||||
port->priv->pf_parameter_get = mmal_component_parameter_get;
|
||||
/* No pf_set_format - format of control port cannot be changed */
|
||||
/* No pf_send - buffers cannot be sent to control port */
|
||||
}
|
||||
|
||||
/** Acquire a reference on a port */
|
||||
void mmal_port_acquire(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
|
||||
LOG_TRACE("port %s(%p), refcount %i", port->name, port,
|
||||
component->priv->refcount_ports);
|
||||
|
||||
vcos_mutex_lock(&private->lock);
|
||||
component->priv->refcount_ports++;
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
}
|
||||
|
||||
/** Release a reference on a port */
|
||||
MMAL_STATUS_T mmal_port_release(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = port->component;
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
|
||||
LOG_TRACE("port %s(%p), refcount %i", port->name, port,
|
||||
component->priv->refcount_ports);
|
||||
|
||||
/* Sanity check the refcount */
|
||||
if (!vcos_verify(component->priv->refcount_ports > 0))
|
||||
return MMAL_EINVAL;
|
||||
|
||||
vcos_mutex_lock(&private->lock);
|
||||
if (--component->priv->refcount_ports ||
|
||||
component->priv->refcount || private->destruction_pending)
|
||||
{
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
vcos_mutex_unlock(&private->lock);
|
||||
|
||||
return mmal_component_destroy_internal(component);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Actions support
|
||||
*****************************************************************************/
|
||||
|
||||
/** Registers an action with the core */
|
||||
static void *mmal_component_action_thread_func(void *arg)
|
||||
{
|
||||
MMAL_COMPONENT_T *component = (MMAL_COMPONENT_T *)arg;
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
VCOS_STATUS_T status;
|
||||
|
||||
while (1)
|
||||
{
|
||||
status = vcos_event_wait(&private->action_event);
|
||||
|
||||
if (status == VCOS_EAGAIN)
|
||||
continue;
|
||||
if (private->action_quit)
|
||||
break;
|
||||
if (!vcos_verify(status == VCOS_SUCCESS))
|
||||
break;
|
||||
|
||||
vcos_mutex_lock(&private->action_mutex);
|
||||
private->pf_action(component);
|
||||
vcos_mutex_unlock(&private->action_mutex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Registers an action with the core */
|
||||
MMAL_STATUS_T mmal_component_action_register(MMAL_COMPONENT_T *component,
|
||||
void (*pf_action)(MMAL_COMPONENT_T *) )
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
VCOS_THREAD_ATTR_T attrs;
|
||||
VCOS_STATUS_T status;
|
||||
|
||||
if (private->pf_action)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
status = vcos_event_create(&private->action_event, component->name);
|
||||
if (status != VCOS_SUCCESS)
|
||||
return MMAL_ENOMEM;
|
||||
|
||||
status = vcos_mutex_create(&private->action_mutex, component->name);
|
||||
if (status != VCOS_SUCCESS)
|
||||
{
|
||||
vcos_event_delete(&private->action_event);
|
||||
return MMAL_ENOMEM;
|
||||
}
|
||||
|
||||
vcos_thread_attr_init(&attrs);
|
||||
vcos_thread_attr_setpriority(&attrs,
|
||||
private->private.priority);
|
||||
status = vcos_thread_create(&private->action_thread, component->name, &attrs,
|
||||
mmal_component_action_thread_func, component);
|
||||
if (status != VCOS_SUCCESS)
|
||||
{
|
||||
vcos_mutex_delete(&private->action_mutex);
|
||||
vcos_event_delete(&private->action_event);
|
||||
return MMAL_ENOMEM;
|
||||
}
|
||||
|
||||
private->pf_action = pf_action;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** De-registers the current action with the core */
|
||||
MMAL_STATUS_T mmal_component_action_deregister(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
|
||||
if (!private->pf_action)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
private->action_quit = 1;
|
||||
vcos_event_signal(&private->action_event);
|
||||
vcos_thread_join(&private->action_thread, NULL);
|
||||
vcos_event_delete(&private->action_event);
|
||||
vcos_mutex_delete(&private->action_mutex);
|
||||
private->pf_action = NULL;
|
||||
private->action_quit = 0;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Triggers a registered action */
|
||||
MMAL_STATUS_T mmal_component_action_trigger(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
|
||||
if (!private->pf_action)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
vcos_event_signal(&private->action_event);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Lock an action to prevent it from running */
|
||||
MMAL_STATUS_T mmal_component_action_lock(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
|
||||
if (!private->pf_action)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
vcos_mutex_lock(&private->action_mutex);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Unlock an action to allow it to run again */
|
||||
MMAL_STATUS_T mmal_component_action_unlock(MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
|
||||
|
||||
if (!private->pf_action)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
vcos_mutex_unlock(&private->action_mutex);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Initialisation / Deinitialisation of the MMAL core
|
||||
*****************************************************************************/
|
||||
static void mmal_core_init_once(void)
|
||||
{
|
||||
vcos_mutex_create(&mmal_core_lock, VCOS_FUNCTION);
|
||||
}
|
||||
|
||||
static void mmal_core_init(void)
|
||||
{
|
||||
static VCOS_ONCE_T once = VCOS_ONCE_INIT;
|
||||
vcos_init();
|
||||
vcos_once(&once, mmal_core_init_once);
|
||||
|
||||
vcos_mutex_lock(&mmal_core_lock);
|
||||
if (mmal_core_refcount++)
|
||||
{
|
||||
vcos_mutex_unlock(&mmal_core_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
mmal_logging_init();
|
||||
vcos_mutex_unlock(&mmal_core_lock);
|
||||
}
|
||||
|
||||
static void mmal_core_deinit(void)
|
||||
{
|
||||
vcos_mutex_lock(&mmal_core_lock);
|
||||
if (!mmal_core_refcount || --mmal_core_refcount)
|
||||
{
|
||||
vcos_mutex_unlock(&mmal_core_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
mmal_logging_deinit();
|
||||
vcos_mutex_unlock(&mmal_core_lock);
|
||||
vcos_deinit();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Supplier support
|
||||
*****************************************************************************/
|
||||
|
||||
/** a component supplier gets passed a string and returns a
|
||||
* component (if it can) based on that string.
|
||||
*/
|
||||
|
||||
#define SUPPLIER_PREFIX_LEN 32
|
||||
typedef struct MMAL_COMPONENT_SUPPLIER_T
|
||||
{
|
||||
struct MMAL_COMPONENT_SUPPLIER_T *next;
|
||||
MMAL_COMPONENT_SUPPLIER_FUNCTION_T create;
|
||||
char prefix[SUPPLIER_PREFIX_LEN];
|
||||
} MMAL_COMPONENT_SUPPLIER_T;
|
||||
|
||||
/** List of component suppliers.
|
||||
*
|
||||
* Does not need to be thread-safe if we assume that suppliers
|
||||
* can never be removed.
|
||||
*/
|
||||
static MMAL_COMPONENT_SUPPLIER_T *suppliers;
|
||||
|
||||
/** Create an instance of a component */
|
||||
static MMAL_STATUS_T mmal_component_supplier_create(const char *name, MMAL_COMPONENT_T *component)
|
||||
{
|
||||
MMAL_COMPONENT_SUPPLIER_T *supplier = suppliers;
|
||||
MMAL_STATUS_T status = MMAL_ENOSYS;
|
||||
const char *dot = strchr(name, '.');
|
||||
size_t dot_size = dot ? dot - name : (int)strlen(name);
|
||||
|
||||
/* walk list of suppliers to see if any can create this component */
|
||||
while (supplier)
|
||||
{
|
||||
if (strlen(supplier->prefix) == dot_size && !memcmp(supplier->prefix, name, dot_size))
|
||||
{
|
||||
status = supplier->create(name, component);
|
||||
if (status == MMAL_SUCCESS)
|
||||
break;
|
||||
}
|
||||
supplier = supplier->next;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void mmal_component_supplier_register(const char *prefix,
|
||||
MMAL_COMPONENT_SUPPLIER_FUNCTION_T create_fn)
|
||||
{
|
||||
MMAL_COMPONENT_SUPPLIER_T *supplier = vcos_calloc(1,sizeof(*supplier),NULL);
|
||||
|
||||
LOG_TRACE("prefix %s fn %p", (prefix ? prefix : "NULL"), create_fn);
|
||||
|
||||
if (vcos_verify(supplier))
|
||||
{
|
||||
supplier->create = create_fn;
|
||||
strncpy(supplier->prefix, prefix, SUPPLIER_PREFIX_LEN);
|
||||
supplier->prefix[SUPPLIER_PREFIX_LEN-1] = '\0';
|
||||
|
||||
supplier->next = suppliers;
|
||||
suppliers = supplier;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("no memory for supplier registry entry");
|
||||
}
|
||||
}
|
||||
|
||||
MMAL_DESTRUCTOR(mmal_component_supplier_destructor);
|
||||
void mmal_component_supplier_destructor(void)
|
||||
{
|
||||
MMAL_COMPONENT_SUPPLIER_T *supplier = suppliers;
|
||||
|
||||
/* walk list of suppliers and free associated memory */
|
||||
while (supplier)
|
||||
{
|
||||
MMAL_COMPONENT_SUPPLIER_T *current = supplier;
|
||||
supplier = supplier->next;
|
||||
vcos_free(current);
|
||||
}
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_COMPONENT_PRIVATE_H
|
||||
#define MMAL_COMPONENT_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MMAL_VIDEO_DECODE "video_decode"
|
||||
#define MMAL_VIDEO_ENCODE "video_encode"
|
||||
#define MMAL_VIDEO_RENDER "video_render"
|
||||
#define MMAL_AUDIO_DECODE "audio_decode"
|
||||
#define MMAL_AUDIO_ENCODE "audio_encode"
|
||||
#define MMAL_AUDIO_RENDER "audio_render"
|
||||
#define MMAL_CAMERA "camera"
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
# define MMAL_CONSTRUCTOR(func) void __attribute__((constructor,used)) func(void)
|
||||
# define MMAL_DESTRUCTOR(func) void __attribute__((destructor,used)) func(void)
|
||||
#else
|
||||
# define MMAL_CONSTRUCTOR(func) void func(void)
|
||||
# define MMAL_DESTRUCTOR(func) void func(void)
|
||||
#endif
|
||||
|
||||
#include "mmal.h"
|
||||
#include "mmal_component.h"
|
||||
|
||||
/** Definition of a component. */
|
||||
struct MMAL_COMPONENT_PRIVATE_T
|
||||
{
|
||||
/** Pointer to the private data of the component module in use */
|
||||
struct MMAL_COMPONENT_MODULE_T *module;
|
||||
|
||||
MMAL_STATUS_T (*pf_enable)(MMAL_COMPONENT_T *component);
|
||||
MMAL_STATUS_T (*pf_disable)(MMAL_COMPONENT_T *component);
|
||||
MMAL_STATUS_T (*pf_destroy)(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Pool of event buffer headers, for sending events from component to client. */
|
||||
MMAL_POOL_T *event_pool;
|
||||
|
||||
/** Reference counting of the component */
|
||||
int refcount;
|
||||
/** Reference counting of the ports. Component won't be destroyed until this
|
||||
* goes to 0 */
|
||||
int refcount_ports;
|
||||
|
||||
/** Priority associated with the 'action thread' for this component, when
|
||||
* such action thread is applicable. */
|
||||
int priority;
|
||||
};
|
||||
|
||||
/** Set a generic component control parameter.
|
||||
*
|
||||
* @param control_port control port of component on which to set the parameter.
|
||||
* @param param parameter to be set.
|
||||
* @return MMAL_SUCCESS or another status on error.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_parameter_set(MMAL_PORT_T *control_port,
|
||||
const MMAL_PARAMETER_HEADER_T *param);
|
||||
|
||||
/** Get a generic component control parameter.
|
||||
*
|
||||
* @param contorl_port control port of component from which to get the parameter.
|
||||
* @param param parameter to be retrieved.
|
||||
* @return MMAL_SUCCESS or another status on error.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_parameter_get(MMAL_PORT_T *control_port,
|
||||
MMAL_PARAMETER_HEADER_T *param);
|
||||
|
||||
/** Registers an action with the core.
|
||||
* The MMAL core allows components to register an action which will be run
|
||||
* from a separate thread context when the action is explicitly triggered by
|
||||
* the component.
|
||||
*
|
||||
* @param component component registering the action.
|
||||
* @param action action to register.
|
||||
* @return MMAL_SUCCESS or another status on error.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_action_register(MMAL_COMPONENT_T *component,
|
||||
void (*pf_action)(MMAL_COMPONENT_T *));
|
||||
|
||||
/** De-registers the current action registered with the core.
|
||||
*
|
||||
* @param component component de-registering the action.
|
||||
* @return MMAL_SUCCESS or another status on error.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_action_deregister(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Triggers a registered action.
|
||||
* Explicitly triggers an action registered by a component.
|
||||
*
|
||||
* @param component component on which to trigger the action.
|
||||
* @return MMAL_SUCCESS or another status on error.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_action_trigger(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Lock an action to prevent it from running.
|
||||
* Allows a component to make sure no action is running while the lock is taken.
|
||||
*
|
||||
* @param component component.
|
||||
* @return MMAL_SUCCESS or another status on error.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_action_lock(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Unlock an action to allow it to run again.
|
||||
*
|
||||
* @param component component.
|
||||
* @return MMAL_SUCCESS or another status on error.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_action_unlock(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Prototype used by components to register themselves to the supplier. */
|
||||
typedef MMAL_STATUS_T (*MMAL_COMPONENT_SUPPLIER_FUNCTION_T)(const char *name,
|
||||
MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Create an instance of a component given a constructor for the component.
|
||||
* This allows the creation of client-side components which haven't been registered with the core.
|
||||
* See \ref mmal_component_create for the public interface used to create components.
|
||||
*
|
||||
* @param name name assigned to the component by the client
|
||||
* @param constructor constructor function for the component
|
||||
* @param constructor_private private data for the constructor
|
||||
* @param component returned component
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_create_with_constructor(const char *name,
|
||||
MMAL_STATUS_T (*constructor)(const char *name, MMAL_COMPONENT_T *),
|
||||
struct MMAL_COMPONENT_MODULE_T *constructor_private,
|
||||
MMAL_COMPONENT_T **component);
|
||||
|
||||
/** Register a component with the mmal component supplier.
|
||||
*
|
||||
* @param prefix prefix for this supplier, e.g. "VC"
|
||||
* @param create_fn function which will instantiate a component given a name.
|
||||
*/
|
||||
void mmal_component_supplier_register(const char *prefix,
|
||||
MMAL_COMPONENT_SUPPLIER_FUNCTION_T create_fn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_COMPONENT_PRIVATE_H */
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_CORE_PRIVATE_H
|
||||
#define MMAL_CORE_PRIVATE_H
|
||||
|
||||
/** Initialise the logging system.
|
||||
*/
|
||||
void mmal_logging_init(void);
|
||||
|
||||
/** Deinitialise the logging system.
|
||||
*/
|
||||
void mmal_logging_deinit(void);
|
||||
|
||||
#endif /* MMAL_CORE_PRIVATE_H */
|
||||
|
@ -1,138 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "mmal_port_private.h"
|
||||
#include "mmal_buffer.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *mmal_event_format_changed_get(MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event;
|
||||
MMAL_ES_FORMAT_T *format;
|
||||
uint32_t size;
|
||||
|
||||
size = sizeof(MMAL_EVENT_FORMAT_CHANGED_T);
|
||||
size += sizeof(MMAL_ES_FORMAT_T) + sizeof(MMAL_ES_SPECIFIC_FORMAT_T);
|
||||
|
||||
if (!buffer || buffer->cmd != MMAL_EVENT_FORMAT_CHANGED || buffer->length < size)
|
||||
return 0;
|
||||
|
||||
event = (MMAL_EVENT_FORMAT_CHANGED_T *)buffer->data;
|
||||
format = event->format = (MMAL_ES_FORMAT_T *)&event[1];
|
||||
format->es = (MMAL_ES_SPECIFIC_FORMAT_T *)&format[1];
|
||||
format->extradata = (uint8_t *)&format->es[1];
|
||||
format->extradata_size = buffer->length - size;
|
||||
return event;
|
||||
}
|
||||
|
||||
MMAL_STATUS_T mmal_event_error_send(MMAL_COMPONENT_T *component, MMAL_STATUS_T error_status)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T* event;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
if(!component)
|
||||
{
|
||||
LOG_ERROR("invalid component");
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
status = mmal_port_event_get(component->control, &event, MMAL_EVENT_ERROR);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("event not available for component %s %p, result %d", component->name, component, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
event->length = sizeof(MMAL_STATUS_T);
|
||||
*(MMAL_STATUS_T *)event->data = error_status;
|
||||
mmal_port_event_send(component->control, event);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
MMAL_STATUS_T mmal_event_eos_send(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_EVENT_END_OF_STREAM_T *event;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
if(!port)
|
||||
{
|
||||
LOG_ERROR("invalid port");
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
status = mmal_port_event_get(port->component->control, &buffer, MMAL_EVENT_EOS);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("event not available for port %s %p, result %d", port->name, port, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
buffer->length = sizeof(*event);
|
||||
event = (MMAL_EVENT_END_OF_STREAM_T *)buffer->data;
|
||||
event->port_type = port->type;
|
||||
event->port_index = port->index;
|
||||
mmal_port_event_send(port->component->control, buffer);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
MMAL_STATUS_T mmal_event_forward(MMAL_BUFFER_HEADER_T *event, MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
if(!port || port->type != MMAL_PORT_TYPE_OUTPUT)
|
||||
{
|
||||
LOG_ERROR("invalid port");
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
status = mmal_port_event_get(port->component->control, &buffer, event->cmd);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("event not available for port %s %p, result %d", port->name, port, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (buffer->alloc_size < event->length)
|
||||
{
|
||||
LOG_ERROR("event buffer too small (%i/%i)", buffer->alloc_size, event->length);
|
||||
mmal_buffer_header_release(buffer);
|
||||
return MMAL_ENOSPC;
|
||||
}
|
||||
|
||||
memcpy(buffer->data, event->data, event->length);
|
||||
buffer->length = event->length;
|
||||
buffer->offset = event->offset;
|
||||
buffer->flags = event->flags;
|
||||
buffer->pts = event->pts;
|
||||
mmal_port_event_send(port->component->control, buffer);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_EVENTS_PRIVATE_H
|
||||
#define MMAL_EVENTS_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mmal_events.h"
|
||||
|
||||
/** Send an error event through the component's control port.
|
||||
* The error event data will be the MMAL_STATUS_T passed in.
|
||||
*
|
||||
* @param component component to receive the error event.
|
||||
* @param status the error status to be sent.
|
||||
* @return MMAL_SUCCESS or an error if the event could not be sent.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_event_error_send(MMAL_COMPONENT_T *component, MMAL_STATUS_T status);
|
||||
|
||||
/** Send an eos event through a specific port.
|
||||
*
|
||||
* @param port port to receive the error event.
|
||||
* @return MMAL_SUCCESS or an error if the event could not be sent.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_event_eos_send(MMAL_PORT_T *port);
|
||||
|
||||
/** Forward an event onto an output port.
|
||||
* This will allocate a new event buffer on the output port, make a copy
|
||||
* of the event buffer which will then be forwarded.
|
||||
*
|
||||
* @event event to forward.
|
||||
* @param port port to forward event to.
|
||||
* @return MMAL_SUCCESS or an error if the event could not be forwarded.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_event_forward(MMAL_BUFFER_HEADER_T *event, MMAL_PORT_T *port);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_EVENTS_PRIVATE_H */
|
@ -1,183 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal_types.h"
|
||||
#include "mmal_format.h"
|
||||
#include "util/mmal_util_rational.h"
|
||||
|
||||
#define MMAL_ES_FORMAT_MAGIC MMAL_FOURCC('m','a','g','f')
|
||||
#define EXTRADATA_SIZE_DEFAULT 32
|
||||
#define EXTRADATA_SIZE_MAX (10*1024)
|
||||
|
||||
typedef struct MMAL_ES_FORMAT_PRIVATE_T
|
||||
{
|
||||
MMAL_ES_FORMAT_T format;
|
||||
MMAL_ES_SPECIFIC_FORMAT_T es;
|
||||
|
||||
uint32_t magic;
|
||||
|
||||
unsigned int extradata_size;
|
||||
uint8_t *extradata;
|
||||
|
||||
uint8_t buffer[EXTRADATA_SIZE_DEFAULT];
|
||||
|
||||
} MMAL_ES_FORMAT_PRIVATE_T;
|
||||
|
||||
/** Allocate a format structure */
|
||||
MMAL_ES_FORMAT_T *mmal_format_alloc(void)
|
||||
{
|
||||
MMAL_ES_FORMAT_PRIVATE_T *private;
|
||||
|
||||
private = vcos_malloc(sizeof(*private), "mmal format");
|
||||
if(!private) return 0;
|
||||
memset(private, 0, sizeof(*private));
|
||||
|
||||
private->magic = MMAL_ES_FORMAT_MAGIC;
|
||||
private->format.es = (void *)&private->es;
|
||||
private->extradata_size = EXTRADATA_SIZE_DEFAULT;
|
||||
|
||||
return &private->format;
|
||||
}
|
||||
|
||||
/** Free a format structure */
|
||||
void mmal_format_free(MMAL_ES_FORMAT_T *format)
|
||||
{
|
||||
MMAL_ES_FORMAT_PRIVATE_T *private = (MMAL_ES_FORMAT_PRIVATE_T *)format;
|
||||
vcos_assert(private->magic == MMAL_ES_FORMAT_MAGIC);
|
||||
if(private->extradata) vcos_free(private->extradata);
|
||||
vcos_free(private);
|
||||
}
|
||||
|
||||
/** Copy a format structure */
|
||||
void mmal_format_copy(MMAL_ES_FORMAT_T *fmt_dst, MMAL_ES_FORMAT_T *fmt_src)
|
||||
{
|
||||
void *backup = fmt_dst->es;
|
||||
*fmt_dst->es = *fmt_src->es;
|
||||
*fmt_dst = *fmt_src;
|
||||
fmt_dst->es = backup;
|
||||
fmt_dst->extradata = 0;
|
||||
fmt_dst->extradata_size = 0;
|
||||
}
|
||||
|
||||
/** Full copy of a format structure (including extradata) */
|
||||
MMAL_STATUS_T mmal_format_full_copy(MMAL_ES_FORMAT_T *fmt_dst, MMAL_ES_FORMAT_T *fmt_src)
|
||||
{
|
||||
mmal_format_copy(fmt_dst, fmt_src);
|
||||
|
||||
if (fmt_src->extradata_size)
|
||||
{
|
||||
MMAL_STATUS_T status = mmal_format_extradata_alloc(fmt_dst, fmt_src->extradata_size);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
fmt_dst->extradata_size = fmt_src->extradata_size;
|
||||
memcpy(fmt_dst->extradata, fmt_src->extradata, fmt_src->extradata_size);
|
||||
}
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Compare 2 format structures */
|
||||
uint32_t mmal_format_compare(MMAL_ES_FORMAT_T *fmt1, MMAL_ES_FORMAT_T *fmt2)
|
||||
{
|
||||
MMAL_VIDEO_FORMAT_T *video1, *video2;
|
||||
uint32_t result = 0;
|
||||
|
||||
if (fmt1->type != fmt2->type)
|
||||
return MMAL_ES_FORMAT_COMPARE_FLAG_TYPE;
|
||||
|
||||
if (fmt1->encoding != fmt2->encoding)
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_ENCODING;
|
||||
if (fmt1->bitrate != fmt2->bitrate)
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_BITRATE;
|
||||
if (fmt1->flags != fmt2->flags)
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_FLAGS;
|
||||
if (fmt1->extradata_size != fmt2->extradata_size ||
|
||||
(fmt1->extradata_size && (!fmt1->extradata || !fmt2->extradata)) ||
|
||||
memcmp(fmt1->extradata, fmt2->extradata, fmt1->extradata_size))
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_EXTRADATA;
|
||||
|
||||
/* Compare the ES specific information */
|
||||
switch (fmt1->type)
|
||||
{
|
||||
case MMAL_ES_TYPE_VIDEO:
|
||||
video1 = &fmt1->es->video;
|
||||
video2 = &fmt2->es->video;
|
||||
if (video1->width != video2->width || video1->height != video2->height)
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_RESOLUTION;
|
||||
if (memcmp(&video1->crop, &video2->crop, sizeof(video1->crop)))
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_CROPPING;
|
||||
if (!mmal_rational_equal(video1->par, video2->par))
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_ASPECT_RATIO;
|
||||
if (!mmal_rational_equal(video1->frame_rate, video2->frame_rate))
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_FRAME_RATE;
|
||||
if (video1->color_space != video2->color_space)
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_COLOR_SPACE;
|
||||
/* coverity[overrun-buffer-arg] We're comparing the rest of the video format structure */
|
||||
if (memcmp(((char*)&video1->color_space) + sizeof(video1->color_space),
|
||||
((char*)&video2->color_space) + sizeof(video2->color_space),
|
||||
sizeof(*video1) - offsetof(MMAL_VIDEO_FORMAT_T, color_space) - sizeof(video1->color_space)))
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_ES_OTHER;
|
||||
break;
|
||||
case MMAL_ES_TYPE_AUDIO:
|
||||
if (memcmp(fmt1->es, fmt2->es, sizeof(MMAL_AUDIO_FORMAT_T)))
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_ES_OTHER;
|
||||
break;
|
||||
case MMAL_ES_TYPE_SUBPICTURE:
|
||||
if (memcmp(fmt1->es, fmt2->es, sizeof(MMAL_SUBPICTURE_FORMAT_T)))
|
||||
result |= MMAL_ES_FORMAT_COMPARE_FLAG_ES_OTHER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** */
|
||||
MMAL_STATUS_T mmal_format_extradata_alloc(MMAL_ES_FORMAT_T *format, unsigned int size)
|
||||
{
|
||||
MMAL_ES_FORMAT_PRIVATE_T *private = (MMAL_ES_FORMAT_PRIVATE_T *)format;
|
||||
|
||||
/* Sanity check the size requested */
|
||||
if(size > EXTRADATA_SIZE_MAX)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
/* Allocate memory if needed */
|
||||
if(private->extradata_size < size)
|
||||
{
|
||||
if(private->extradata) vcos_free(private->extradata);
|
||||
private->extradata = vcos_malloc(size, "mmal format extradata");
|
||||
if(!private->extradata)
|
||||
return MMAL_ENOMEM;
|
||||
private->extradata_size = size;
|
||||
}
|
||||
|
||||
/* Set the fields in the actual format structure */
|
||||
if(private->extradata) private->format.extradata = private->extradata;
|
||||
else private->format.extradata = private->buffer;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "mmal_logging.h"
|
||||
#include "core/mmal_core_private.h"
|
||||
|
||||
VCOS_LOG_CAT_T mmal_log_category;
|
||||
static VCOS_LOG_LEVEL_T mmal_log_level = VCOS_LOG_ERROR;
|
||||
|
||||
void mmal_logging_init(void)
|
||||
{
|
||||
vcos_log_set_level(VCOS_LOG_CATEGORY, mmal_log_level);
|
||||
vcos_log_register("mmal", VCOS_LOG_CATEGORY);
|
||||
}
|
||||
|
||||
void mmal_logging_deinit(void)
|
||||
{
|
||||
mmal_log_level = mmal_log_category.level;
|
||||
vcos_log_unregister(VCOS_LOG_CATEGORY);
|
||||
}
|
@ -1,303 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "mmal_pool.h"
|
||||
#include "core/mmal_buffer_private.h"
|
||||
#include "mmal_logging.h"
|
||||
|
||||
/** Definition of a pool */
|
||||
typedef struct MMAL_POOL_PRIVATE_T
|
||||
{
|
||||
MMAL_POOL_T pool; /**< Actual pool */
|
||||
|
||||
MMAL_POOL_BH_CB_T cb; /**< Buffer header release callback */
|
||||
void *userdata; /**< User provided data to pass with callback */
|
||||
|
||||
mmal_pool_allocator_alloc_t allocator_alloc; /**< Allocator for the payload buffers */
|
||||
mmal_pool_allocator_free_t allocator_free; /**< Allocator for the payload buffers */
|
||||
void *allocator_context; /**< Context for the allocator */
|
||||
|
||||
unsigned int header_size; /**< Size of an initialised buffer header structure */
|
||||
unsigned int payload_size;
|
||||
|
||||
unsigned int headers_alloc_num; /**< Number of buffer headers allocated as part of the private structure */
|
||||
|
||||
} MMAL_POOL_PRIVATE_T;
|
||||
|
||||
#define ROUND_UP(s,align) ((((unsigned long)(s)) & ~((align)-1)) + (align))
|
||||
#define ALIGN 8
|
||||
|
||||
static void mmal_pool_buffer_header_release(MMAL_BUFFER_HEADER_T *header);
|
||||
|
||||
static void *mmal_pool_allocator_default_alloc(void *context, uint32_t size)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(context);
|
||||
return vcos_malloc(size, "mmal_pool payload");
|
||||
}
|
||||
|
||||
static void mmal_pool_allocator_default_free(void *context, void *mem)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(context);
|
||||
vcos_free(mem);
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_pool_initialise_buffer_headers(MMAL_POOL_T *pool, unsigned int headers,
|
||||
MMAL_BOOL_T reinitialise)
|
||||
{
|
||||
MMAL_POOL_PRIVATE_T *private = (MMAL_POOL_PRIVATE_T *)pool;
|
||||
MMAL_BUFFER_HEADER_T *header;
|
||||
uint8_t *payload = NULL;
|
||||
unsigned int i;
|
||||
|
||||
header = (MMAL_BUFFER_HEADER_T *)((uint8_t *)pool->header + ROUND_UP(sizeof(void *)*headers,ALIGN));
|
||||
|
||||
for (i = 0; i < headers; i++)
|
||||
{
|
||||
if (reinitialise)
|
||||
header = mmal_buffer_header_initialise(header, private->header_size);
|
||||
|
||||
if (private->payload_size && private->allocator_alloc)
|
||||
{
|
||||
LOG_TRACE("allocating %u bytes for payload %u/%u", private->payload_size, i, headers);
|
||||
payload = (uint8_t*)private->allocator_alloc(private->allocator_context, private->payload_size);
|
||||
if (! payload)
|
||||
{
|
||||
LOG_ERROR("failed to allocate payload %u/%u", i, headers);
|
||||
return MMAL_ENOMEM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (header->priv->pf_payload_free && header->priv->payload && header->priv->payload_size)
|
||||
{
|
||||
LOG_TRACE("freeing %u bytes for payload %u/%u", header->priv->payload_size, i, headers);
|
||||
header->priv->pf_payload_free(header->priv->payload_context, header->priv->payload);
|
||||
}
|
||||
}
|
||||
header->data = payload;
|
||||
header->alloc_size = private->payload_size;
|
||||
header->priv->pf_release = mmal_pool_buffer_header_release;
|
||||
header->priv->owner = (void *)pool;
|
||||
header->priv->refcount = 1;
|
||||
header->priv->payload = payload;
|
||||
header->priv->payload_context = private->allocator_context;
|
||||
header->priv->pf_payload_free = private->allocator_free;
|
||||
header->priv->payload_size = private->payload_size;
|
||||
pool->header[i] = header;
|
||||
pool->headers_num = i+1;
|
||||
header = (MMAL_BUFFER_HEADER_T *)((uint8_t*)header + private->header_size);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Create a pool of MMAL_BUFFER_HEADER_T */
|
||||
MMAL_POOL_T *mmal_pool_create(unsigned int headers, uint32_t payload_size)
|
||||
{
|
||||
return mmal_pool_create_with_allocator(headers, payload_size, NULL,
|
||||
mmal_pool_allocator_default_alloc, mmal_pool_allocator_default_free);
|
||||
}
|
||||
|
||||
/** Create a pool of MMAL_BUFFER_HEADER_T */
|
||||
MMAL_POOL_T *mmal_pool_create_with_allocator(unsigned int headers, uint32_t payload_size,
|
||||
void *allocator_context, mmal_pool_allocator_alloc_t allocator_alloc,
|
||||
mmal_pool_allocator_free_t allocator_free)
|
||||
{
|
||||
unsigned int i, headers_array_size, header_size, pool_size;
|
||||
MMAL_POOL_PRIVATE_T *private;
|
||||
MMAL_BUFFER_HEADER_T **array;
|
||||
MMAL_POOL_T *pool;
|
||||
MMAL_QUEUE_T *queue;
|
||||
|
||||
queue = mmal_queue_create();
|
||||
if (!queue)
|
||||
{
|
||||
LOG_ERROR("failed to create queue");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Calculate how much memory we need */
|
||||
pool_size = ROUND_UP(sizeof(MMAL_POOL_PRIVATE_T),ALIGN);
|
||||
headers_array_size = ROUND_UP(sizeof(void *)*headers,ALIGN);
|
||||
header_size = ROUND_UP(mmal_buffer_header_size(0),ALIGN);
|
||||
|
||||
LOG_TRACE("allocating %u + %u + %u * %u bytes for pool",
|
||||
pool_size, headers_array_size, header_size, headers);
|
||||
private = vcos_calloc(pool_size, 1, "MMAL pool");
|
||||
array = vcos_calloc(headers_array_size + header_size * headers, 1, "MMAL buffer headers");
|
||||
if (!private || !array)
|
||||
{
|
||||
LOG_ERROR("failed to allocate pool");
|
||||
if (private) vcos_free(private);
|
||||
if (array) vcos_free(array);
|
||||
mmal_queue_destroy(queue);
|
||||
return NULL;
|
||||
}
|
||||
pool = &private->pool;
|
||||
pool->queue = queue;
|
||||
pool->header = (MMAL_BUFFER_HEADER_T **)array;
|
||||
private->header_size = header_size;
|
||||
private->payload_size = payload_size;
|
||||
private->headers_alloc_num = headers;
|
||||
|
||||
/* Use default allocators if none has been specified by client */
|
||||
if (!allocator_alloc || !allocator_free)
|
||||
{
|
||||
allocator_alloc = mmal_pool_allocator_default_alloc;
|
||||
allocator_free = mmal_pool_allocator_default_free;
|
||||
allocator_context = NULL;
|
||||
}
|
||||
|
||||
/* Keep reference to the allocator to allow resizing the payloads at a later point */
|
||||
private->allocator_alloc = allocator_alloc;
|
||||
private->allocator_free = allocator_free;
|
||||
private->allocator_context = allocator_context;
|
||||
|
||||
if (mmal_pool_initialise_buffer_headers(pool, headers, 1) != MMAL_SUCCESS)
|
||||
{
|
||||
mmal_pool_destroy(pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add all the headers to the queue */
|
||||
for (i = 0; i < pool->headers_num; i++)
|
||||
mmal_queue_put(queue, pool->header[i]);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
/** Destroy a pool of MMAL_BUFFER_HEADER_T */
|
||||
void mmal_pool_destroy(MMAL_POOL_T *pool)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
/* If the payload_size is non-zero then the buffer header payload
|
||||
* must be freed. Otherwise it is the caller's responsibility. */
|
||||
for (i = 0; i < pool->headers_num; ++i)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_PRIVATE_T* priv = pool->header[i]->priv;
|
||||
|
||||
if (priv->pf_payload_free && priv->payload && priv->payload_size)
|
||||
priv->pf_payload_free(priv->payload_context, priv->payload);
|
||||
}
|
||||
|
||||
if (pool->header)
|
||||
vcos_free(pool->header);
|
||||
|
||||
if(pool->queue) mmal_queue_destroy(pool->queue);
|
||||
vcos_free(pool);
|
||||
}
|
||||
|
||||
/** Resize a pool of MMAL_BUFFER_HEADER_T */
|
||||
MMAL_STATUS_T mmal_pool_resize(MMAL_POOL_T *pool, unsigned int headers, uint32_t payload_size)
|
||||
{
|
||||
MMAL_POOL_PRIVATE_T *private = (MMAL_POOL_PRIVATE_T *)pool;
|
||||
unsigned int i;
|
||||
|
||||
if (!private || !headers)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
/* Check if anything needs to be done */
|
||||
if (headers == pool->headers_num && payload_size == private->payload_size)
|
||||
return MMAL_SUCCESS;
|
||||
|
||||
/* Remove all the headers from the queue */
|
||||
for (i = 0; i < pool->headers_num; i++)
|
||||
mmal_queue_get(pool->queue);
|
||||
|
||||
/* Start by freeing the current payloads */
|
||||
private->payload_size = 0;
|
||||
mmal_pool_initialise_buffer_headers(pool, pool->headers_num, 0);
|
||||
pool->headers_num = 0;
|
||||
|
||||
/* Check if we need to reallocate the buffer headers themselves */
|
||||
if (headers > private->headers_alloc_num)
|
||||
{
|
||||
private->headers_alloc_num = 0;
|
||||
if (pool->header)
|
||||
vcos_free(pool->header);
|
||||
pool->header =
|
||||
vcos_calloc(private->header_size * headers + ROUND_UP(sizeof(void *)*headers,ALIGN),
|
||||
1, "MMAL buffer headers");
|
||||
if (!pool->header)
|
||||
return MMAL_ENOMEM;
|
||||
private->headers_alloc_num = headers;
|
||||
}
|
||||
|
||||
/* Allocate the new payloads */
|
||||
private->payload_size = payload_size;
|
||||
mmal_pool_initialise_buffer_headers(pool, headers, 1);
|
||||
|
||||
/* Add all the headers to the queue */
|
||||
for (i = 0; i < pool->headers_num; i++)
|
||||
mmal_queue_put(pool->queue, pool->header[i]);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/** Buffer header release callback.
|
||||
* Call out to a further client callback and put the buffer back in the queue
|
||||
* so it can be reused, unless the client callback prevents it. */
|
||||
static void mmal_pool_buffer_header_release(MMAL_BUFFER_HEADER_T *header)
|
||||
{
|
||||
MMAL_POOL_T *pool = (MMAL_POOL_T *)header->priv->owner;
|
||||
MMAL_POOL_PRIVATE_T *private = (MMAL_POOL_PRIVATE_T *)pool;
|
||||
MMAL_BOOL_T queue_buffer = 1;
|
||||
|
||||
header->priv->refcount = 1;
|
||||
if(private->cb)
|
||||
queue_buffer = private->cb(pool, header, private->userdata);
|
||||
if (queue_buffer)
|
||||
mmal_queue_put(pool->queue, header);
|
||||
}
|
||||
|
||||
/** Set a buffer header release callback to the pool */
|
||||
void mmal_pool_callback_set(MMAL_POOL_T *pool, MMAL_POOL_BH_CB_T cb, void *userdata)
|
||||
{
|
||||
MMAL_POOL_PRIVATE_T *private = (MMAL_POOL_PRIVATE_T *)pool;
|
||||
private->cb = cb;
|
||||
private->userdata = userdata;
|
||||
}
|
||||
|
||||
/* Set a pre-release callback for all buffer headers in the pool */
|
||||
void mmal_pool_pre_release_callback_set(MMAL_POOL_T *pool, MMAL_BH_PRE_RELEASE_CB_T cb, void *userdata)
|
||||
{
|
||||
unsigned int i;
|
||||
MMAL_POOL_PRIVATE_T *private = (MMAL_POOL_PRIVATE_T *)pool;
|
||||
MMAL_BUFFER_HEADER_T *header =
|
||||
(MMAL_BUFFER_HEADER_T*)((uint8_t*)pool->header + ROUND_UP(sizeof(void*)*pool->headers_num,ALIGN));
|
||||
|
||||
for (i = 0; i < pool->headers_num; ++i)
|
||||
{
|
||||
mmal_buffer_header_pre_release_cb_set(header, cb, userdata);
|
||||
header = (MMAL_BUFFER_HEADER_T *)((uint8_t*)header + private->header_size);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,803 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal_clock.h"
|
||||
#include "mmal_logging.h"
|
||||
#include "core/mmal_clock_private.h"
|
||||
#include "core/mmal_port_private.h"
|
||||
#include "util/mmal_util.h"
|
||||
|
||||
#ifdef __VIDEOCORE__
|
||||
# include "vcfw/rtos/common/rtos_common_mem.h"
|
||||
#endif
|
||||
|
||||
/** Minimum number of buffers required on a clock port */
|
||||
#define MMAL_PORT_CLOCK_BUFFERS_MIN 16
|
||||
|
||||
/** Private clock port context */
|
||||
typedef struct MMAL_PORT_CLOCK_T
|
||||
{
|
||||
MMAL_PORT_CLOCK_EVENT_CB event_cb; /**< callback for notifying the component of clock events */
|
||||
MMAL_QUEUE_T *queue; /**< queue for empty buffers sent to the port */
|
||||
MMAL_CLOCK_T *clock; /**< clock module for scheduling requests */
|
||||
MMAL_BOOL_T is_reference; /**< TRUE -> clock port is a reference, therefore
|
||||
will forward time updates */
|
||||
MMAL_BOOL_T buffer_info_reporting; /**< controls buffer info reporting */
|
||||
} MMAL_PORT_CLOCK_T;
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
*****************************************************************************/
|
||||
#ifdef __VIDEOCORE__
|
||||
/* FIXME: mmal_buffer_header_mem_lock() assumes that payload memory is on the
|
||||
* relocatable heap when on VC. However that is not always the case. The MMAL
|
||||
* framework will allocate memory from the normal heap when ports are connected.
|
||||
* To work around this, override the default behaviour by providing a payload
|
||||
* allocator for clock ports which always allocates from the relocatable heap. */
|
||||
static uint8_t* mmal_port_clock_payload_alloc(MMAL_PORT_T *port, uint32_t payload_size)
|
||||
{
|
||||
int alignment = port->buffer_alignment_min;
|
||||
uint8_t *mem;
|
||||
|
||||
if (!alignment)
|
||||
alignment = 32;
|
||||
vcos_assert((alignment & (alignment-1)) == 0);
|
||||
|
||||
mem = (uint8_t*)mem_alloc(payload_size, alignment, MEM_FLAG_DIRECT, port->name);
|
||||
if (!mem)
|
||||
{
|
||||
LOG_ERROR("could not allocate %u bytes", payload_size);
|
||||
return NULL;
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void mmal_port_clock_payload_free(MMAL_PORT_T *port, uint8_t *payload)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
mem_release((MEM_HANDLE_T)payload);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Callback invoked by the clock module in response to a client request */
|
||||
static void mmal_port_clock_request_cb(MMAL_CLOCK_T* clock, int64_t media_time, void *cb_data, MMAL_CLOCK_VOID_FP cb)
|
||||
{
|
||||
MMAL_PORT_CLOCK_REQUEST_CB cb_client = (MMAL_PORT_CLOCK_REQUEST_CB)cb;
|
||||
|
||||
/* Forward to the client */
|
||||
cb_client((MMAL_PORT_T*)clock->user_data, media_time, cb_data);
|
||||
}
|
||||
|
||||
/* Process buffers received from other clock ports */
|
||||
static MMAL_STATUS_T mmal_port_clock_process_buffer(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_PORT_CLOCK_T *priv_clock = port->priv->clock;
|
||||
MMAL_STATUS_T status = MMAL_SUCCESS;
|
||||
MMAL_CLOCK_EVENT_T event = MMAL_CLOCK_EVENT_INIT(MMAL_CLOCK_EVENT_INVALID);
|
||||
|
||||
if (buffer->length != sizeof(MMAL_CLOCK_EVENT_T))
|
||||
{
|
||||
LOG_ERROR("invalid buffer length %d expected %d",
|
||||
buffer->length, sizeof(MMAL_CLOCK_EVENT_T));
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
mmal_buffer_header_mem_lock(buffer);
|
||||
memcpy(&event, buffer->data, sizeof(MMAL_CLOCK_EVENT_T));
|
||||
mmal_buffer_header_mem_unlock(buffer);
|
||||
|
||||
if (event.magic != MMAL_CLOCK_EVENT_MAGIC)
|
||||
{
|
||||
LOG_ERROR("buffer corrupt (magic %4.4s)", (char*)&event.magic);
|
||||
buffer->length = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
LOG_TRACE("port %s id %4.4s", port->name, (char*)&event.id);
|
||||
|
||||
switch (event.id)
|
||||
{
|
||||
case MMAL_CLOCK_EVENT_ACTIVE:
|
||||
status = mmal_clock_active_set(priv_clock->clock, event.data.enable);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_TIME:
|
||||
status = mmal_clock_media_time_set(priv_clock->clock, event.data.media_time);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_SCALE:
|
||||
status = mmal_clock_scale_set(priv_clock->clock, event.data.scale);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_UPDATE_THRESHOLD:
|
||||
status = mmal_clock_update_threshold_set(priv_clock->clock, &event.data.update_threshold);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_DISCONT_THRESHOLD:
|
||||
status = mmal_clock_discont_threshold_set(priv_clock->clock, &event.data.discont_threshold);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_REQUEST_THRESHOLD:
|
||||
status = mmal_clock_request_threshold_set(priv_clock->clock, &event.data.request_threshold);
|
||||
break;
|
||||
case MMAL_CLOCK_EVENT_INPUT_BUFFER_INFO:
|
||||
case MMAL_CLOCK_EVENT_OUTPUT_BUFFER_INFO:
|
||||
/* nothing to do - just forward to the client */
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("invalid event %4.4s", (char*)&event.id);
|
||||
status = MMAL_EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (priv_clock->event_cb && status == MMAL_SUCCESS)
|
||||
{
|
||||
/* Notify the component, but don't return the buffer */
|
||||
event.buffer = buffer;
|
||||
priv_clock->event_cb(port, &event);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Finished with the buffer, so return it */
|
||||
buffer->length = 0;
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_port_clock_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
MMAL_PORT_CLOCK_T *priv_clock = port->priv->clock;
|
||||
|
||||
if (buffer->length)
|
||||
return mmal_port_clock_process_buffer(port, buffer);
|
||||
|
||||
/* Queue empty buffers to be used later when forwarding clock updates */
|
||||
mmal_queue_put(priv_clock->queue, buffer);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_port_clock_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/* Flush empty buffers */
|
||||
buffer = mmal_queue_get(port->priv->clock->queue);
|
||||
while (buffer)
|
||||
{
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
buffer = mmal_queue_get(port->priv->clock->queue);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_port_clock_parameter_set(MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_SUCCESS;
|
||||
MMAL_CLOCK_EVENT_T event = MMAL_CLOCK_EVENT_INIT(MMAL_CLOCK_EVENT_INVALID);
|
||||
|
||||
switch (param->id)
|
||||
{
|
||||
case MMAL_PARAMETER_CLOCK_REFERENCE:
|
||||
{
|
||||
const MMAL_PARAMETER_BOOLEAN_T *p = (const MMAL_PARAMETER_BOOLEAN_T*)param;
|
||||
status = mmal_port_clock_reference_set(port, p->enable);
|
||||
event.id = MMAL_CLOCK_EVENT_REFERENCE;
|
||||
event.data.enable = p->enable;
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_ACTIVE:
|
||||
{
|
||||
const MMAL_PARAMETER_BOOLEAN_T *p = (const MMAL_PARAMETER_BOOLEAN_T*)param;
|
||||
status = mmal_port_clock_active_set(port, p->enable);
|
||||
event.id = MMAL_CLOCK_EVENT_ACTIVE;
|
||||
event.data.enable = p->enable;
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_SCALE:
|
||||
{
|
||||
const MMAL_PARAMETER_RATIONAL_T *p = (const MMAL_PARAMETER_RATIONAL_T*)param;
|
||||
status = mmal_port_clock_scale_set(port, p->value);
|
||||
event.id = MMAL_CLOCK_EVENT_SCALE;
|
||||
event.data.scale = p->value;
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_TIME:
|
||||
{
|
||||
const MMAL_PARAMETER_INT64_T *p = (const MMAL_PARAMETER_INT64_T*)param;
|
||||
status = mmal_port_clock_media_time_set(port, p->value);
|
||||
event.id = MMAL_CLOCK_EVENT_TIME;
|
||||
event.data.media_time = p->value;
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD:
|
||||
{
|
||||
const MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD_T *p = (const MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD_T *)param;
|
||||
status = mmal_port_clock_update_threshold_set(port, &p->value);
|
||||
event.id = MMAL_CLOCK_EVENT_UPDATE_THRESHOLD;
|
||||
event.data.update_threshold = p->value;
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD:
|
||||
{
|
||||
const MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD_T *p = (const MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD_T *)param;
|
||||
status = mmal_port_clock_discont_threshold_set(port, &p->value);
|
||||
event.id = MMAL_CLOCK_EVENT_DISCONT_THRESHOLD;
|
||||
event.data.discont_threshold = p->value;
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD:
|
||||
{
|
||||
const MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD_T *p = (const MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD_T *)param;
|
||||
status = mmal_port_clock_request_threshold_set(port, &p->value);
|
||||
event.id = MMAL_CLOCK_EVENT_REQUEST_THRESHOLD;
|
||||
event.data.request_threshold = p->value;
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_ENABLE_BUFFER_INFO:
|
||||
{
|
||||
const MMAL_PARAMETER_BOOLEAN_T *p = (const MMAL_PARAMETER_BOOLEAN_T*)param;
|
||||
port->priv->clock->buffer_info_reporting = p->enable;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR("unsupported clock parameter 0x%x", param->id);
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
/* Notify the component */
|
||||
if (port->priv->clock->event_cb && status == MMAL_SUCCESS)
|
||||
port->priv->clock->event_cb(port, &event);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_port_clock_parameter_get(MMAL_PORT_T *port, MMAL_PARAMETER_HEADER_T *param)
|
||||
{
|
||||
MMAL_PORT_CLOCK_T *priv_clock = port->priv->clock;
|
||||
MMAL_STATUS_T status = MMAL_SUCCESS;
|
||||
|
||||
switch (param->id)
|
||||
{
|
||||
case MMAL_PARAMETER_CLOCK_REFERENCE:
|
||||
{
|
||||
MMAL_PARAMETER_BOOLEAN_T *p = (MMAL_PARAMETER_BOOLEAN_T*)param;
|
||||
p->enable = priv_clock->is_reference;
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_ACTIVE:
|
||||
{
|
||||
MMAL_PARAMETER_BOOLEAN_T *p = (MMAL_PARAMETER_BOOLEAN_T*)param;
|
||||
p->enable = mmal_clock_is_active(priv_clock->clock);
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_SCALE:
|
||||
{
|
||||
MMAL_PARAMETER_RATIONAL_T *p = (MMAL_PARAMETER_RATIONAL_T*)param;
|
||||
p->value = mmal_clock_scale_get(priv_clock->clock);
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_TIME:
|
||||
{
|
||||
MMAL_PARAMETER_INT64_T *p = (MMAL_PARAMETER_INT64_T*)param;
|
||||
p->value = mmal_clock_media_time_get(priv_clock->clock);
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD:
|
||||
{
|
||||
MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD_T *p = (MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD_T *)param;
|
||||
status = mmal_clock_update_threshold_get(priv_clock->clock, &p->value);
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD:
|
||||
{
|
||||
MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD_T *p = (MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD_T *)param;
|
||||
status = mmal_clock_discont_threshold_get(priv_clock->clock, &p->value);
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD:
|
||||
{
|
||||
MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD_T *p = (MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD_T *)param;
|
||||
status = mmal_clock_request_threshold_get(priv_clock->clock, &p->value);
|
||||
}
|
||||
break;
|
||||
case MMAL_PARAMETER_CLOCK_ENABLE_BUFFER_INFO:
|
||||
{
|
||||
MMAL_PARAMETER_BOOLEAN_T *p = (MMAL_PARAMETER_BOOLEAN_T*)param;
|
||||
p->enable = priv_clock->buffer_info_reporting;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("unsupported clock parameter 0x%x", param->id);
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_port_clock_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(cb);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_port_clock_disable(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PORT_CLOCK_T *priv_clock = port->priv->clock;
|
||||
|
||||
if (mmal_clock_is_active(priv_clock->clock))
|
||||
mmal_clock_active_set(priv_clock->clock, MMAL_FALSE);
|
||||
|
||||
mmal_port_clock_flush(port);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_port_clock_set_format(MMAL_PORT_T *port)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmal_port_clock_connect(MMAL_PORT_T *port, MMAL_PORT_T *other_port)
|
||||
{
|
||||
MMAL_PARAM_UNUSED(port);
|
||||
MMAL_PARAM_UNUSED(other_port);
|
||||
return MMAL_ENOSYS;
|
||||
}
|
||||
|
||||
/* Send an event buffer to a connected port */
|
||||
static MMAL_STATUS_T mmal_port_clock_forward_event(MMAL_PORT_T *port, const MMAL_CLOCK_EVENT_T *event)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
buffer = mmal_queue_get(port->priv->clock->queue);
|
||||
if (!buffer)
|
||||
{
|
||||
LOG_INFO("%s: no free event buffers available for event %4.4s", port->name, (const char*)&event->id);
|
||||
return MMAL_ENOSPC;
|
||||
}
|
||||
|
||||
status = mmal_buffer_header_mem_lock(buffer);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("failed to lock buffer %s", mmal_status_to_string(status));
|
||||
mmal_queue_put_back(port->priv->clock->queue, buffer);
|
||||
goto end;
|
||||
}
|
||||
buffer->length = sizeof(MMAL_CLOCK_EVENT_T);
|
||||
memcpy(buffer->data, event, buffer->length);
|
||||
mmal_buffer_header_mem_unlock(buffer);
|
||||
|
||||
mmal_port_buffer_header_callback(port, buffer);
|
||||
|
||||
end:
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Send a clock active state to a connected port */
|
||||
static MMAL_STATUS_T mmal_port_clock_forward_active_state(MMAL_PORT_T *port, MMAL_BOOL_T active)
|
||||
{
|
||||
MMAL_CLOCK_EVENT_T event;
|
||||
|
||||
event.id = MMAL_CLOCK_EVENT_ACTIVE;
|
||||
event.magic = MMAL_CLOCK_EVENT_MAGIC;
|
||||
event.data.enable = active;
|
||||
|
||||
return mmal_port_clock_forward_event(port, &event);
|
||||
}
|
||||
|
||||
/* Send a clock scale update to a connected port */
|
||||
static MMAL_STATUS_T mmal_port_clock_forward_scale(MMAL_PORT_T *port, MMAL_RATIONAL_T scale)
|
||||
{
|
||||
MMAL_CLOCK_EVENT_T event;
|
||||
|
||||
event.id = MMAL_CLOCK_EVENT_SCALE;
|
||||
event.magic = MMAL_CLOCK_EVENT_MAGIC;
|
||||
event.data.scale = scale;
|
||||
|
||||
return mmal_port_clock_forward_event(port, &event);
|
||||
}
|
||||
|
||||
/* Send a clock time update to a connected port */
|
||||
static MMAL_STATUS_T mmal_port_clock_forward_media_time(MMAL_PORT_T *port, int64_t media_time)
|
||||
{
|
||||
MMAL_CLOCK_EVENT_T event;
|
||||
|
||||
event.id = MMAL_CLOCK_EVENT_TIME;
|
||||
event.magic = MMAL_CLOCK_EVENT_MAGIC;
|
||||
event.data.media_time = media_time;
|
||||
|
||||
return mmal_port_clock_forward_event(port, &event);
|
||||
}
|
||||
|
||||
/* Send a clock update threshold to a connected port */
|
||||
static MMAL_STATUS_T mmal_port_clock_forward_update_threshold(MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_UPDATE_THRESHOLD_T *threshold)
|
||||
{
|
||||
MMAL_CLOCK_EVENT_T event;
|
||||
|
||||
event.id = MMAL_CLOCK_EVENT_UPDATE_THRESHOLD;
|
||||
event.magic = MMAL_CLOCK_EVENT_MAGIC;
|
||||
event.data.update_threshold = *threshold;
|
||||
|
||||
return mmal_port_clock_forward_event(port, &event);
|
||||
}
|
||||
|
||||
/* Send a clock discontinuity threshold to a connected port */
|
||||
static MMAL_STATUS_T mmal_port_clock_forward_discont_threshold(MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_DISCONT_THRESHOLD_T *threshold)
|
||||
{
|
||||
MMAL_CLOCK_EVENT_T event;
|
||||
|
||||
event.id = MMAL_CLOCK_EVENT_DISCONT_THRESHOLD;
|
||||
event.magic = MMAL_CLOCK_EVENT_MAGIC;
|
||||
event.data.discont_threshold = *threshold;
|
||||
|
||||
return mmal_port_clock_forward_event(port, &event);
|
||||
}
|
||||
|
||||
/* Send a clock request threshold to a connected port */
|
||||
static MMAL_STATUS_T mmal_port_clock_forward_request_threshold(MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_REQUEST_THRESHOLD_T *threshold)
|
||||
{
|
||||
MMAL_CLOCK_EVENT_T event;
|
||||
|
||||
event.id = MMAL_CLOCK_EVENT_REQUEST_THRESHOLD;
|
||||
event.magic = MMAL_CLOCK_EVENT_MAGIC;
|
||||
event.data.request_threshold = *threshold;
|
||||
|
||||
return mmal_port_clock_forward_event(port, &event);
|
||||
}
|
||||
|
||||
/* Send information regarding an input buffer to connected port */
|
||||
static MMAL_STATUS_T mmal_port_clock_forward_input_buffer_info(MMAL_PORT_T *port, const MMAL_CLOCK_BUFFER_INFO_T *info)
|
||||
{
|
||||
MMAL_CLOCK_EVENT_T event;
|
||||
|
||||
event.id = MMAL_CLOCK_EVENT_INPUT_BUFFER_INFO;
|
||||
event.magic = MMAL_CLOCK_EVENT_MAGIC;
|
||||
event.data.buffer = *info;
|
||||
|
||||
return mmal_port_clock_forward_event(port, &event);
|
||||
}
|
||||
|
||||
/* Send information regarding an output buffer to connected port */
|
||||
static MMAL_STATUS_T mmal_port_clock_forward_output_buffer_info(MMAL_PORT_T *port, const MMAL_CLOCK_BUFFER_INFO_T *info)
|
||||
{
|
||||
MMAL_CLOCK_EVENT_T event;
|
||||
|
||||
event.id = MMAL_CLOCK_EVENT_OUTPUT_BUFFER_INFO;
|
||||
event.magic = MMAL_CLOCK_EVENT_MAGIC;
|
||||
event.data.buffer = *info;
|
||||
|
||||
return mmal_port_clock_forward_event(port, &event);
|
||||
}
|
||||
|
||||
/* Initialise all callbacks and setup internal resources */
|
||||
static MMAL_STATUS_T mmal_port_clock_setup(MMAL_PORT_T *port, unsigned int extra_size,
|
||||
MMAL_PORT_CLOCK_EVENT_CB event_cb)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
port->priv->clock = (MMAL_PORT_CLOCK_T*)((char*)(port->priv->module) + extra_size);
|
||||
|
||||
status = mmal_clock_create(&port->priv->clock->clock);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("failed to create clock module on port %s (%s)",
|
||||
port->name, mmal_status_to_string(status));
|
||||
return status;
|
||||
}
|
||||
port->priv->clock->clock->user_data = port;
|
||||
|
||||
port->buffer_size = sizeof(MMAL_CLOCK_EVENT_T);
|
||||
port->buffer_size_min = sizeof(MMAL_CLOCK_EVENT_T);
|
||||
port->buffer_num_min = MMAL_PORT_CLOCK_BUFFERS_MIN;
|
||||
port->buffer_num_recommended = MMAL_PORT_CLOCK_BUFFERS_MIN;
|
||||
|
||||
port->priv->clock->event_cb = event_cb;
|
||||
port->priv->clock->queue = mmal_queue_create();
|
||||
if (!port->priv->clock->queue)
|
||||
{
|
||||
mmal_clock_destroy(port->priv->clock->clock);
|
||||
return MMAL_ENOMEM;
|
||||
}
|
||||
|
||||
port->priv->pf_set_format = mmal_port_clock_set_format;
|
||||
port->priv->pf_enable = mmal_port_clock_enable;
|
||||
port->priv->pf_disable = mmal_port_clock_disable;
|
||||
port->priv->pf_send = mmal_port_clock_send;
|
||||
port->priv->pf_flush = mmal_port_clock_flush;
|
||||
port->priv->pf_parameter_set = mmal_port_clock_parameter_set;
|
||||
port->priv->pf_parameter_get = mmal_port_clock_parameter_get;
|
||||
port->priv->pf_connect = mmal_port_clock_connect;
|
||||
#ifdef __VIDEOCORE__
|
||||
port->priv->pf_payload_alloc = mmal_port_clock_payload_alloc;
|
||||
port->priv->pf_payload_free = mmal_port_clock_payload_free;
|
||||
port->capabilities = MMAL_PORT_CAPABILITY_ALLOCATION;
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Release all internal resources */
|
||||
static void mmal_port_clock_teardown(MMAL_PORT_T *port)
|
||||
{
|
||||
if (!port)
|
||||
return;
|
||||
mmal_queue_destroy(port->priv->clock->queue);
|
||||
mmal_clock_destroy(port->priv->clock->clock);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
*****************************************************************************/
|
||||
/* Allocate a clock port */
|
||||
MMAL_PORT_T* mmal_port_clock_alloc(MMAL_COMPONENT_T *component, unsigned int extra_size,
|
||||
MMAL_PORT_CLOCK_EVENT_CB event_cb)
|
||||
{
|
||||
MMAL_PORT_T *port;
|
||||
|
||||
port = mmal_port_alloc(component, MMAL_PORT_TYPE_CLOCK,
|
||||
extra_size + sizeof(MMAL_PORT_CLOCK_T));
|
||||
if (!port)
|
||||
return NULL;
|
||||
|
||||
if (mmal_port_clock_setup(port, extra_size, event_cb) != MMAL_SUCCESS)
|
||||
{
|
||||
mmal_port_free(port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
/* Free a clock port */
|
||||
void mmal_port_clock_free(MMAL_PORT_T *port)
|
||||
{
|
||||
mmal_port_clock_teardown(port);
|
||||
mmal_port_free(port);
|
||||
}
|
||||
|
||||
/* Allocate an array of clock ports */
|
||||
MMAL_PORT_T **mmal_ports_clock_alloc(MMAL_COMPONENT_T *component, unsigned int ports_num,
|
||||
unsigned int extra_size, MMAL_PORT_CLOCK_EVENT_CB event_cb)
|
||||
{
|
||||
unsigned int i;
|
||||
MMAL_PORT_T **ports;
|
||||
|
||||
ports = mmal_ports_alloc(component, ports_num, MMAL_PORT_TYPE_CLOCK,
|
||||
extra_size + sizeof(MMAL_PORT_CLOCK_T));
|
||||
if (!ports)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ports_num; i++)
|
||||
{
|
||||
if (mmal_port_clock_setup(ports[i], extra_size, event_cb) != MMAL_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != ports_num)
|
||||
{
|
||||
for (ports_num = i, i = 0; i < ports_num; i++)
|
||||
mmal_port_clock_free(ports[i]);
|
||||
vcos_free(ports);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ports;
|
||||
}
|
||||
|
||||
/* Free an array of clock ports */
|
||||
void mmal_ports_clock_free(MMAL_PORT_T **ports, unsigned int ports_num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ports_num; i++)
|
||||
mmal_port_clock_free(ports[i]);
|
||||
vcos_free(ports);
|
||||
}
|
||||
|
||||
/* Register a callback request */
|
||||
MMAL_STATUS_T mmal_port_clock_request_add(MMAL_PORT_T *port, int64_t media_time,
|
||||
MMAL_PORT_CLOCK_REQUEST_CB cb, void *cb_data)
|
||||
{
|
||||
return mmal_clock_request_add(port->priv->clock->clock, media_time,
|
||||
mmal_port_clock_request_cb, cb_data, (MMAL_CLOCK_VOID_FP)cb);
|
||||
}
|
||||
|
||||
/* Flush all pending clock requests */
|
||||
MMAL_STATUS_T mmal_port_clock_request_flush(MMAL_PORT_T *port)
|
||||
{
|
||||
return mmal_clock_request_flush(port->priv->clock->clock);
|
||||
}
|
||||
|
||||
/* Set the clock port's reference state */
|
||||
MMAL_STATUS_T mmal_port_clock_reference_set(MMAL_PORT_T *port, MMAL_BOOL_T reference)
|
||||
{
|
||||
port->priv->clock->is_reference = reference;
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get the clock port's reference state */
|
||||
MMAL_BOOL_T mmal_port_clock_reference_get(MMAL_PORT_T *port)
|
||||
{
|
||||
return port->priv->clock->is_reference;
|
||||
}
|
||||
|
||||
/* Set the clock port's active state */
|
||||
MMAL_STATUS_T mmal_port_clock_active_set(MMAL_PORT_T *port, MMAL_BOOL_T active)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
status = mmal_clock_active_set(port->priv->clock->clock, active);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (port->priv->clock->is_reference)
|
||||
status = mmal_port_clock_forward_active_state(port, active);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Get the clock port's active state */
|
||||
MMAL_BOOL_T mmal_port_clock_active_get(MMAL_PORT_T *port)
|
||||
{
|
||||
return mmal_clock_is_active(port->priv->clock->clock);
|
||||
}
|
||||
|
||||
/* Set the clock port's scale */
|
||||
MMAL_STATUS_T mmal_port_clock_scale_set(MMAL_PORT_T *port, MMAL_RATIONAL_T scale)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
status = mmal_clock_scale_set(port->priv->clock->clock, scale);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (port->priv->clock->is_reference)
|
||||
status = mmal_port_clock_forward_scale(port, scale);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Get the clock port's scale */
|
||||
MMAL_RATIONAL_T mmal_port_clock_scale_get(MMAL_PORT_T *port)
|
||||
{
|
||||
return mmal_clock_scale_get(port->priv->clock->clock);
|
||||
}
|
||||
|
||||
/* Set the clock port's media-time */
|
||||
MMAL_STATUS_T mmal_port_clock_media_time_set(MMAL_PORT_T *port, int64_t media_time)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
status = mmal_clock_media_time_set(port->priv->clock->clock, media_time);
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_DEBUG("clock media-time update ignored");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (port->priv->clock->is_reference)
|
||||
status = mmal_port_clock_forward_media_time(port, media_time);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Get the clock port's media-time */
|
||||
int64_t mmal_port_clock_media_time_get(MMAL_PORT_T *port)
|
||||
{
|
||||
return mmal_clock_media_time_get(port->priv->clock->clock);
|
||||
}
|
||||
|
||||
/* Set the clock port's update threshold */
|
||||
MMAL_STATUS_T mmal_port_clock_update_threshold_set(MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_UPDATE_THRESHOLD_T *threshold)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
status = mmal_clock_update_threshold_set(port->priv->clock->clock, threshold);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (port->priv->clock->is_reference)
|
||||
status = mmal_port_clock_forward_update_threshold(port, threshold);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Get the clock port's update threshold */
|
||||
MMAL_STATUS_T mmal_port_clock_update_threshold_get(MMAL_PORT_T *port,
|
||||
MMAL_CLOCK_UPDATE_THRESHOLD_T *threshold)
|
||||
{
|
||||
return mmal_clock_update_threshold_get(port->priv->clock->clock, threshold);
|
||||
}
|
||||
|
||||
/* Set the clock port's discontinuity threshold */
|
||||
MMAL_STATUS_T mmal_port_clock_discont_threshold_set(MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_DISCONT_THRESHOLD_T *threshold)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
status = mmal_clock_discont_threshold_set(port->priv->clock->clock, threshold);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (port->priv->clock->is_reference)
|
||||
status = mmal_port_clock_forward_discont_threshold(port, threshold);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Get the clock port's discontinuity threshold */
|
||||
MMAL_STATUS_T mmal_port_clock_discont_threshold_get(MMAL_PORT_T *port,
|
||||
MMAL_CLOCK_DISCONT_THRESHOLD_T *threshold)
|
||||
{
|
||||
return mmal_clock_discont_threshold_get(port->priv->clock->clock, threshold);
|
||||
}
|
||||
|
||||
/* Set the clock port's request threshold */
|
||||
MMAL_STATUS_T mmal_port_clock_request_threshold_set(MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_REQUEST_THRESHOLD_T *threshold)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
status = mmal_clock_request_threshold_set(port->priv->clock->clock, threshold);
|
||||
if (status != MMAL_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (port->priv->clock->is_reference)
|
||||
status = mmal_port_clock_forward_request_threshold(port, threshold);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Get the clock port's request threshold */
|
||||
MMAL_STATUS_T mmal_port_clock_request_threshold_get(MMAL_PORT_T *port,
|
||||
MMAL_CLOCK_REQUEST_THRESHOLD_T *threshold)
|
||||
{
|
||||
return mmal_clock_request_threshold_get(port->priv->clock->clock, threshold);
|
||||
}
|
||||
|
||||
/* Provide input buffer information */
|
||||
void mmal_port_clock_input_buffer_info(MMAL_PORT_T *port, const MMAL_CLOCK_BUFFER_INFO_T *info)
|
||||
{
|
||||
if (port->priv->clock->buffer_info_reporting)
|
||||
mmal_port_clock_forward_input_buffer_info(port, info);
|
||||
}
|
||||
|
||||
/* Provide output buffer information */
|
||||
void mmal_port_clock_output_buffer_info(MMAL_PORT_T *port, const MMAL_CLOCK_BUFFER_INFO_T *info)
|
||||
{
|
||||
if (port->priv->clock->buffer_info_reporting)
|
||||
mmal_port_clock_forward_output_buffer_info(port, info);
|
||||
}
|
||||
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_PORT_PRIVATE_H
|
||||
#define MMAL_PORT_PRIVATE_H
|
||||
|
||||
#include "interface/mmal/mmal.h"
|
||||
#include "interface/mmal/mmal_clock.h"
|
||||
#include "interface/mmal/core/mmal_events_private.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Definition of a port. */
|
||||
typedef struct MMAL_PORT_PRIVATE_T
|
||||
{
|
||||
/** Pointer to the private data of the core */
|
||||
struct MMAL_PORT_PRIVATE_CORE_T *core;
|
||||
/** Pointer to the private data of the module in use */
|
||||
struct MMAL_PORT_MODULE_T *module;
|
||||
/** Pointer to the private data used by clock ports */
|
||||
struct MMAL_PORT_CLOCK_T *clock;
|
||||
|
||||
MMAL_STATUS_T (*pf_set_format)(MMAL_PORT_T *port);
|
||||
MMAL_STATUS_T (*pf_enable)(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T);
|
||||
MMAL_STATUS_T (*pf_disable)(MMAL_PORT_T *port);
|
||||
MMAL_STATUS_T (*pf_send)(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *);
|
||||
MMAL_STATUS_T (*pf_flush)(MMAL_PORT_T *port);
|
||||
MMAL_STATUS_T (*pf_parameter_set)(MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param);
|
||||
MMAL_STATUS_T (*pf_parameter_get)(MMAL_PORT_T *port, MMAL_PARAMETER_HEADER_T *param);
|
||||
MMAL_STATUS_T (*pf_connect)(MMAL_PORT_T *port, MMAL_PORT_T *other_port);
|
||||
|
||||
uint8_t *(*pf_payload_alloc)(MMAL_PORT_T *port, uint32_t payload_size);
|
||||
void (*pf_payload_free)(MMAL_PORT_T *port, uint8_t *payload);
|
||||
|
||||
} MMAL_PORT_PRIVATE_T;
|
||||
|
||||
/** Callback called by components when a \ref MMAL_BUFFER_HEADER_T needs to be sent back to the
|
||||
* user */
|
||||
void mmal_port_buffer_header_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
|
||||
|
||||
/** Callback called by components when an event \ref MMAL_BUFFER_HEADER_T needs to be sent to the
|
||||
* user. Events differ from ordinary buffer headers because they originate from the component
|
||||
* and do not return data from the client to the component. */
|
||||
void mmal_port_event_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
|
||||
|
||||
/** Allocate a port structure */
|
||||
MMAL_PORT_T *mmal_port_alloc(MMAL_COMPONENT_T *, MMAL_PORT_TYPE_T type, unsigned int extra_size);
|
||||
/** Free a port structure */
|
||||
void mmal_port_free(MMAL_PORT_T *port);
|
||||
/** Allocate an array of ports */
|
||||
MMAL_PORT_T **mmal_ports_alloc(MMAL_COMPONENT_T *, unsigned int ports_num, MMAL_PORT_TYPE_T type,
|
||||
unsigned int extra_size);
|
||||
/** Free an array of ports */
|
||||
void mmal_ports_free(MMAL_PORT_T **ports, unsigned int ports_num);
|
||||
|
||||
/** Acquire a reference on a port */
|
||||
void mmal_port_acquire(MMAL_PORT_T *port);
|
||||
|
||||
/** Release a reference on a port */
|
||||
MMAL_STATUS_T mmal_port_release(MMAL_PORT_T *port);
|
||||
|
||||
/** Pause processing on a port */
|
||||
MMAL_STATUS_T mmal_port_pause(MMAL_PORT_T *port, MMAL_BOOL_T pause);
|
||||
|
||||
/** Returns whether a port is connected or not */
|
||||
MMAL_BOOL_T mmal_port_is_connected(MMAL_PORT_T *port);
|
||||
|
||||
/*****************************************************************************
|
||||
* Clock Port API
|
||||
*****************************************************************************/
|
||||
/** Definition of a clock port event callback.
|
||||
* Used to inform the client of a clock event that has occurred.
|
||||
*
|
||||
* @param port The clock port where the event occurred
|
||||
* @param event The event that has occurred
|
||||
*/
|
||||
typedef void (*MMAL_PORT_CLOCK_EVENT_CB)(MMAL_PORT_T *port, const MMAL_CLOCK_EVENT_T *event);
|
||||
|
||||
/** Allocate a clock port.
|
||||
*
|
||||
* @param component The component requesting the alloc
|
||||
* @param extra_size Size of the port module
|
||||
* @param event_cb Clock event callback
|
||||
*
|
||||
* @return Pointer to new clock port or NULL on failure.
|
||||
*/
|
||||
MMAL_PORT_T* mmal_port_clock_alloc(MMAL_COMPONENT_T *component, unsigned int extra_size,
|
||||
MMAL_PORT_CLOCK_EVENT_CB event_cb);
|
||||
|
||||
/** Free a clock port.
|
||||
*
|
||||
* @param port The clock port to free
|
||||
*/
|
||||
void mmal_port_clock_free(MMAL_PORT_T *port);
|
||||
|
||||
/** Allocate an array of clock ports.
|
||||
*
|
||||
* @param component The component requesting the alloc
|
||||
* @param ports_num Number of ports to allocate
|
||||
* @param extra_size Size of the port module
|
||||
* @param event_cb Clock event callback
|
||||
*
|
||||
* @return Pointer to a new array of clock ports or NULL on failure.
|
||||
*/
|
||||
MMAL_PORT_T **mmal_ports_clock_alloc(MMAL_COMPONENT_T *component, unsigned int ports_num,
|
||||
unsigned int extra_size, MMAL_PORT_CLOCK_EVENT_CB event_cb);
|
||||
|
||||
/** Free an array of clock ports.
|
||||
*
|
||||
* @param ports The clock ports to free
|
||||
* @param ports_num Number of ports to free
|
||||
*/
|
||||
void mmal_ports_clock_free(MMAL_PORT_T **ports, unsigned int ports_num);
|
||||
|
||||
/** Definition of a clock port request callback.
|
||||
* This is invoked when the media-time requested by the client is reached.
|
||||
*
|
||||
* @param port The clock port which serviced the request
|
||||
* @param media_time The current media-time
|
||||
* @param cb_data Client-supplied data
|
||||
*/
|
||||
typedef void (*MMAL_PORT_CLOCK_REQUEST_CB)(MMAL_PORT_T *port, int64_t media_time, void *cb_data);
|
||||
|
||||
/** Register a request with the clock port.
|
||||
* When the specified media-time is reached, the clock port will invoke the supplied callback.
|
||||
*
|
||||
* @param port The clock port
|
||||
* @param media_time The media-time at which the callback should be invoked (microseconds)
|
||||
* @param cb Callback to invoke
|
||||
* @param cb_data Client-supplied callback data
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_clock_request_add(MMAL_PORT_T *port, int64_t media_time,
|
||||
MMAL_PORT_CLOCK_REQUEST_CB cb, void *cb_data);
|
||||
|
||||
/** Remove all previously registered clock port requests.
|
||||
*
|
||||
* @param port The clock port
|
||||
*
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_clock_request_flush(MMAL_PORT_T *port);
|
||||
|
||||
/** Get/set the clock port's reference state */
|
||||
MMAL_STATUS_T mmal_port_clock_reference_set(MMAL_PORT_T *port, MMAL_BOOL_T reference);
|
||||
MMAL_BOOL_T mmal_port_clock_reference_get(MMAL_PORT_T *port);
|
||||
|
||||
/** Get/set the clock port's active state */
|
||||
MMAL_STATUS_T mmal_port_clock_active_set(MMAL_PORT_T *port, MMAL_BOOL_T active);
|
||||
MMAL_BOOL_T mmal_port_clock_active_get(MMAL_PORT_T *port);
|
||||
|
||||
/** Get/set the clock port's scale */
|
||||
MMAL_STATUS_T mmal_port_clock_scale_set(MMAL_PORT_T *port, MMAL_RATIONAL_T scale);
|
||||
MMAL_RATIONAL_T mmal_port_clock_scale_get(MMAL_PORT_T *port);
|
||||
|
||||
/** Get/set the clock port's media-time */
|
||||
MMAL_STATUS_T mmal_port_clock_media_time_set(MMAL_PORT_T *port, int64_t media_time);
|
||||
int64_t mmal_port_clock_media_time_get(MMAL_PORT_T *port);
|
||||
|
||||
/** Get/set the clock port's update threshold */
|
||||
MMAL_STATUS_T mmal_port_clock_update_threshold_set(MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_UPDATE_THRESHOLD_T *threshold);
|
||||
MMAL_STATUS_T mmal_port_clock_update_threshold_get(MMAL_PORT_T *port,
|
||||
MMAL_CLOCK_UPDATE_THRESHOLD_T *threshold);
|
||||
|
||||
/** Get/set the clock port's discontinuity threshold */
|
||||
MMAL_STATUS_T mmal_port_clock_discont_threshold_set(MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_DISCONT_THRESHOLD_T *threshold);
|
||||
MMAL_STATUS_T mmal_port_clock_discont_threshold_get(MMAL_PORT_T *port,
|
||||
MMAL_CLOCK_DISCONT_THRESHOLD_T *threshold);
|
||||
|
||||
/** Get/set the clock port's request threshold */
|
||||
MMAL_STATUS_T mmal_port_clock_request_threshold_set(MMAL_PORT_T *port,
|
||||
const MMAL_CLOCK_REQUEST_THRESHOLD_T *threshold);
|
||||
MMAL_STATUS_T mmal_port_clock_request_threshold_get(MMAL_PORT_T *port,
|
||||
MMAL_CLOCK_REQUEST_THRESHOLD_T *threshold);
|
||||
|
||||
/** Provide information regarding a buffer received on the component's input/output port */
|
||||
void mmal_port_clock_input_buffer_info(MMAL_PORT_T *port, const MMAL_CLOCK_BUFFER_INFO_T *info);
|
||||
void mmal_port_clock_output_buffer_info(MMAL_PORT_T *port, const MMAL_CLOCK_BUFFER_INFO_T *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_PORT_PRIVATE_H */
|
@ -1,166 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "mmal_queue.h"
|
||||
|
||||
/** Definition of the QUEUE */
|
||||
struct MMAL_QUEUE_T
|
||||
{
|
||||
VCOS_MUTEX_T lock;
|
||||
unsigned int length;
|
||||
MMAL_BUFFER_HEADER_T *first;
|
||||
MMAL_BUFFER_HEADER_T **last;
|
||||
VCOS_SEMAPHORE_T semaphore;
|
||||
};
|
||||
|
||||
/** Create a QUEUE of MMAL_BUFFER_HEADER_T */
|
||||
MMAL_QUEUE_T *mmal_queue_create(void)
|
||||
{
|
||||
MMAL_QUEUE_T *queue;
|
||||
|
||||
queue = vcos_malloc(sizeof(*queue), "MMAL queue");
|
||||
if(!queue) return 0;
|
||||
|
||||
if(vcos_mutex_create(&queue->lock, "MMAL queue lock") != VCOS_SUCCESS )
|
||||
{
|
||||
vcos_free(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(vcos_semaphore_create(&queue->semaphore, "MMAL queue sema", 0) != VCOS_SUCCESS )
|
||||
{
|
||||
vcos_mutex_delete(&queue->lock);
|
||||
vcos_free(queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* gratuitous lock for coverity */ vcos_mutex_lock(&queue->lock);
|
||||
queue->length = 0;
|
||||
queue->first = 0;
|
||||
queue->last = &queue->first;
|
||||
/* gratuitous unlock for coverity */ vcos_mutex_unlock(&queue->lock);
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
/** Put a MMAL_BUFFER_HEADER_T into a QUEUE */
|
||||
void mmal_queue_put(MMAL_QUEUE_T *queue, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
if(!queue || !buffer) return;
|
||||
|
||||
vcos_mutex_lock(&queue->lock);
|
||||
queue->length++;
|
||||
*queue->last = buffer;
|
||||
buffer->next = 0;
|
||||
queue->last = &buffer->next;
|
||||
vcos_semaphore_post(&queue->semaphore);
|
||||
vcos_mutex_unlock(&queue->lock);
|
||||
}
|
||||
|
||||
/** Put a MMAL_BUFFER_HEADER_T back at the start of a QUEUE. */
|
||||
void mmal_queue_put_back(MMAL_QUEUE_T *queue, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
if(!queue || !buffer) return;
|
||||
|
||||
vcos_mutex_lock(&queue->lock);
|
||||
queue->length++;
|
||||
buffer->next = queue->first;
|
||||
queue->first = buffer;
|
||||
if(queue->last == &queue->first) queue->last = &buffer->next;
|
||||
vcos_semaphore_post(&queue->semaphore);
|
||||
vcos_mutex_unlock(&queue->lock);
|
||||
}
|
||||
|
||||
/** Get a MMAL_BUFFER_HEADER_T from a QUEUE. */
|
||||
MMAL_BUFFER_HEADER_T *mmal_queue_get(MMAL_QUEUE_T *queue)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
if(!queue) return 0;
|
||||
|
||||
vcos_mutex_lock(&queue->lock);
|
||||
buffer = queue->first;
|
||||
if(!buffer)
|
||||
{
|
||||
vcos_mutex_unlock(&queue->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* coverity[lock] This semaphore isn't being used as a mutex */
|
||||
vcos_semaphore_wait(&queue->semaphore); /* Will always succeed */
|
||||
|
||||
queue->first = buffer->next;
|
||||
if(!queue->first) queue->last = &queue->first;
|
||||
|
||||
queue->length--;
|
||||
vcos_mutex_unlock(&queue->lock);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/** Wait for a MMAL_BUFFER_HEADER_T from a QUEUE. */
|
||||
MMAL_BUFFER_HEADER_T *mmal_queue_wait(MMAL_QUEUE_T *queue)
|
||||
{
|
||||
if(!queue) return 0;
|
||||
|
||||
vcos_semaphore_wait(&queue->semaphore);
|
||||
vcos_semaphore_post(&queue->semaphore);
|
||||
return mmal_queue_get(queue);
|
||||
}
|
||||
|
||||
MMAL_BUFFER_HEADER_T *mmal_queue_timedwait(MMAL_QUEUE_T *queue, VCOS_UNSIGNED timeout)
|
||||
{
|
||||
int ret = 0;
|
||||
if (!queue)
|
||||
return NULL;
|
||||
|
||||
ret = vcos_semaphore_wait_timeout(&queue->semaphore, timeout);
|
||||
|
||||
if (ret != VCOS_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
vcos_semaphore_post(&queue->semaphore);
|
||||
return mmal_queue_get(queue);
|
||||
}
|
||||
|
||||
/** Get the number of MMAL_BUFFER_HEADER_T currently in a QUEUE */
|
||||
unsigned int mmal_queue_length(MMAL_QUEUE_T *queue)
|
||||
{
|
||||
if(!queue) return 0;
|
||||
|
||||
return queue->length;
|
||||
}
|
||||
|
||||
/** Destroy a queue of MMAL_BUFFER_HEADER_T */
|
||||
void mmal_queue_destroy(MMAL_QUEUE_T *queue)
|
||||
{
|
||||
if(!queue) return;
|
||||
vcos_mutex_delete(&queue->lock);
|
||||
vcos_semaphore_delete(&queue->semaphore);
|
||||
vcos_free(queue);
|
||||
}
|
@ -1,390 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Multi-Media Abstraction Layer API
|
||||
*/
|
||||
|
||||
#ifndef MMAL_H
|
||||
#define MMAL_H
|
||||
|
||||
/**
|
||||
*
|
||||
* \mainpage Multi-Media Abstraction Layer (MMAL). Draft Version 0.1.
|
||||
*
|
||||
* \par Contents
|
||||
* - \ref intro_sec
|
||||
* - \ref features
|
||||
* - \ref concepts
|
||||
* - \ref comp
|
||||
* - \ref create
|
||||
* - \ref port
|
||||
* - \ref buf
|
||||
* - \ref metadata
|
||||
* - \ref queue
|
||||
* - \ref pool
|
||||
* - \ref param
|
||||
* - \ref events
|
||||
* - \ref version
|
||||
* - \ref example
|
||||
*
|
||||
* \section intro_sec Introduction
|
||||
*
|
||||
* MMAL (Multi-Media Abstraction Layer) is a framework which is used to provide a host-side,
|
||||
* simple and relatively low-level interface to multimedia components running on VideoCore.
|
||||
* It also provides a component interface so that new components can be easily created and
|
||||
* integrated into the framework.
|
||||
*
|
||||
* There is no requirement that all the components be running on VideoCore as MMAL doesn't
|
||||
* put any restriction on where components live. The current implementation for instance
|
||||
* provides some components which can be run on both host-side or VideoCore (e.g. the splitter
|
||||
* component).
|
||||
*
|
||||
* \section features Features
|
||||
*
|
||||
* The MMAL API has been designed to support all the following features:
|
||||
* - Sufficiently generic to support different kinds of multimedia component.
|
||||
* - Simple to use from client side (mostly synchronous except where it matters).
|
||||
* - Straightforward API for designing components (e.g. avoids multiple data paths, as found in RIL).
|
||||
* - Allows for fully-optimised implementation of components (e.g. zero-copy buffer passing).
|
||||
* - Portability (API is self-contained).
|
||||
* - Supports multiple instances (e.g. of VideoCore).
|
||||
* - Extensible without breaking source or binary backward compatibility.
|
||||
*
|
||||
* \section concepts API concepts
|
||||
*
|
||||
* The MMAL API is based on the concept of components, ports and buffer headers.
|
||||
* Clients create MMAL components which expose ports for each individual
|
||||
* elementary stream of data they support (e.g. audio/video). Components expose
|
||||
* input ports to receive data from the client, and expose output ports
|
||||
* to return data to the client.
|
||||
*
|
||||
* Data sent to or received from the component needs to be attached to a buffer header.
|
||||
* Buffer headers are necessary because they contain buffer specific ancillary data which is
|
||||
* necessary for the component and client to do their processing (e.g timestamps).
|
||||
*
|
||||
* \section comp Components
|
||||
*
|
||||
* MMAL lets clients create multi-media components (video encoders,
|
||||
* video decoders, camera, and so-on) using a common API. Clients exchange
|
||||
* data with components using buffer headers. A buffer header
|
||||
* has a pointer to the payload data and optional metadata.
|
||||
* Buffer headers are sent to and received from ports that are provided by components.
|
||||
*
|
||||
* A typical decoder component would have a single input port and a
|
||||
* single output port, but the same architecture could also be used
|
||||
* for components with different layouts (e.g. a camera with a
|
||||
* capture and preview port, or a debugging component with just an input port).
|
||||
*
|
||||
* \subsection create Component Creation
|
||||
*
|
||||
* Each component is identified by a unique name. To create a specific component
|
||||
* the client needs to call \ref mmal_component_create with the desired component's
|
||||
* name as an argument.
|
||||
* This call will return a context (\ref MMAL_COMPONENT_T) to the component. This
|
||||
* context will expose the input and output ports (\ref MMAL_PORT_T) supported
|
||||
* by this specific component.
|
||||
*
|
||||
* \note All VideoCore components have a name starting with the "vc." prefix (this prefix
|
||||
* is used to distinguish when a creation request needs to be forwarded to VideoCore).
|
||||
*
|
||||
* \section port Component Ports
|
||||
*
|
||||
* A port (\ref MMAL_PORT_T) is the entity which exposes an elementary stream
|
||||
* (\ref MMAL_ES_FORMAT_T) on a component. It is also the entity to which buffer headers
|
||||
* (\ref MMAL_BUFFER_HEADER_T) are sent or from which they are received.
|
||||
*
|
||||
* Clients do not need to create ports. They are created automatically by
|
||||
* the component when this one is created but the format of a port might need to
|
||||
* be set by the client depending on the type of component the client is using.
|
||||
*
|
||||
* For example, for a video decoding component, one input port and one output port
|
||||
* will be available. The format of the input port must be set by the
|
||||
* client (using \ref mmal_port_format_commit) while the format of the output port
|
||||
* will be automatically set by the component once the component has enough information
|
||||
* to find out what its format should be.
|
||||
*
|
||||
* If the input port format contains enough information for the component to determine
|
||||
* the format of the output port straight away, then the output port will be set to the proper
|
||||
* format when \ref mmal_port_format_commit returns. Otherwise the output format will be set to
|
||||
* \ref MMAL_ENCODING_UNKNOWN until the component is fed enough data to determine the format
|
||||
* of the output port.
|
||||
* When this happens, the client will receive an event on the output port, signalling
|
||||
* that its format has changed.
|
||||
*
|
||||
* \section buf Buffer Headers
|
||||
*
|
||||
* Buffer headers (\ref MMAL_BUFFER_HEADER_T) are used to exchange data with components.
|
||||
* They do not contain the data directly but instead contain a pointer to the data being
|
||||
* transferred.
|
||||
*
|
||||
* Separating the buffer headers from the payload means that the memory for the data can
|
||||
* be allocated outside of MMAL (e.g. if it is supplied by an external library) while still
|
||||
* providing a consistent way to exchange data between clients and components.
|
||||
*
|
||||
* Buffer headers are allocated from pools and are reference counted. The refcount
|
||||
* will drop when \ref mmal_buffer_header_release is called and the buffer header
|
||||
* will be recycled to its pool when it reaches zero.
|
||||
* The client can be notified when the buffer header is recycled so that it can recycle the
|
||||
* associated payload memory as well.
|
||||
*
|
||||
* A pool of buffer headers should be created after committing the format of the port. When
|
||||
* the format is changed, the minimum and recommended size and number of buffers may change.
|
||||
*
|
||||
* \note The current number of buffers and their size (\ref MMAL_PORT_T::buffer_num and \ref
|
||||
* MMAL_PORT_T::buffer_size) are not modified by MMAL, and must be updated by the client as
|
||||
* required after changes to a port's format.
|
||||
*
|
||||
* \subsection metadata Buffer Metadata
|
||||
*
|
||||
* The API provides a way for clients or components to associate metadata with buffer headers.
|
||||
* A camera component could for example store information like exposure time or focal length
|
||||
* as metadata within the buffer header containing the frame just captured.
|
||||
* \note This area needs more work
|
||||
*
|
||||
* \subsection queue Queues of Buffer Headers
|
||||
*
|
||||
* Queues (\ref MMAL_QUEUE_T) are a facility that allows thread-safe processing of buffer headers
|
||||
* from the client. Callbacks triggered by a MMAL component when it sends a buffer header to the
|
||||
* client can simply put the buffer in a queue and let the main processing thread of the client
|
||||
* get its data from the queue.
|
||||
*
|
||||
* \subsection pool Pools of Buffer Headers
|
||||
*
|
||||
* Pools (\ref MMAL_POOL_T) let clients allocate a fixed number of buffer headers, and
|
||||
* a queue (\ref MMAL_QUEUE_T). They are used for buffer header allocation.
|
||||
* Optionally a pool can also allocate the payload memory for the client.
|
||||
*
|
||||
* Pools can also be resized after creation, for example, if the port format is changed leading
|
||||
* to a new number or size of buffers being required.
|
||||
*
|
||||
* \section param Port Parameters
|
||||
*
|
||||
* Components support setting and getting component specific parameters using
|
||||
* \ref mmal_port_parameter_set and \ref mmal_port_parameter_get. Parameters
|
||||
* are identified using an integer index; parameter data is binary. See the \ref MMAL_PARAMETER_IDS
|
||||
* "Pre-defined MMAL parameter IDs" page for more information on the pre-defined parameters.
|
||||
*
|
||||
* \section events Port Events
|
||||
*
|
||||
* Components can generate events on their ports. Events are sent to clients
|
||||
* as buffer headers and thus when the client receives a buffer header on one
|
||||
* of the component's port it should check if the buffer header is an event
|
||||
* and in which case process it and then release it (\ref mmal_buffer_header_release).
|
||||
* The reason for transmitting events in-band with the actual data is that it
|
||||
* is often very valuable to know exactly when the event happens relative to the
|
||||
* the actual data (e.g. with a focus event, from which video frame are we in focus).\n
|
||||
* Buffer headers used to transmit events are allocated internally by the framework
|
||||
* so it is important to release the buffer headers with \ref mmal_buffer_header_release
|
||||
* so the buffer headers make it back to their actual owner.
|
||||
*
|
||||
* Event buffer headers are allocated when the component is created, based on the
|
||||
* minimum number and size of control port buffers set by the component. Component
|
||||
* wide events (not port specific) are sent to the control port callback when that
|
||||
* port is enabled. Port events are sent to the port callback, the same as data
|
||||
* buffers, but the 'cmd' field is non-zero.
|
||||
*
|
||||
* \section version Versioning
|
||||
*
|
||||
* The API requires that the MMAL core be the same or more recent version
|
||||
* as the components and clients. Clients and components can be older and
|
||||
* the API will still work both at compile-time and run-time.
|
||||
*
|
||||
* \section example Example Code
|
||||
*
|
||||
* The following code is a simple example on how to do video decoding using MMAL. Note that
|
||||
* the code is intended to be clear and illustrate how to use MMAL at its most fundamental
|
||||
* level, not necessarily the most efficient way to achieve the same result. Use of opaque
|
||||
* images, tunneling and zero-copy inter-processor buffers can all improve the performance
|
||||
* or reduce the load.
|
||||
*
|
||||
* The \ref MmalConnectionUtility "Port Connection Utility" functions can also be used to
|
||||
* replace much of the common "boilerplate" code, especially when a pipeline of several
|
||||
* components needs to be processed.
|
||||
*
|
||||
* \code
|
||||
* #include <mmal.h>
|
||||
* ...
|
||||
* static void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
* {
|
||||
* // The decoder is done with the data, just recycle the buffer header into its pool
|
||||
* mmal_buffer_header_release(buffer);
|
||||
* }
|
||||
* static void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
* {
|
||||
* MMAL_QUEUE_T *queue = (MMAL_QUEUE_T *)port->userdata;
|
||||
* mmal_queue_put(queue, buffer); // Queue the decoded video frame
|
||||
* }
|
||||
* ...
|
||||
*
|
||||
* MMAL_COMPONENT_T *decoder = 0;
|
||||
* MMAL_STATUS_T status;
|
||||
*
|
||||
* // Create the video decoder component on VideoCore
|
||||
* status = mmal_component_create("vc.ril.video_decoder", &decoder);
|
||||
* ABORT_IF_ERROR(status);
|
||||
*
|
||||
* // Set format of video decoder input port
|
||||
* MMAL_ES_FORMAT_T *format_in = decoder->input[0]->format;
|
||||
* format_in->type = MMAL_ES_TYPE_VIDEO;
|
||||
* format_in->encoding = MMAL_ENCODING_H264;
|
||||
* format_in->es->video.width = 1280;
|
||||
* format_in->es->video.height = 720;
|
||||
* format_in->es->video.frame_rate.num = 30;
|
||||
* format_in->es->video.frame_rate.den = 1;
|
||||
* format_in->es->video.par.num = 1;
|
||||
* format_in->es->video.par.den = 1;
|
||||
* format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED;
|
||||
* status = mmal_format_extradata_alloc(format_in, YOUR_H264_CODEC_HEADER_BYTES_SIZE);
|
||||
* ABORT_IF_ERROR(status);
|
||||
* format_in->extradata_size = YOUR_H264_CODEC_HEADER_BYTES_SIZE;
|
||||
* memcpy(format_in->extradata, YOUR_H264_CODEC_HEADER_BYTES, format_in->extradata_size);
|
||||
*
|
||||
* status = mmal_port_format_commit(decoder->input[0]);
|
||||
* ABORT_IF_ERROR(status);
|
||||
*
|
||||
* // Once the call to mmal_port_format_commit() on the input port returns, the decoder will
|
||||
* // have set the format of the output port.
|
||||
* // If the decoder still doesn t have enough information to determine the format of the
|
||||
* // output port, the encoding will be set to unknown. As soon as the decoder receives
|
||||
* // enough stream data to determine the format of the output port it will send an event
|
||||
* // to the client to signal that the format of the port has changed.
|
||||
* // However, for the sake of simplicity this example assumes that the decoder was given
|
||||
* // all the necessary information right at the start (i.e. video format and codec header bytes)
|
||||
* MMAL_FORMAT_T *format_out = decoder->output[0]->format;
|
||||
* if (format_out->encoding == MMAL_ENCODING_UNKNOWN)
|
||||
* ABORT();
|
||||
*
|
||||
* // Now we know the format of both ports and the requirements of the decoder, we can create
|
||||
* // our buffer headers and their associated memory buffers. We use the buffer pool API for this.
|
||||
* decoder->input[0]->buffer_num = decoder->input[0]->buffer_num_min;
|
||||
* decoder->input[0]->buffer_size = decoder->input[0]->buffer_size_min;
|
||||
* MMAL_POOL_T *pool_in = mmal_pool_create(decoder->input[0]->buffer_num,
|
||||
* decoder->input[0]->buffer_size);
|
||||
* decoder->output[0]->buffer_num = decoder->output[0]->buffer_num_min;
|
||||
* decoder->output[0]->buffer_size = decoder->output[0]->buffer_size_min;
|
||||
* MMAL_POOL_T *pool_out = mmal_pool_create(decoder->output[0]->buffer_num,
|
||||
* decoder->output[0]->buffer_size);
|
||||
*
|
||||
* // Create a queue to store our decoded video frames. The callback we will get when
|
||||
* // a frame has been decoded will put the frame into this queue.
|
||||
* MMAL_QUEUE_T *queue_decoded_frames = mmal_queue_create();
|
||||
* decoder->output[0]->userdata = (void)queue_decoded_frames;
|
||||
*
|
||||
* // Enable all the input port and the output port.
|
||||
* // The callback specified here is the function which will be called when the buffer header
|
||||
* // we sent to the component has been processed.
|
||||
* status = mmal_port_enable(decoder->input[0], input_callback);
|
||||
* ABORT_IF_ERROR(status);
|
||||
* status = mmal_port_enable(decoder->output[0], output_callback);
|
||||
* ABORT_IF_ERROR(status);
|
||||
*
|
||||
* // Enable the component. Components will only process data when they are enabled.
|
||||
* status = mmal_component_enable(decoder);
|
||||
* ABORT_IF_ERROR(status);
|
||||
*
|
||||
* // Data processing loop
|
||||
* while (1)
|
||||
* {
|
||||
* MMAL_BUFFER_HEADER_T *header;
|
||||
*
|
||||
* // The client needs to implement its own blocking code.
|
||||
* // (e.g. a semaphore which is posted when a buffer header is put in one of the queues)
|
||||
* WAIT_FOR_QUEUES_TO_HAVE_BUFFERS();
|
||||
*
|
||||
* // Send empty buffers to the output port of the decoder to allow the decoder to start
|
||||
* // producing frames as soon as it gets input data
|
||||
* while ((buffer = mmal_queue_get(pool_out->queue)) != NULL)
|
||||
* {
|
||||
* status = mmal_port_send_buffer(decoder->output[0], buffer);
|
||||
* ABORT_IF_ERROR(status);
|
||||
* }
|
||||
*
|
||||
* // Send data to decode to the input port of the video decoder
|
||||
* if ((buffer = mmal_queue_get(pool_in->queue)) != NULL)
|
||||
* {
|
||||
* READ_DATA_INTO_BUFFER(buffer);
|
||||
*
|
||||
* status = mmal_port_send_buffer(decoder->input[0], buffer);
|
||||
* ABORT_IF_ERROR(status);
|
||||
* }
|
||||
*
|
||||
* // Get our decoded frames. We also need to cope with events
|
||||
* // generated from the component here.
|
||||
* while ((buffer = mmal_queue_get(queue_decoded_frames)) != NULL)
|
||||
* {
|
||||
* if (buffer->cmd)
|
||||
* {
|
||||
* // This is an event. Do something with it and release the buffer.
|
||||
* mmal_buffer_header_release(buffer);
|
||||
* continue;
|
||||
* }
|
||||
*
|
||||
* // We have a frame, do something with it (why not display it for instance?).
|
||||
* // Once we're done with it, we release it. It will magically go back
|
||||
* // to its original pool so it can be reused for a new video frame.
|
||||
* mmal_buffer_header_release(buffer);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // Cleanup everything
|
||||
* mmal_component_destroy(decoder);
|
||||
* mmal_pool_destroy(pool_in);
|
||||
* mmal_pool_destroy(pool_out);
|
||||
* mmal_queue_destroy(queue_decode_frames);
|
||||
*
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
#include "mmal_common.h"
|
||||
#include "mmal_types.h"
|
||||
#include "mmal_port.h"
|
||||
#include "mmal_component.h"
|
||||
#include "mmal_parameters.h"
|
||||
#include "mmal_metadata.h"
|
||||
#include "mmal_queue.h"
|
||||
#include "mmal_pool.h"
|
||||
#include "mmal_events.h"
|
||||
|
||||
/**/
|
||||
/** \name API Version
|
||||
* The following define the version number of the API */
|
||||
/* @{ */
|
||||
/** Major version number.
|
||||
* This changes when the API breaks in a way which is not backward compatible. */
|
||||
#define MMAL_VERSION_MAJOR 0
|
||||
/** Minor version number.
|
||||
* This changes each time the API is extended in a way which is still source and
|
||||
* binary compatible. */
|
||||
#define MMAL_VERSION_MINOR 1
|
||||
|
||||
#define MMAL_VERSION (MMAL_VERSION_MAJOR << 16 | MMAL_VERSION_MINOR)
|
||||
#define MMAL_VERSION_TO_MAJOR(a) (a >> 16)
|
||||
#define MMAL_VERSION_TO_MINOR(a) (a & 0xFFFF)
|
||||
/* @} */
|
||||
|
||||
#endif /* MMAL_H */
|
@ -1,250 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_BUFFER_H
|
||||
#define MMAL_BUFFER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup MmalBufferHeader Buffer headers
|
||||
* Definition of a buffer header and its associated API.
|
||||
* Buffer headers are the basic element used to pass data and information between different
|
||||
* parts of the system. They are passed to components via ports and sent back to the client
|
||||
* using a callback mechanism.
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
/** Specific data associated with video frames */
|
||||
typedef struct {
|
||||
uint32_t planes; /**< Number of planes composing the video frame */
|
||||
uint32_t offset[4]; /**< Offsets to the different planes. These must point within the
|
||||
payload buffer */
|
||||
uint32_t pitch[4]; /**< Pitch (size in bytes of a line of a plane) of the different
|
||||
planes */
|
||||
uint32_t flags; /**< Flags describing video specific properties of a buffer header
|
||||
(see \ref videobufferheaderflags "Video buffer header flags") */
|
||||
/* TBD stereoscopic support */
|
||||
} MMAL_BUFFER_HEADER_VIDEO_SPECIFIC_T;
|
||||
|
||||
/** Type specific data that's associated with a payload buffer */
|
||||
typedef union
|
||||
{
|
||||
/** Specific data associated with video frames */
|
||||
MMAL_BUFFER_HEADER_VIDEO_SPECIFIC_T video;
|
||||
|
||||
} MMAL_BUFFER_HEADER_TYPE_SPECIFIC_T;
|
||||
|
||||
/** Definition of the buffer header structure.
|
||||
* A buffer header does not directly carry the data to be passed to a component but instead
|
||||
* it references the actual data using a pointer (and an associated length).
|
||||
* It also contains an internal area which can be used to store command or metadata to be
|
||||
* associated with the external data.
|
||||
*/
|
||||
typedef struct MMAL_BUFFER_HEADER_T
|
||||
{
|
||||
struct MMAL_BUFFER_HEADER_T *next; /**< Used to link several buffer headers together */
|
||||
|
||||
struct MMAL_BUFFER_HEADER_PRIVATE_T *priv; /**< Data private to the framework */
|
||||
|
||||
uint32_t cmd; /**< Defines what the buffer header contains. This is a FourCC
|
||||
with 0 as a special value meaning stream data */
|
||||
|
||||
uint8_t *data; /**< Pointer to the start of the payload buffer (should not be
|
||||
changed by component) */
|
||||
uint32_t alloc_size; /**< Allocated size in bytes of payload buffer */
|
||||
uint32_t length; /**< Number of bytes currently used in the payload buffer (starting
|
||||
from offset) */
|
||||
uint32_t offset; /**< Offset in bytes to the start of valid data in the payload buffer */
|
||||
|
||||
uint32_t flags; /**< Flags describing properties of a buffer header (see
|
||||
\ref bufferheaderflags "Buffer header flags") */
|
||||
|
||||
int64_t pts; /**< Presentation timestamp in microseconds. \ref MMAL_TIME_UNKNOWN
|
||||
is used when the pts is unknown. */
|
||||
int64_t dts; /**< Decode timestamp in microseconds (dts = pts, except in the case
|
||||
of video streams with B frames). \ref MMAL_TIME_UNKNOWN
|
||||
is used when the dts is unknown. */
|
||||
|
||||
/** Type specific data that's associated with a payload buffer */
|
||||
MMAL_BUFFER_HEADER_TYPE_SPECIFIC_T *type;
|
||||
|
||||
void *user_data; /**< Field reserved for use by the client */
|
||||
|
||||
} MMAL_BUFFER_HEADER_T;
|
||||
|
||||
/** \name Buffer header flags
|
||||
* \anchor bufferheaderflags
|
||||
* The following flags describe properties of a buffer header */
|
||||
/* @{ */
|
||||
/** Signals that the current payload is the end of the stream of data */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_EOS (1<<0)
|
||||
/** Signals that the start of the current payload starts a frame */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_FRAME_START (1<<1)
|
||||
/** Signals that the end of the current payload ends a frame */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_FRAME_END (1<<2)
|
||||
/** Signals that the current payload contains only complete frames (1 or more) */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_FRAME (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END)
|
||||
/** Signals that the current payload is a keyframe (i.e. self decodable) */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME (1<<3)
|
||||
/** Signals a discontinuity in the stream of data (e.g. after a seek).
|
||||
* Can be used for instance by a decoder to reset its state */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY (1<<4)
|
||||
/** Signals a buffer containing some kind of config data for the component
|
||||
* (e.g. codec config data) */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_CONFIG (1<<5)
|
||||
/** Signals an encrypted payload */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED (1<<6)
|
||||
/** Signals a buffer containing side information */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO (1<<7)
|
||||
/** Signals a buffer which is the snapshot/postview image from a stills capture */
|
||||
#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT (1<<8)
|
||||
/** Signals a buffer which contains data known to be corrupted */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED (1<<9)
|
||||
/** Signals that a buffer failed to be transmitted */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED (1<<10)
|
||||
/** Signals the output buffer won't be used, just update reference frames */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_DECODEONLY (1<<11)
|
||||
/** User flags - can be passed in and will get returned */
|
||||
#define MMAL_BUFFER_HEADER_FLAG_USER0 (1<<28)
|
||||
#define MMAL_BUFFER_HEADER_FLAG_USER1 (1<<29)
|
||||
#define MMAL_BUFFER_HEADER_FLAG_USER2 (1<<30)
|
||||
#define MMAL_BUFFER_HEADER_FLAG_USER3 (1<<31)
|
||||
/* @} */
|
||||
|
||||
/** \name Video buffer header flags
|
||||
* \anchor videobufferheaderflags
|
||||
* The following flags describe properties of a video buffer header */
|
||||
/* @{ */
|
||||
/** Signals an interlaced video frame */
|
||||
#define MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED (1<<0)
|
||||
/** Signals that the top field of the current interlaced frame should be displayed first */
|
||||
#define MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST (1<<2)
|
||||
/** Signals that the buffer should be displayed on external display if attached. */
|
||||
#define MMAL_BUFFER_HEADER_VIDEO_FLAG_DISPLAY_EXTERNAL (1<<3)
|
||||
/** Signals that contents of the buffer requires copy protection. */
|
||||
#define MMAL_BUFFER_HEADER_VIDEO_FLAG_PROTECTED (1<<4)
|
||||
/* @} */
|
||||
|
||||
/** Acquire a buffer header.
|
||||
* Acquiring a buffer header increases a reference counter on it and makes sure that the
|
||||
* buffer header won't be recycled until all the references to it are gone.
|
||||
* This is useful for instance if a component needs to return a buffer header but still needs
|
||||
* access to it for some internal processing (e.g. reference frames in video codecs).
|
||||
*
|
||||
* @param header buffer header to acquire
|
||||
*/
|
||||
void mmal_buffer_header_acquire(MMAL_BUFFER_HEADER_T *header);
|
||||
|
||||
/** Reset a buffer header.
|
||||
* Resets all header variables to default values.
|
||||
*
|
||||
* @param header buffer header to reset
|
||||
*/
|
||||
void mmal_buffer_header_reset(MMAL_BUFFER_HEADER_T *header);
|
||||
|
||||
/** Release a buffer header.
|
||||
* Releasing a buffer header will decrease its reference counter and when no more references
|
||||
* are left, the buffer header will be recycled by calling its 'release' callback function.
|
||||
*
|
||||
* If a pre-release callback is set (\ref MMAL_BH_PRE_RELEASE_CB_T), this will be invoked
|
||||
* before calling the buffer's release callback and potentially postpone buffer recycling.
|
||||
* Once pre-release is complete the buffer header is recycled with
|
||||
* \ref mmal_buffer_header_release_continue.
|
||||
*
|
||||
* @param header buffer header to release
|
||||
*/
|
||||
void mmal_buffer_header_release(MMAL_BUFFER_HEADER_T *header);
|
||||
|
||||
/** Continue the buffer header release process.
|
||||
* This should be called to complete buffer header recycling once all pre-release activity
|
||||
* has been completed.
|
||||
*
|
||||
* @param header buffer header to release
|
||||
*/
|
||||
void mmal_buffer_header_release_continue(MMAL_BUFFER_HEADER_T *header);
|
||||
|
||||
/** Buffer header pre-release callback.
|
||||
* The callback is invoked just before a buffer is released back into a
|
||||
* pool. This is used by clients who need to trigger additional actions
|
||||
* before the buffer can finally be released (e.g. wait for a bulk transfer
|
||||
* to complete).
|
||||
*
|
||||
* The callback should return TRUE if the buffer release need to be post-poned.
|
||||
*
|
||||
* @param header buffer header about to be released
|
||||
* @param userdata user-specific data
|
||||
*
|
||||
* @return TRUE if the buffer should not be released
|
||||
*/
|
||||
typedef MMAL_BOOL_T (*MMAL_BH_PRE_RELEASE_CB_T)(MMAL_BUFFER_HEADER_T *header, void *userdata);
|
||||
|
||||
/** Set a buffer header pre-release callback.
|
||||
* If the callback is NULL, the buffer will be released back into the pool
|
||||
* immediately as usual.
|
||||
*
|
||||
* @param header buffer header to associate callback with
|
||||
* @param cb pre-release callback to invoke
|
||||
* @param userdata user-specific data
|
||||
*/
|
||||
void mmal_buffer_header_pre_release_cb_set(MMAL_BUFFER_HEADER_T *header, MMAL_BH_PRE_RELEASE_CB_T cb, void *userdata);
|
||||
|
||||
/** Replicate a buffer header into another one.
|
||||
* Replicating a buffer header will not only do an exact copy of all the public fields of the
|
||||
* buffer header (including data and alloc_size), but it will also acquire a reference to the
|
||||
* source buffer header which will only be released once the replicate has been released.
|
||||
*
|
||||
* @param dest buffer header into which to replicate
|
||||
* @param src buffer header to use as the source for the replication
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_buffer_header_replicate(MMAL_BUFFER_HEADER_T *dest, MMAL_BUFFER_HEADER_T *src);
|
||||
|
||||
/** Lock the data buffer contained in the buffer header in memory.
|
||||
* This call does nothing on all platforms except VideoCore where it is needed to pin a
|
||||
* buffer in memory before any access to it.
|
||||
*
|
||||
* @param header buffer header to lock
|
||||
*/
|
||||
MMAL_STATUS_T mmal_buffer_header_mem_lock(MMAL_BUFFER_HEADER_T *header);
|
||||
|
||||
/** Unlock the data buffer contained in the buffer header.
|
||||
* This call does nothing on all platforms except VideoCore where it is needed to un-pin a
|
||||
* buffer in memory after any access to it.
|
||||
*
|
||||
* @param header buffer header to unlock
|
||||
*/
|
||||
void mmal_buffer_header_mem_unlock(MMAL_BUFFER_HEADER_T *header);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_BUFFER_H */
|
@ -1,202 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MMAL_CLOCK_H
|
||||
#define MMAL_CLOCK_H
|
||||
|
||||
#include "vcos/vcos.h"
|
||||
#include "mmal_types.h"
|
||||
#include "mmal_common.h"
|
||||
#include <cassert>
|
||||
/** \defgroup MmalClock Clock Framework
|
||||
* The MMAL clock framework provides scheduling facilities to the rest of
|
||||
* MMAL.
|
||||
*
|
||||
* The framework consists mainly of clock ports and a clock module. Client
|
||||
* applications and components interact directly with clock ports, while
|
||||
* the clock module is only used internally by clock ports.
|
||||
*
|
||||
* Clock ports ensure that the local media-time for each component is
|
||||
* synchronised across all components. This is done by passing buffers between
|
||||
* clock ports which contain clock-specific data.
|
||||
*
|
||||
* One clock port will normally act as the reference clock for the rest of the
|
||||
* system. This is usually chosen to be the clock port of the audio render
|
||||
* component, but is configurable by the client and could potentially be any
|
||||
* other clock port (or even the client application itself).
|
||||
*
|
||||
* Components that are responsible for timed delivery of frames, do so by
|
||||
* registering callback requests for a particular time-stamp with the clock
|
||||
* port. These requests are scheduled using the clock module which maintains
|
||||
* an internal media-time.
|
||||
*
|
||||
* The clock framework also provides the ability to perform playback at different
|
||||
* speeds. This is achieved with a clock scale factor which determines the speed
|
||||
* at which the media-time advances relative to real-time, with:
|
||||
* scale = 1.0 -> normal playback speed
|
||||
* scale = 0 -> playback paused
|
||||
* scale > 1.0 -> fast-forward
|
||||
* scale < 1.0 -> slow motion
|
||||
*/
|
||||
|
||||
/** Clock event magic */
|
||||
#define MMAL_CLOCK_EVENT_MAGIC MMAL_FOURCC('C','K','L','M')
|
||||
|
||||
/** Clock reference update */
|
||||
#define MMAL_CLOCK_EVENT_REFERENCE MMAL_FOURCC('C','R','E','F')
|
||||
|
||||
/** Clock state update */
|
||||
#define MMAL_CLOCK_EVENT_ACTIVE MMAL_FOURCC('C','A','C','T')
|
||||
|
||||
/** Clock scale update */
|
||||
#define MMAL_CLOCK_EVENT_SCALE MMAL_FOURCC('C','S','C','A')
|
||||
|
||||
/** Clock media-time update */
|
||||
#define MMAL_CLOCK_EVENT_TIME MMAL_FOURCC('C','T','I','M')
|
||||
|
||||
/** Clock update threshold */
|
||||
#define MMAL_CLOCK_EVENT_UPDATE_THRESHOLD MMAL_FOURCC('C','U','T','H')
|
||||
|
||||
/** Clock discontinuity threshold */
|
||||
#define MMAL_CLOCK_EVENT_DISCONT_THRESHOLD MMAL_FOURCC('C','D','T','H')
|
||||
|
||||
/** Clock request threshold */
|
||||
#define MMAL_CLOCK_EVENT_REQUEST_THRESHOLD MMAL_FOURCC('C','R','T','H')
|
||||
|
||||
/** Buffer statistics */
|
||||
#define MMAL_CLOCK_EVENT_INPUT_BUFFER_INFO MMAL_FOURCC('C','I','B','I')
|
||||
#define MMAL_CLOCK_EVENT_OUTPUT_BUFFER_INFO MMAL_FOURCC('C','O','B','I')
|
||||
|
||||
/** Clock latency setting */
|
||||
#define MMAL_CLOCK_EVENT_LATENCY MMAL_FOURCC('C','L','A','T')
|
||||
|
||||
/** Clock event not valid */
|
||||
#define MMAL_CLOCK_EVENT_INVALID 0
|
||||
|
||||
|
||||
/** Thresholds used when updating a clock's media-time */
|
||||
typedef struct MMAL_CLOCK_UPDATE_THRESHOLD_T
|
||||
{
|
||||
/** Time differences below this threshold are ignored (microseconds) */
|
||||
int64_t threshold_lower;
|
||||
|
||||
/** Time differences above this threshold reset media-time (microseconds) */
|
||||
int64_t threshold_upper;
|
||||
} MMAL_CLOCK_UPDATE_THRESHOLD_T;
|
||||
|
||||
/** Threshold for detecting a discontinuity in media-time */
|
||||
typedef struct MMAL_CLOCK_DISCONT_THRESHOLD_T
|
||||
{
|
||||
/** Threshold after which backward jumps in media-time are treated as a
|
||||
* discontinuity (microseconds) */
|
||||
int64_t threshold;
|
||||
|
||||
/** Duration in microseconds for which a discontinuity applies (wall-time) */
|
||||
int64_t duration;
|
||||
} MMAL_CLOCK_DISCONT_THRESHOLD_T;
|
||||
|
||||
/** Threshold applied to client callback requests */
|
||||
typedef struct MMAL_CLOCK_REQUEST_THRESHOLD_T
|
||||
{
|
||||
/** Frames with a media-time difference (compared to current media-time)
|
||||
* above this threshold are dropped (microseconds) */
|
||||
int64_t threshold;
|
||||
|
||||
/** Enable/disable the request threshold */
|
||||
MMAL_BOOL_T threshold_enable;
|
||||
} MMAL_CLOCK_REQUEST_THRESHOLD_T;
|
||||
|
||||
/** Structure for passing buffer information to a clock port */
|
||||
typedef struct MMAL_CLOCK_BUFFER_INFO_T
|
||||
{
|
||||
int64_t time_stamp;
|
||||
uint32_t arrival_time;
|
||||
} MMAL_CLOCK_BUFFER_INFO_T;
|
||||
|
||||
/** Clock latency settings used by the clock component */
|
||||
typedef struct MMAL_CLOCK_LATENCY_T
|
||||
{
|
||||
int64_t target; /**< target latency (microseconds) */
|
||||
int64_t attack_period; /**< duration of one attack period (microseconds) */
|
||||
int64_t attack_rate; /**< amount by which media-time will be adjusted
|
||||
every attack_period (microseconds) */
|
||||
} MMAL_CLOCK_LATENCY_T;
|
||||
|
||||
/** Clock event used to pass data between clock ports and a client. */
|
||||
typedef struct MMAL_CLOCK_EVENT_T
|
||||
{
|
||||
/** 4cc event id */
|
||||
uint32_t id;
|
||||
|
||||
/** 4cc event magic */
|
||||
uint32_t magic;
|
||||
|
||||
/** buffer associated with this event (can be NULL) */
|
||||
struct MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/** pad to 64-bit boundary */
|
||||
uint32_t padding0;
|
||||
|
||||
/** additional event data (type-specific) */
|
||||
union
|
||||
{
|
||||
/** used either for clock reference or clock state */
|
||||
MMAL_BOOL_T enable;
|
||||
|
||||
/** new clock scale */
|
||||
MMAL_RATIONAL_T scale;
|
||||
|
||||
/** new media-time */
|
||||
int64_t media_time;
|
||||
|
||||
/** media-time update threshold */
|
||||
MMAL_CLOCK_UPDATE_THRESHOLD_T update_threshold;
|
||||
|
||||
/** media-time discontinuity threshold */
|
||||
MMAL_CLOCK_DISCONT_THRESHOLD_T discont_threshold;
|
||||
|
||||
/** client callback request threshold */
|
||||
MMAL_CLOCK_REQUEST_THRESHOLD_T request_threshold;
|
||||
|
||||
/** input/output buffer information */
|
||||
MMAL_CLOCK_BUFFER_INFO_T buffer;
|
||||
|
||||
/** clock latency setting */
|
||||
MMAL_CLOCK_LATENCY_T latency;
|
||||
} data;
|
||||
|
||||
/** pad to 64-bit boundary */
|
||||
uint64_t padding1;
|
||||
} MMAL_CLOCK_EVENT_T;
|
||||
|
||||
/* Make sure MMAL_CLOCK_EVENT_T will preserve 64-bit alignment */
|
||||
static_assert(!(sizeof(MMAL_CLOCK_EVENT_T) & 0x7),"mmal error");
|
||||
|
||||
#define MMAL_CLOCK_EVENT_INIT(id) { id, MMAL_CLOCK_EVENT_MAGIC, NULL, 0, {0}, 0 }
|
||||
|
||||
#endif /* MMAL_CLOCK_H */
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file mmal_common.h
|
||||
* Multi-Media Abstraction Layer - Common definitions
|
||||
*/
|
||||
|
||||
#ifndef MMAL_COMMON_H
|
||||
#define MMAL_COMMON_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <vcos.h>
|
||||
|
||||
/* C99 64bits integers */
|
||||
#ifndef INT64_C
|
||||
# define INT64_C(value) value##LL
|
||||
# define UINT64_C(value) value##ULL
|
||||
#endif
|
||||
|
||||
#define MMAL_TSRING(s) #s
|
||||
#define MMAL_TO_STRING(s) MMAL_TSRING(s)
|
||||
|
||||
#define MMAL_COUNTOF(x) (sizeof((x))/sizeof((x)[0]))
|
||||
#define MMAL_MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#define MMAL_MAX(a,b) ((a)<(b)?(b):(a))
|
||||
|
||||
/* FIXME: should be different for big endian */
|
||||
#define MMAL_FOURCC(a,b,c,d) ((a) | (b << 8) | (c << 16) | (d << 24))
|
||||
#define MMAL_PARAM_UNUSED(a) (void)(a)
|
||||
#define MMAL_MAGIC MMAL_FOURCC('m','m','a','l')
|
||||
|
||||
typedef int32_t MMAL_BOOL_T;
|
||||
#define MMAL_FALSE 0
|
||||
#define MMAL_TRUE 1
|
||||
|
||||
typedef struct MMAL_CORE_STATISTICS_T
|
||||
{
|
||||
uint32_t buffer_count; /**< Total buffer count on this port */
|
||||
uint32_t first_buffer_time; /**< Time (us) of first buffer seen on this port */
|
||||
uint32_t last_buffer_time; /**< Time (us) of most recently buffer on this port */
|
||||
uint32_t max_delay; /**< Max delay (us) between buffers, ignoring first few frames */
|
||||
} MMAL_CORE_STATISTICS_T;
|
||||
|
||||
/** Statistics collected by the core on all ports, if enabled in the build.
|
||||
*/
|
||||
typedef struct MMAL_CORE_PORT_STATISTICS_T
|
||||
{
|
||||
MMAL_CORE_STATISTICS_T rx;
|
||||
MMAL_CORE_STATISTICS_T tx;
|
||||
} MMAL_CORE_PORT_STATISTICS_T;
|
||||
|
||||
/** Unsigned 16.16 fixed point value, also known as Q16.16 */
|
||||
typedef uint32_t MMAL_FIXED_16_16_T;
|
||||
|
||||
#endif /* MMAL_COMMON_H */
|
@ -1,148 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_COMPONENT_H
|
||||
#define MMAL_COMPONENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup MmalComponent Components
|
||||
* Definition of a MMAL component and its associated API. A component will always expose ports
|
||||
* which it uses to send and receive data in the form of buffer headers
|
||||
* (\ref MMAL_BUFFER_HEADER_T) */
|
||||
/* @{ */
|
||||
|
||||
#include "mmal_types.h"
|
||||
#include "mmal_port.h"
|
||||
|
||||
struct MMAL_COMPONENT_PRIVATE_T;
|
||||
typedef struct MMAL_COMPONENT_PRIVATE_T MMAL_COMPONENT_PRIVATE_T;
|
||||
|
||||
/** Definition of a component. */
|
||||
typedef struct MMAL_COMPONENT_T
|
||||
{
|
||||
/** Pointer to the private data of the module in use */
|
||||
struct MMAL_COMPONENT_PRIVATE_T *priv;
|
||||
|
||||
/** Pointer to private data of the client */
|
||||
struct MMAL_COMPONENT_USERDATA_T *userdata;
|
||||
|
||||
/** Component name */
|
||||
const char *name;
|
||||
|
||||
/** Specifies whether the component is enabled or not */
|
||||
uint32_t is_enabled;
|
||||
|
||||
/** All components expose a control port.
|
||||
* The control port is used by clients to set / get parameters that are global to the
|
||||
* component. It is also used to receive events, which again are global to the component.
|
||||
* To be able to receive events, the client needs to enable and register a callback on the
|
||||
* control port. */
|
||||
MMAL_PORT_T *control;
|
||||
|
||||
uint32_t input_num; /**< Number of input ports */
|
||||
MMAL_PORT_T **input; /**< Array of input ports */
|
||||
|
||||
uint32_t output_num; /**< Number of output ports */
|
||||
MMAL_PORT_T **output; /**< Array of output ports */
|
||||
|
||||
uint32_t clock_num; /**< Number of clock ports */
|
||||
MMAL_PORT_T **clock; /**< Array of clock ports */
|
||||
|
||||
uint32_t port_num; /**< Total number of ports */
|
||||
MMAL_PORT_T **port; /**< Array of all the ports (control/input/output/clock) */
|
||||
|
||||
/** Uniquely identifies the component's instance within the MMAL
|
||||
* context / process. For debugging. */
|
||||
uint32_t id;
|
||||
|
||||
} MMAL_COMPONENT_T;
|
||||
|
||||
/** Create an instance of a component.
|
||||
* The newly created component will expose ports to the client. All the exposed ports are
|
||||
* disabled by default.
|
||||
* Note that components are reference counted and creating a component automatically
|
||||
* acquires a reference to it (released when \ref mmal_component_destroy is called).
|
||||
*
|
||||
* @param name name of the component to create, e.g. "video_decode"
|
||||
* @param component returned component
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_create(const char *name,
|
||||
MMAL_COMPONENT_T **component);
|
||||
|
||||
/** Acquire a reference on a component.
|
||||
* Acquiring a reference on a component will prevent a component from being destroyed until
|
||||
* the acquired reference is released (by a call to \ref mmal_component_destroy).
|
||||
* References are internally counted so all acquired references need a matching call to
|
||||
* release them.
|
||||
*
|
||||
* @param component component to acquire
|
||||
*/
|
||||
void mmal_component_acquire(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Release a reference on a component
|
||||
* Release an acquired reference on a component. Triggers the destruction of the component when
|
||||
* the last reference is being released.
|
||||
* \note This is in fact an alias of \ref mmal_component_destroy which is added to make client
|
||||
* code clearer.
|
||||
*
|
||||
* @param component component to release
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_release(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Destroy a previously created component
|
||||
* Release an acquired reference on a component. Only actually destroys the component when
|
||||
* the last reference is being released.
|
||||
*
|
||||
* @param component component to destroy
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_destroy(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Enable processing on a component
|
||||
* @param component component to enable
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_enable(MMAL_COMPONENT_T *component);
|
||||
|
||||
/** Disable processing on a component
|
||||
* @param component component to disable
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_component_disable(MMAL_COMPONENT_T *component);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_COMPONENT_H */
|
@ -1,224 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_CONNECTION_H
|
||||
#define MMAL_CONNECTION_H
|
||||
|
||||
/** \defgroup MmalConnectionUtility Port connection utility
|
||||
* \ingroup MmalUtilities
|
||||
* The port connection utility functions can be used in place of common sequences
|
||||
* of calls to the MMAL API in order to process buffers being passed between two
|
||||
* ports.
|
||||
*
|
||||
* \section ProcessingConnectionBufferHeaders Processing connection buffer headers
|
||||
* Either in response to the client callback function being called, or simply on a
|
||||
* timer, the client will need to process the buffer headers of the connection
|
||||
* (unless tunneling is used).
|
||||
*
|
||||
* Buffer headers that are in the pool queue will need to be sent to the output port,
|
||||
* while buffer headers in the connection queue are sent to the input port. The
|
||||
* buffer headers in the connection queue may contain pixel data (the cmd field is
|
||||
* zero) or an event (the cmd field is non-zero). In general, pixel data buffer
|
||||
* headers need to be passed on, while event buffer headers are released. In the
|
||||
* case of the format changed event, mmal_connection_event_format_changed() can be
|
||||
* called before the event is released.
|
||||
*
|
||||
* Other, specialized use cases may also be implemented, such as getting and
|
||||
* immediately releasing buffer headers from the connection queue in order to
|
||||
* prevent their propagation. This could be used to drop out video, for example.
|
||||
*
|
||||
* \section TunnellingConnections Tunnelling connections
|
||||
* If the \ref MMAL_CONNECTION_FLAG_TUNNELLING flag is set when the connection is
|
||||
* created, MMAL tunneling will be used. This automates the passing of the buffer
|
||||
* headers between the output port and input port, and back again. It will also do
|
||||
* this as efficiently as possible, avoiding trips between the ARM and the VideoCore
|
||||
* if both components are implemented on the VideoCore. The consequence of this is
|
||||
* that there is no client callback made as buffer headers get transferred.
|
||||
*
|
||||
* The client can still monitor the control port of a component (usually a sink
|
||||
* component, such as video_render) for the end of stream, in order to know when to
|
||||
* dismantle the connection.
|
||||
*
|
||||
* \section ConnectionClientCallback Client callback
|
||||
* When not using tunnelling, the client callback function is called each time a
|
||||
* buffer arrives from a port (either input or output).
|
||||
*
|
||||
* \note The callback is made on a different thread from the one used by the
|
||||
* client to set up the connection, so care must be taken with thread safety.
|
||||
* One option is to raise a signal to the main client thread that queue processing
|
||||
* needs to be done, another is for the callback to perform the queue processing
|
||||
* itself.
|
||||
*
|
||||
* The client can also store an opaque pointer in the connection object, which is
|
||||
* never used by the MMAL code and is only meaningful to the client.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \name Connection flags
|
||||
* \anchor connectionflags
|
||||
* The following flags describe the properties of the connection. */
|
||||
/* @{ */
|
||||
/** The connection is tunnelled. Buffer headers do not transit via the client but
|
||||
* directly from the output port to the input port. */
|
||||
#define MMAL_CONNECTION_FLAG_TUNNELLING 0x1
|
||||
/** Force the pool of buffer headers used by the connection to be allocated on the input port. */
|
||||
#define MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT 0x2
|
||||
/** Force the pool of buffer headers used by the connection to be allocated on the output port. */
|
||||
#define MMAL_CONNECTION_FLAG_ALLOCATION_ON_OUTPUT 0x4
|
||||
/* @} */
|
||||
|
||||
/** Forward type definition for a connection */
|
||||
typedef struct MMAL_CONNECTION_T MMAL_CONNECTION_T;
|
||||
|
||||
/** Definition of the callback used by a connection to signal back to the client
|
||||
* that a buffer header is available either in the pool or in the output queue.
|
||||
*
|
||||
* @param connection Pointer to the connection
|
||||
*/
|
||||
typedef void (*MMAL_CONNECTION_CALLBACK_T)(MMAL_CONNECTION_T *connection);
|
||||
|
||||
/** Structure describing a connection between 2 ports (1 output and 1 input port) */
|
||||
struct MMAL_CONNECTION_T {
|
||||
|
||||
void *user_data; /**< Field reserved for use by the client. */
|
||||
MMAL_CONNECTION_CALLBACK_T callback; /**< Callback set by the client. */
|
||||
|
||||
uint32_t is_enabled; /**< Specifies whether the connection is enabled or not (Read Only). */
|
||||
|
||||
uint32_t flags; /**< Flags passed during the create call (Read Only). A bitwise
|
||||
* combination of \ref connectionflags "Connection flags" values.
|
||||
*/
|
||||
MMAL_PORT_T *in; /**< Input port used for the connection (Read Only). */
|
||||
MMAL_PORT_T *out; /**< Output port used for the connection (Read Only). */
|
||||
|
||||
MMAL_POOL_T *pool; /**< Pool of buffer headers used by the output port (Read Only). */
|
||||
MMAL_QUEUE_T *queue; /**< Queue for the buffer headers produced by the output port (Read Only). */
|
||||
|
||||
const char *name; /**< Connection name (Read Only). Used for debugging purposes. */
|
||||
|
||||
/* Used for debug / statistics */
|
||||
int64_t time_setup; /**< Time in microseconds taken to setup the connection. */
|
||||
int64_t time_enable; /**< Time in microseconds taken to enable the connection. */
|
||||
int64_t time_disable; /**< Time in microseconds taken to disable the connection. */
|
||||
};
|
||||
|
||||
/** Create a connection between two ports.
|
||||
* The connection shall include a pool of buffer headers suitable for the current format of
|
||||
* the output port. The format of the input port shall have been set to the same as that of
|
||||
* the input port.
|
||||
* Note that connections are reference counted and creating a connection automatically
|
||||
* acquires a reference to it (released when \ref mmal_connection_destroy is called).
|
||||
*
|
||||
* @param connection The address of a connection pointer that will be set to point to the created
|
||||
* connection.
|
||||
* @param out The output port to use for the connection.
|
||||
* @param in The input port to use for the connection.
|
||||
* @param flags The flags specifying which type of connection should be created.
|
||||
* A bitwise combination of \ref connectionflags "Connection flags" values.
|
||||
* @return MMAL_SUCCESS on success.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_connection_create(MMAL_CONNECTION_T **connection,
|
||||
MMAL_PORT_T *out, MMAL_PORT_T *in, uint32_t flags);
|
||||
|
||||
/** Acquire a reference on a connection.
|
||||
* Acquiring a reference on a connection will prevent a connection from being destroyed until
|
||||
* the acquired reference is released (by a call to \ref mmal_connection_destroy).
|
||||
* References are internally counted so all acquired references need a matching call to
|
||||
* release them.
|
||||
*
|
||||
* @param connection connection to acquire
|
||||
*/
|
||||
void mmal_connection_acquire(MMAL_CONNECTION_T *connection);
|
||||
|
||||
/** Release a reference on a connection
|
||||
* Release an acquired reference on a connection. Triggers the destruction of the connection when
|
||||
* the last reference is being released.
|
||||
* \note This is in fact an alias of \ref mmal_connection_destroy which is added to make client
|
||||
* code clearer.
|
||||
*
|
||||
* @param connection connection to release
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_connection_release(MMAL_CONNECTION_T *connection);
|
||||
|
||||
/** Destroy a connection.
|
||||
* Release an acquired reference on a connection. Only actually destroys the connection when
|
||||
* the last reference is being released.
|
||||
* The actual destruction of the connection will start by disabling it, if necessary.
|
||||
* Any pool, queue, and so on owned by the connection shall then be destroyed.
|
||||
*
|
||||
* @param connection The connection to be destroyed.
|
||||
* @return MMAL_SUCCESS on success.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_connection_destroy(MMAL_CONNECTION_T *connection);
|
||||
|
||||
/** Enable a connection.
|
||||
* The format of the two ports must have been committed before calling this function,
|
||||
* although note that on creation, the connection automatically copies and commits the
|
||||
* output port's format to the input port.
|
||||
*
|
||||
* The MMAL_CONNECTION_T::callback field must have been set if the \ref MMAL_CONNECTION_FLAG_TUNNELLING
|
||||
* flag was not specified on creation. The client may also set the MMAL_CONNECTION_T::user_data
|
||||
* in order to get a pointer passed, via the connection, to the callback.
|
||||
*
|
||||
* @param connection The connection to be enabled.
|
||||
* @return MMAL_SUCCESS on success.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_connection_enable(MMAL_CONNECTION_T *connection);
|
||||
|
||||
/** Disable a connection.
|
||||
*
|
||||
* @param connection The connection to be disabled.
|
||||
* @return MMAL_SUCCESS on success.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_connection_disable(MMAL_CONNECTION_T *connection);
|
||||
|
||||
/** Apply a format changed event to the connection.
|
||||
* This function can be used when the client is processing buffer headers and receives
|
||||
* a format changed event (\ref MMAL_EVENT_FORMAT_CHANGED). The connection is
|
||||
* reconfigured, changing the format of the ports, the number of buffer headers and
|
||||
* the size of the payload buffers as necessary.
|
||||
*
|
||||
* @param connection The connection to which the event shall be applied.
|
||||
* @param buffer The buffer containing a format changed event.
|
||||
* @return MMAL_SUCCESS on success.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_connection_event_format_changed(MMAL_CONNECTION_T *connection,
|
||||
MMAL_BUFFER_HEADER_T *buffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* MMAL_CONNECTION_H */
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_DEFAULT_COMPONENTS_H
|
||||
#define MMAL_DEFAULT_COMPONENTS_H
|
||||
|
||||
/** \defgroup MmalDefaultComponents List of default components
|
||||
* This provides a list of default components on a per platform basis.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define MMAL_COMPONENT_DEFAULT_CONTAINER_READER "container_reader"
|
||||
#define MMAL_COMPONENT_DEFAULT_CONTAINER_WRITER "container_writer"
|
||||
|
||||
#if defined(ENABLE_MMAL_STANDALONE)
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_DECODER "avcodec.video_decode"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER "avcodec.video_encode"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER "sdl.video_render"
|
||||
# define MMAL_COMPONENT_DEFAULT_IMAGE_DECODER "avcodec.video_decode"
|
||||
# define MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER "avcodec.video_encode"
|
||||
# define MMAL_COMPONENT_DEFAULT_CAMERA "artificial_camera"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_CONVERTER "avcodec.video_convert"
|
||||
# define MMAL_COMPONENT_DEFAULT_SPLITTER "splitter"
|
||||
# define MMAL_COMPONENT_DEFAULT_SCHEDULER "scheduler"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_INJECTER "video_inject"
|
||||
# define MMAL_COMPONENT_DEFAULT_AUDIO_DECODER "avcodec.audio_decode"
|
||||
# define MMAL_COMPONENT_DEFAULT_AUDIO_RENDERER "sdl.audio_render"
|
||||
# define MMAL_COMPONENT_DEFAULT_MIRACAST "miracast"
|
||||
#elif defined(__VIDEOCORE__)
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_DECODER "ril.video_decode"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER "ril.video_encode"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER "ril.video_render"
|
||||
# define MMAL_COMPONENT_DEFAULT_IMAGE_DECODER "ril.image_decode"
|
||||
# define MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER "ril.image_encode"
|
||||
# define MMAL_COMPONENT_DEFAULT_CAMERA "ril.camera"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_CONVERTER "video_convert"
|
||||
# define MMAL_COMPONENT_DEFAULT_SPLITTER "splitter"
|
||||
# define MMAL_COMPONENT_DEFAULT_SCHEDULER "scheduler"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_INJECTER "video_inject"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_SPLITTER "ril.video_splitter"
|
||||
# define MMAL_COMPONENT_DEFAULT_AUDIO_DECODER "none"
|
||||
# define MMAL_COMPONENT_DEFAULT_AUDIO_RENDERER "ril.audio_render"
|
||||
# define MMAL_COMPONENT_DEFAULT_MIRACAST "miracast"
|
||||
#else
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_DECODER "vc.ril.video_decode"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER "vc.ril.video_encode"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER "vc.ril.video_render"
|
||||
# define MMAL_COMPONENT_DEFAULT_IMAGE_DECODER "vc.ril.image_decode"
|
||||
# define MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER "vc.ril.image_encode"
|
||||
# define MMAL_COMPONENT_DEFAULT_CAMERA "vc.ril.camera"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_CONVERTER "vc.video_convert"
|
||||
# define MMAL_COMPONENT_DEFAULT_SPLITTER "vc.splitter"
|
||||
# define MMAL_COMPONENT_DEFAULT_SCHEDULER "vc.scheduler"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_INJECTER "vc.video_inject"
|
||||
# define MMAL_COMPONENT_DEFAULT_VIDEO_SPLITTER "vc.ril.video_splitter"
|
||||
# define MMAL_COMPONENT_DEFAULT_AUDIO_DECODER "none"
|
||||
# define MMAL_COMPONENT_DEFAULT_AUDIO_RENDERER "vc.ril.audio_render"
|
||||
# define MMAL_COMPONENT_DEFAULT_MIRACAST "vc.miracast"
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* MMAL_DEFAULT_COMPONENTS_H */
|
@ -1,208 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_ENCODINGS_H
|
||||
#define MMAL_ENCODINGS_H
|
||||
|
||||
#include "mmal_common.h"
|
||||
|
||||
/** \defgroup MmalEncodings List of pre-defined encodings
|
||||
* This defines a list of common encodings. This list isn't exhaustive and is only
|
||||
* provided as a convenience to avoid clients having to use FourCC codes directly.
|
||||
* However components are allowed to define and use their own FourCC codes. */
|
||||
/* @{ */
|
||||
|
||||
/** \name Pre-defined video encodings */
|
||||
/* @{ */
|
||||
#define MMAL_ENCODING_H264 MMAL_FOURCC('H','2','6','4')
|
||||
#define MMAL_ENCODING_H263 MMAL_FOURCC('H','2','6','3')
|
||||
#define MMAL_ENCODING_MP4V MMAL_FOURCC('M','P','4','V')
|
||||
#define MMAL_ENCODING_MP2V MMAL_FOURCC('M','P','2','V')
|
||||
#define MMAL_ENCODING_MP1V MMAL_FOURCC('M','P','1','V')
|
||||
#define MMAL_ENCODING_WMV3 MMAL_FOURCC('W','M','V','3')
|
||||
#define MMAL_ENCODING_WMV2 MMAL_FOURCC('W','M','V','2')
|
||||
#define MMAL_ENCODING_WMV1 MMAL_FOURCC('W','M','V','1')
|
||||
#define MMAL_ENCODING_WVC1 MMAL_FOURCC('W','V','C','1')
|
||||
#define MMAL_ENCODING_VP8 MMAL_FOURCC('V','P','8',' ')
|
||||
#define MMAL_ENCODING_VP7 MMAL_FOURCC('V','P','7',' ')
|
||||
#define MMAL_ENCODING_VP6 MMAL_FOURCC('V','P','6',' ')
|
||||
#define MMAL_ENCODING_THEORA MMAL_FOURCC('T','H','E','O')
|
||||
#define MMAL_ENCODING_SPARK MMAL_FOURCC('S','P','R','K')
|
||||
#define MMAL_ENCODING_MJPEG MMAL_FOURCC('M','J','P','G')
|
||||
|
||||
#define MMAL_ENCODING_JPEG MMAL_FOURCC('J','P','E','G')
|
||||
#define MMAL_ENCODING_GIF MMAL_FOURCC('G','I','F',' ')
|
||||
#define MMAL_ENCODING_PNG MMAL_FOURCC('P','N','G',' ')
|
||||
#define MMAL_ENCODING_PPM MMAL_FOURCC('P','P','M',' ')
|
||||
#define MMAL_ENCODING_TGA MMAL_FOURCC('T','G','A',' ')
|
||||
#define MMAL_ENCODING_BMP MMAL_FOURCC('B','M','P',' ')
|
||||
|
||||
#define MMAL_ENCODING_I420 MMAL_FOURCC('I','4','2','0')
|
||||
#define MMAL_ENCODING_I420_SLICE MMAL_FOURCC('S','4','2','0')
|
||||
#define MMAL_ENCODING_YV12 MMAL_FOURCC('Y','V','1','2')
|
||||
#define MMAL_ENCODING_I422 MMAL_FOURCC('I','4','2','2')
|
||||
#define MMAL_ENCODING_I422_SLICE MMAL_FOURCC('S','4','2','2')
|
||||
#define MMAL_ENCODING_YUYV MMAL_FOURCC('Y','U','Y','V')
|
||||
#define MMAL_ENCODING_YVYU MMAL_FOURCC('Y','V','Y','U')
|
||||
#define MMAL_ENCODING_UYVY MMAL_FOURCC('U','Y','V','Y')
|
||||
#define MMAL_ENCODING_VYUY MMAL_FOURCC('V','Y','U','Y')
|
||||
#define MMAL_ENCODING_NV12 MMAL_FOURCC('N','V','1','2')
|
||||
#define MMAL_ENCODING_NV21 MMAL_FOURCC('N','V','2','1')
|
||||
#define MMAL_ENCODING_ARGB MMAL_FOURCC('A','R','G','B')
|
||||
#define MMAL_ENCODING_RGBA MMAL_FOURCC('R','G','B','A')
|
||||
#define MMAL_ENCODING_ABGR MMAL_FOURCC('A','B','G','R')
|
||||
#define MMAL_ENCODING_BGRA MMAL_FOURCC('B','G','R','A')
|
||||
#define MMAL_ENCODING_RGB16 MMAL_FOURCC('R','G','B','2')
|
||||
#define MMAL_ENCODING_RGB24 MMAL_FOURCC('R','G','B','3')
|
||||
#define MMAL_ENCODING_RGB32 MMAL_FOURCC('R','G','B','4')
|
||||
#define MMAL_ENCODING_BGR16 MMAL_FOURCC('B','G','R','2')
|
||||
#define MMAL_ENCODING_BGR24 MMAL_FOURCC('B','G','R','3')
|
||||
#define MMAL_ENCODING_BGR32 MMAL_FOURCC('B','G','R','4')
|
||||
|
||||
/** SAND Video (YUVUV128) format, native format understood by VideoCore.
|
||||
* This format is *not* opaque - if requested you will receive full frames
|
||||
* of YUV_UV video.
|
||||
*/
|
||||
#define MMAL_ENCODING_YUVUV128 MMAL_FOURCC('S','A','N','D')
|
||||
|
||||
/** VideoCore opaque image format, image handles are returned to
|
||||
* the host but not the actual image data.
|
||||
*/
|
||||
#define MMAL_ENCODING_OPAQUE MMAL_FOURCC('O','P','Q','V')
|
||||
|
||||
/** An EGL image handle
|
||||
*/
|
||||
#define MMAL_ENCODING_EGL_IMAGE MMAL_FOURCC('E','G','L','I')
|
||||
|
||||
/* }@ */
|
||||
|
||||
/** \name Pre-defined audio encodings */
|
||||
/* @{ */
|
||||
#define MMAL_ENCODING_PCM_UNSIGNED_BE MMAL_FOURCC('P','C','M','U')
|
||||
#define MMAL_ENCODING_PCM_UNSIGNED_LE MMAL_FOURCC('p','c','m','u')
|
||||
#define MMAL_ENCODING_PCM_SIGNED_BE MMAL_FOURCC('P','C','M','S')
|
||||
#define MMAL_ENCODING_PCM_SIGNED_LE MMAL_FOURCC('p','c','m','s')
|
||||
#define MMAL_ENCODING_PCM_FLOAT_BE MMAL_FOURCC('P','C','M','F')
|
||||
#define MMAL_ENCODING_PCM_FLOAT_LE MMAL_FOURCC('p','c','m','f')
|
||||
/* Defines for native endianness */
|
||||
#ifdef MMAL_IS_BIG_ENDIAN
|
||||
#define MMAL_ENCODING_PCM_UNSIGNED MMAL_ENCODING_PCM_UNSIGNED_BE
|
||||
#define MMAL_ENCODING_PCM_SIGNED MMAL_ENCODING_PCM_SIGNED_BE
|
||||
#define MMAL_ENCODING_PCM_FLOAT MMAL_ENCODING_PCM_FLOAT_BE
|
||||
#else
|
||||
#define MMAL_ENCODING_PCM_UNSIGNED MMAL_ENCODING_PCM_UNSIGNED_LE
|
||||
#define MMAL_ENCODING_PCM_SIGNED MMAL_ENCODING_PCM_SIGNED_LE
|
||||
#define MMAL_ENCODING_PCM_FLOAT MMAL_ENCODING_PCM_FLOAT_LE
|
||||
#endif
|
||||
|
||||
#define MMAL_ENCODING_MP4A MMAL_FOURCC('M','P','4','A')
|
||||
#define MMAL_ENCODING_MPGA MMAL_FOURCC('M','P','G','A')
|
||||
#define MMAL_ENCODING_ALAW MMAL_FOURCC('A','L','A','W')
|
||||
#define MMAL_ENCODING_MULAW MMAL_FOURCC('U','L','A','W')
|
||||
#define MMAL_ENCODING_ADPCM_MS MMAL_FOURCC('M','S',0x0,0x2)
|
||||
#define MMAL_ENCODING_ADPCM_IMA_MS MMAL_FOURCC('M','S',0x0,0x1)
|
||||
#define MMAL_ENCODING_ADPCM_SWF MMAL_FOURCC('A','S','W','F')
|
||||
#define MMAL_ENCODING_WMA1 MMAL_FOURCC('W','M','A','1')
|
||||
#define MMAL_ENCODING_WMA2 MMAL_FOURCC('W','M','A','2')
|
||||
#define MMAL_ENCODING_WMAP MMAL_FOURCC('W','M','A','P')
|
||||
#define MMAL_ENCODING_WMAL MMAL_FOURCC('W','M','A','L')
|
||||
#define MMAL_ENCODING_WMAV MMAL_FOURCC('W','M','A','V')
|
||||
#define MMAL_ENCODING_AMRNB MMAL_FOURCC('A','M','R','N')
|
||||
#define MMAL_ENCODING_AMRWB MMAL_FOURCC('A','M','R','W')
|
||||
#define MMAL_ENCODING_AMRWBP MMAL_FOURCC('A','M','R','P')
|
||||
#define MMAL_ENCODING_AC3 MMAL_FOURCC('A','C','3',' ')
|
||||
#define MMAL_ENCODING_EAC3 MMAL_FOURCC('E','A','C','3')
|
||||
#define MMAL_ENCODING_DTS MMAL_FOURCC('D','T','S',' ')
|
||||
#define MMAL_ENCODING_MLP MMAL_FOURCC('M','L','P',' ')
|
||||
#define MMAL_ENCODING_FLAC MMAL_FOURCC('F','L','A','C')
|
||||
#define MMAL_ENCODING_VORBIS MMAL_FOURCC('V','O','R','B')
|
||||
#define MMAL_ENCODING_SPEEX MMAL_FOURCC('S','P','X',' ')
|
||||
#define MMAL_ENCODING_ATRAC3 MMAL_FOURCC('A','T','R','3')
|
||||
#define MMAL_ENCODING_ATRACX MMAL_FOURCC('A','T','R','X')
|
||||
#define MMAL_ENCODING_ATRACL MMAL_FOURCC('A','T','R','L')
|
||||
#define MMAL_ENCODING_MIDI MMAL_FOURCC('M','I','D','I')
|
||||
#define MMAL_ENCODING_EVRC MMAL_FOURCC('E','V','R','C')
|
||||
#define MMAL_ENCODING_NELLYMOSER MMAL_FOURCC('N','E','L','Y')
|
||||
#define MMAL_ENCODING_QCELP MMAL_FOURCC('Q','C','E','L')
|
||||
#define MMAL_ENCODING_MP4V_DIVX_DRM MMAL_FOURCC('M','4','V','D')
|
||||
/* @} */
|
||||
|
||||
/* @} MmalEncodings List */
|
||||
|
||||
/** \defgroup MmalEncodingVariants List of pre-defined encoding variants
|
||||
* This defines a list of common encoding variants. This list isn't exhaustive and is only
|
||||
* provided as a convenience to avoid clients having to use FourCC codes directly.
|
||||
* However components are allowed to define and use their own FourCC codes. */
|
||||
/* @{ */
|
||||
|
||||
/** \name Pre-defined H264 encoding variants */
|
||||
/* @{ */
|
||||
/** ISO 14496-10 Annex B byte stream format */
|
||||
#define MMAL_ENCODING_VARIANT_H264_DEFAULT 0
|
||||
/** ISO 14496-15 AVC stream format */
|
||||
#define MMAL_ENCODING_VARIANT_H264_AVC1 MMAL_FOURCC('A','V','C','1')
|
||||
/** Implicitly delineated NAL units without emulation prevention */
|
||||
#define MMAL_ENCODING_VARIANT_H264_RAW MMAL_FOURCC('R','A','W',' ')
|
||||
/* @} */
|
||||
|
||||
/** \name Pre-defined MPEG4 audio encoding variants */
|
||||
/* @{ */
|
||||
/** Raw stream format */
|
||||
#define MMAL_ENCODING_VARIANT_MP4A_DEFAULT 0
|
||||
/** ADTS stream format */
|
||||
#define MMAL_ENCODING_VARIANT_MP4A_ADTS MMAL_FOURCC('A','D','T','S')
|
||||
/* @} */
|
||||
|
||||
/* @} MmalEncodingVariants List */
|
||||
|
||||
/** \defgroup MmalColorSpace List of pre-defined video color spaces
|
||||
* This defines a list of common color spaces. This list isn't exhaustive and is only
|
||||
* provided as a convenience to avoid clients having to use FourCC codes directly.
|
||||
* However components are allowed to define and use their own FourCC codes. */
|
||||
/* @{ */
|
||||
|
||||
/** Unknown color space */
|
||||
#define MMAL_COLOR_SPACE_UNKNOWN 0
|
||||
/** ITU-R BT.601-5 [SDTV] */
|
||||
#define MMAL_COLOR_SPACE_ITUR_BT601 MMAL_FOURCC('Y','6','0','1')
|
||||
/** ITU-R BT.709-3 [HDTV] */
|
||||
#define MMAL_COLOR_SPACE_ITUR_BT709 MMAL_FOURCC('Y','7','0','9')
|
||||
/** JPEG JFIF */
|
||||
#define MMAL_COLOR_SPACE_JPEG_JFIF MMAL_FOURCC('Y','J','F','I')
|
||||
/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
|
||||
#define MMAL_COLOR_SPACE_FCC MMAL_FOURCC('Y','F','C','C')
|
||||
/** Society of Motion Picture and Television Engineers 240M (1999) */
|
||||
#define MMAL_COLOR_SPACE_SMPTE240M MMAL_FOURCC('Y','2','4','0')
|
||||
/** ITU-R BT.470-2 System M */
|
||||
#define MMAL_COLOR_SPACE_BT470_2_M MMAL_FOURCC('Y','_','_','M')
|
||||
/** ITU-R BT.470-2 System BG */
|
||||
#define MMAL_COLOR_SPACE_BT470_2_BG MMAL_FOURCC('Y','_','B','G')
|
||||
/** JPEG JFIF, but with 16..255 luma */
|
||||
#define MMAL_COLOR_SPACE_JFIF_Y16_255 MMAL_FOURCC('Y','Y','1','6')
|
||||
/* @} MmalColorSpace List */
|
||||
|
||||
#endif /* MMAL_ENCODINGS_H */
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_EVENTS_H
|
||||
#define MMAL_EVENTS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mmal_common.h"
|
||||
#include "mmal_parameters.h"
|
||||
#include "mmal_port.h"
|
||||
|
||||
/** \defgroup MmalEvents List of pre-defined event types
|
||||
* This defines a list of standard event types. Components can still define proprietary
|
||||
* event types by using their own FourCC and defining their own event structures. */
|
||||
/* @{ */
|
||||
|
||||
/** \name Pre-defined event FourCCs */
|
||||
/* @{ */
|
||||
|
||||
/** Error event. Data contains a \ref MMAL_STATUS_T */
|
||||
#define MMAL_EVENT_ERROR MMAL_FOURCC('E','R','R','O')
|
||||
|
||||
/** End-of-stream event. Data contains a \ref MMAL_EVENT_END_OF_STREAM_T */
|
||||
#define MMAL_EVENT_EOS MMAL_FOURCC('E','E','O','S')
|
||||
|
||||
/** Format changed event. Data contains a \ref MMAL_EVENT_FORMAT_CHANGED_T */
|
||||
#define MMAL_EVENT_FORMAT_CHANGED MMAL_FOURCC('E','F','C','H')
|
||||
|
||||
/** Parameter changed event. Data contains the new parameter value, see
|
||||
* \ref MMAL_EVENT_PARAMETER_CHANGED_T
|
||||
*/
|
||||
#define MMAL_EVENT_PARAMETER_CHANGED MMAL_FOURCC('E','P','C','H')
|
||||
|
||||
/* @} */
|
||||
|
||||
|
||||
/** End-of-stream event. */
|
||||
typedef struct MMAL_EVENT_END_OF_STREAM_T
|
||||
{
|
||||
MMAL_PORT_TYPE_T port_type; /**< Type of port that received the end of stream */
|
||||
uint32_t port_index; /**< Index of port that received the end of stream */
|
||||
} MMAL_EVENT_END_OF_STREAM_T;
|
||||
|
||||
/** Format changed event data. */
|
||||
typedef struct MMAL_EVENT_FORMAT_CHANGED_T
|
||||
{
|
||||
uint32_t buffer_size_min; /**< Minimum size of buffers the port requires */
|
||||
uint32_t buffer_num_min; /**< Minimum number of buffers the port requires */
|
||||
uint32_t buffer_size_recommended; /**< Size of buffers the port recommends for optimal performance.
|
||||
A value of zero means no special recommendation. */
|
||||
uint32_t buffer_num_recommended; /**< Number of buffers the port recommends for optimal
|
||||
performance. A value of zero means no special recommendation. */
|
||||
|
||||
MMAL_ES_FORMAT_T *format; /**< New elementary stream format */
|
||||
} MMAL_EVENT_FORMAT_CHANGED_T;
|
||||
|
||||
/** Parameter changed event data.
|
||||
* This is a variable sized event. The full parameter is included in the event
|
||||
* data, not just the header. Use the \ref MMAL_PARAMETER_HEADER_T::id field to determine how to
|
||||
* cast the structure. The \ref MMAL_PARAMETER_HEADER_T::size field can be used to check validity.
|
||||
*/
|
||||
typedef struct MMAL_EVENT_PARAMETER_CHANGED_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
} MMAL_EVENT_PARAMETER_CHANGED_T;
|
||||
|
||||
/** Get a pointer to the \ref MMAL_EVENT_FORMAT_CHANGED_T structure contained in the buffer header.
|
||||
* Note that the pointer will point inside the data contained in the buffer header
|
||||
* so doesn't need to be freed explicitly.
|
||||
*
|
||||
* @param buffer buffer header containing the MMAL_EVENT_FORMAT_CHANGED event.
|
||||
* @return pointer to a MMAL_EVENT_FORMAT_CHANGED_T structure.
|
||||
*/
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *mmal_event_format_changed_get(MMAL_BUFFER_HEADER_T *buffer);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_EVENTS_H */
|
@ -1,223 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_FORMAT_H
|
||||
#define MMAL_FORMAT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup MmalFormat Elementary stream format
|
||||
* Definition of an elementary stream format and its associated API */
|
||||
/* @{ */
|
||||
|
||||
#include "mmal_types.h"
|
||||
#include "mmal_encodings.h"
|
||||
|
||||
/** Enumeration of the different types of elementary streams.
|
||||
* This divides elementary streams into 4 big categories, plus an invalid type. */
|
||||
typedef enum {
|
||||
MMAL_ES_TYPE_UNKNOWN, /**< Unknown elementary stream type */
|
||||
MMAL_ES_TYPE_CONTROL, /**< Elementary stream of control commands */
|
||||
MMAL_ES_TYPE_AUDIO, /**< Audio elementary stream */
|
||||
MMAL_ES_TYPE_VIDEO, /**< Video elementary stream */
|
||||
MMAL_ES_TYPE_SUBPICTURE /**< Sub-picture elementary stream (e.g. subtitles, overlays) */
|
||||
} MMAL_ES_TYPE_T;
|
||||
|
||||
/** Definition of a video format.
|
||||
* This describes the properties specific to a video stream */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t width; /**< Width of frame in pixels */
|
||||
uint32_t height; /**< Height of frame in rows of pixels */
|
||||
MMAL_RECT_T crop; /**< Visible region of the frame */
|
||||
MMAL_RATIONAL_T frame_rate; /**< Frame rate */
|
||||
MMAL_RATIONAL_T par; /**< Pixel aspect ratio */
|
||||
|
||||
MMAL_FOURCC_T color_space; /**< FourCC specifying the color space of the
|
||||
* video stream. See the \ref MmalColorSpace
|
||||
* "pre-defined color spaces" for some examples.
|
||||
*/
|
||||
|
||||
} MMAL_VIDEO_FORMAT_T;
|
||||
|
||||
/** Definition of an audio format.
|
||||
* This describes the properties specific to an audio stream */
|
||||
typedef struct MMAL_AUDIO_FORMAT_T
|
||||
{
|
||||
uint32_t channels; /**< Number of audio channels */
|
||||
uint32_t sample_rate; /**< Sample rate */
|
||||
|
||||
uint32_t bits_per_sample; /**< Bits per sample */
|
||||
uint32_t block_align; /**< Size of a block of data */
|
||||
|
||||
/** \todo add channel mapping, gapless and replay-gain support */
|
||||
|
||||
} MMAL_AUDIO_FORMAT_T;
|
||||
|
||||
/** Definition of a subpicture format.
|
||||
* This describes the properties specific to a subpicture stream */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t x_offset; /**< Width offset to the start of the subpicture */
|
||||
uint32_t y_offset; /**< Height offset to the start of the subpicture */
|
||||
|
||||
/** \todo surely more things are needed here */
|
||||
|
||||
} MMAL_SUBPICTURE_FORMAT_T;
|
||||
|
||||
/** Definition of the type specific format.
|
||||
* This describes the type specific information of the elementary stream. */
|
||||
typedef union
|
||||
{
|
||||
MMAL_AUDIO_FORMAT_T audio; /**< Audio specific information */
|
||||
MMAL_VIDEO_FORMAT_T video; /**< Video specific information */
|
||||
MMAL_SUBPICTURE_FORMAT_T subpicture; /**< Subpicture specific information */
|
||||
} MMAL_ES_SPECIFIC_FORMAT_T;
|
||||
|
||||
/** \name Elementary stream flags
|
||||
* \anchor elementarystreamflags
|
||||
* The following flags describe properties of an elementary stream */
|
||||
/* @{ */
|
||||
#define MMAL_ES_FORMAT_FLAG_FRAMED 0x1 /**< The elementary stream will already be framed */
|
||||
/* @} */
|
||||
|
||||
/** \name Undefined encoding value.
|
||||
* This value indicates an unknown encoding
|
||||
*/
|
||||
/* @{ */
|
||||
#define MMAL_ENCODING_UNKNOWN 0
|
||||
/* @} */
|
||||
|
||||
/** \name Default encoding variant value.
|
||||
* This value indicates the default encoding variant is used
|
||||
*/
|
||||
/* @{ */
|
||||
#define MMAL_ENCODING_VARIANT_DEFAULT 0
|
||||
/* @} */
|
||||
|
||||
/** Definition of an elementary stream format */
|
||||
typedef struct MMAL_ES_FORMAT_T
|
||||
{
|
||||
MMAL_ES_TYPE_T type; /**< Type of the elementary stream */
|
||||
|
||||
MMAL_FOURCC_T encoding; /**< FourCC specifying the encoding of the elementary stream.
|
||||
* See the \ref MmalEncodings "pre-defined encodings" for some
|
||||
* examples.
|
||||
*/
|
||||
MMAL_FOURCC_T encoding_variant;/**< FourCC specifying the specific encoding variant of
|
||||
* the elementary stream. See the \ref MmalEncodingVariants
|
||||
* "pre-defined encoding variants" for some examples.
|
||||
*/
|
||||
|
||||
MMAL_ES_SPECIFIC_FORMAT_T *es; /**< Type specific information for the elementary stream */
|
||||
|
||||
uint32_t bitrate; /**< Bitrate in bits per second */
|
||||
uint32_t flags; /**< Flags describing properties of the elementary stream.
|
||||
* See \ref elementarystreamflags "Elementary stream flags".
|
||||
*/
|
||||
|
||||
uint32_t extradata_size; /**< Size of the codec specific data */
|
||||
uint8_t *extradata; /**< Codec specific data */
|
||||
|
||||
} MMAL_ES_FORMAT_T;
|
||||
|
||||
/** Allocate and initialise a \ref MMAL_ES_FORMAT_T structure.
|
||||
*
|
||||
* @return a \ref MMAL_ES_FORMAT_T structure
|
||||
*/
|
||||
MMAL_ES_FORMAT_T *mmal_format_alloc(void);
|
||||
|
||||
/** Free a \ref MMAL_ES_FORMAT_T structure allocated by \ref mmal_format_alloc.
|
||||
*
|
||||
* @param format the \ref MMAL_ES_FORMAT_T structure to free
|
||||
*/
|
||||
void mmal_format_free(MMAL_ES_FORMAT_T *format);
|
||||
|
||||
/** Allocate the extradata buffer in \ref MMAL_ES_FORMAT_T.
|
||||
* This buffer will be freed automatically when the format is destroyed or
|
||||
* another allocation is done.
|
||||
*
|
||||
* @param format format structure for which the extradata buffer will be allocated
|
||||
* @param size size of the extradata buffer to allocate
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_format_extradata_alloc(MMAL_ES_FORMAT_T *format, unsigned int size);
|
||||
|
||||
/** Shallow copy a format structure.
|
||||
* It is worth noting that the extradata buffer will not be copied in the new format.
|
||||
*
|
||||
* @param format_dest destination \ref MMAL_ES_FORMAT_T for the copy
|
||||
* @param format_src source \ref MMAL_ES_FORMAT_T for the copy
|
||||
*/
|
||||
void mmal_format_copy(MMAL_ES_FORMAT_T *format_dest, MMAL_ES_FORMAT_T *format_src);
|
||||
|
||||
/** Fully copy a format structure, including the extradata buffer.
|
||||
*
|
||||
* @param format_dest destination \ref MMAL_ES_FORMAT_T for the copy
|
||||
* @param format_src source \ref MMAL_ES_FORMAT_T for the copy
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_format_full_copy(MMAL_ES_FORMAT_T *format_dest, MMAL_ES_FORMAT_T *format_src);
|
||||
|
||||
/** \name Comparison flags
|
||||
* \anchor comparisonflags
|
||||
* The following flags describe the differences between 2 format structures */
|
||||
/* @{ */
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_TYPE 0x01 /**< The type is different */
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_ENCODING 0x02 /**< The encoding is different */
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_BITRATE 0x04 /**< The bitrate is different */
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_FLAGS 0x08 /**< The flags are different */
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_EXTRADATA 0x10 /**< The extradata is different */
|
||||
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_RESOLUTION 0x0100 /**< The video resolution is different */
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_CROPPING 0x0200 /**< The video cropping is different */
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_FRAME_RATE 0x0400 /**< The video frame rate is different */
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_ASPECT_RATIO 0x0800 /**< The video aspect ratio is different */
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_COLOR_SPACE 0x1000 /**< The video color space is different */
|
||||
|
||||
#define MMAL_ES_FORMAT_COMPARE_FLAG_ES_OTHER 0x10000000 /**< Other ES specific parameters are different */
|
||||
/* @} */
|
||||
|
||||
/** Compare 2 format structures and returns a set of flags describing the differences.
|
||||
* The result will be zero if the structures are the same, or a combination of
|
||||
* one or more of the \ref comparisonflags "Comparison flags" if different.
|
||||
*
|
||||
* @param format_1 first \ref MMAL_ES_FORMAT_T to compare
|
||||
* @param format_2 second \ref MMAL_ES_FORMAT_T to compare
|
||||
* @return set of flags describing the differences
|
||||
*/
|
||||
uint32_t mmal_format_compare(MMAL_ES_FORMAT_T *format_1, MMAL_ES_FORMAT_T *format_2);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_FORMAT_H */
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_LOGGING_H
|
||||
#define MMAL_LOGGING_H
|
||||
|
||||
#include "mmal_common.h"
|
||||
#include "interface/vcos/vcos_logging.h"
|
||||
|
||||
#ifndef VCOS_LOG_CATEGORY
|
||||
#define VCOS_LOG_CATEGORY (&mmal_log_category)
|
||||
extern VCOS_LOG_CAT_T mmal_log_category;
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (( __GNUC__ > 2 ) || (( __GNUC__ == 2 ) && ( __GNUC_MINOR__ >= 3 )))
|
||||
#define mmal_log_error(s, ...) vcos_log_error("%s: " s, VCOS_FUNCTION, ## __VA_ARGS__)
|
||||
#define mmal_log_info(s, ...) vcos_log_info("%s: " s, VCOS_FUNCTION, ## __VA_ARGS__)
|
||||
#define mmal_log_warn(s, ...) vcos_log_warn("%s: " s, VCOS_FUNCTION, ## __VA_ARGS__)
|
||||
#define mmal_log_debug(s, ...) vcos_log_info("%s: " s, VCOS_FUNCTION, ## __VA_ARGS__)
|
||||
#define mmal_log_trace(s, ...) vcos_log_trace("%s: " s, VCOS_FUNCTION, ## __VA_ARGS__)
|
||||
#elif defined(_MSC_VER)
|
||||
#define mmal_log_error(s, ...) vcos_log_error("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#define mmal_log_info(s, ...) vcos_log_info("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#define mmal_log_warn(s, ...) vcos_log_warn("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#define mmal_log_debug(s, ...) vcos_log_info("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#define mmal_log_trace(s, ...) vcos_log_trace("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#else
|
||||
#define mmal_log_error_fun(s, ...) vcos_log_error("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#define mmal_log_info_fun(s, ...) vcos_log_info("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#define mmal_log_warn_fun(s, ...) vcos_log_warn("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#define mmal_log_debug_fun(s, ...) vcos_log_info("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#define mmal_log_trace_fun(s, ...) vcos_log_trace("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
|
||||
#define mmal_log_error(s...) mmal_log_error_fun(s, 0)
|
||||
#define mmal_log_info(s...) mmal_log_info_fun(s, 0)
|
||||
#define mmal_log_warn(s...) mmal_log_warn_fun(s, 0)
|
||||
#define mmal_log_debug(s...) mmal_log_debug_fun(s, 0)
|
||||
#define mmal_log_trace(s...) mmal_log_trace_fun(s, 0)
|
||||
#endif
|
||||
|
||||
#define LOG_ERROR mmal_log_error
|
||||
#define LOG_INFO mmal_log_info
|
||||
#define LOG_WARN mmal_log_warn
|
||||
#define LOG_DEBUG mmal_log_debug
|
||||
#define LOG_TRACE mmal_log_trace
|
||||
|
||||
#endif /* MMAL_LOGGING_H */
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_METADATA_H
|
||||
#define MMAL_METADATA_H
|
||||
|
||||
#include "mmal_common.h"
|
||||
|
||||
/** \defgroup MmalMetadata List of pre-defined metadata types
|
||||
* This defines a list of standard metadata types. Components can still define proprietary
|
||||
* metadata types by using their own FourCC and defining their own metadata structures. */
|
||||
/* @{ */
|
||||
|
||||
/** \name Pre-defined metadata FourCCs */
|
||||
/* @{ */
|
||||
#define MMAL_METADATA_HELLO_WORLD MMAL_FOURCC('H','E','L','O')
|
||||
/* @} */
|
||||
|
||||
/** Generic metadata type. All metadata structures need to begin with these fields. */
|
||||
typedef struct MMAL_METATDATA_T
|
||||
{
|
||||
uint32_t id; /**< Metadata id. This is a FourCC */
|
||||
uint32_t size; /**< Size in bytes of the following metadata (not including id and size) */
|
||||
} MMAL_METADATA_T;
|
||||
|
||||
/** Hello World metadata. */
|
||||
typedef struct MMAL_METATDATA_HELLO_WORLD_T
|
||||
{
|
||||
uint32_t id; /**< Metadata id. This is a FourCC */
|
||||
uint32_t size; /**< Size in bytes of the following metadata (not including id and size) */
|
||||
|
||||
uint32_t myvalue; /**< Metadata value */
|
||||
} MMAL_METADATA_HELLO_WORLD_T;
|
||||
|
||||
/** Get metadata item from buffer header.
|
||||
* This will search through all the metadata in the buffer header and return a pointer to the
|
||||
* first instance of the requested metadata id.
|
||||
*
|
||||
* @param header buffer header containing the metadata
|
||||
* @param id requested metadata id
|
||||
*
|
||||
* @return Pointer to metadata requested or NULL if not found.
|
||||
*/
|
||||
MMAL_METADATA_T *mmal_metadata_get(MMAL_BUFFER_HEADER_T *header, uint32_t id);
|
||||
|
||||
/** Set metadata item in buffer header.
|
||||
* This will store the metadata item into the buffer header. This operation can fail if not
|
||||
* enough memory is available in the data section of the buffer header.
|
||||
*
|
||||
* @param header buffer header to store the metadata into
|
||||
* @param metadata metadata item to store in buffer header
|
||||
*
|
||||
* @return MMAL_SUCCESS on success or MMAL_ENOMEM if not enough memory is available for storing
|
||||
* the metadata
|
||||
*/
|
||||
MMAL_STATUS_T mmal_metadata_set(MMAL_BUFFER_HEADER_T *header, MMAL_METADATA_T *metadata);
|
||||
|
||||
/* @} */
|
||||
|
||||
#endif /* MMAL_METADATA_H */
|
@ -1,194 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_PARAMETERS_H
|
||||
#define MMAL_PARAMETERS_H
|
||||
|
||||
#include "mmal_common.h"
|
||||
#include "mmal_parameters_camera.h"
|
||||
#include "mmal_parameters_video.h"
|
||||
#include "mmal_parameters_audio.h"
|
||||
#include "mmal_parameters_clock.h"
|
||||
|
||||
/** \defgroup MmalParameters List of pre-defined parameters
|
||||
* This defines a list of standard parameters. Components can define proprietary
|
||||
* parameters by creating a new group and defining their own structures. */
|
||||
/* @{ */
|
||||
|
||||
/** Generic unsigned 64-bit integer parameter type. */
|
||||
typedef struct MMAL_PARAMETER_UINT64_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint64_t value; /**< Parameter value */
|
||||
} MMAL_PARAMETER_UINT64_T;
|
||||
|
||||
/** Generic signed 64-bit integer parameter type. */
|
||||
typedef struct MMAL_PARAMETER_INT64_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
int64_t value; /**< Parameter value */
|
||||
} MMAL_PARAMETER_INT64_T;
|
||||
|
||||
/** Generic unsigned 32-bit integer parameter type. */
|
||||
typedef struct MMAL_PARAMETER_UINT32_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t value; /**< Parameter value */
|
||||
} MMAL_PARAMETER_UINT32_T;
|
||||
|
||||
/** Generic signed 32-bit integer parameter type. */
|
||||
typedef struct MMAL_PARAMETER_INT32_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
int32_t value; /**< Parameter value */
|
||||
} MMAL_PARAMETER_INT32_T;
|
||||
|
||||
/** Generic rational parameter type. */
|
||||
typedef struct MMAL_PARAMETER_RATIONAL_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_RATIONAL_T value; /**< Parameter value */
|
||||
} MMAL_PARAMETER_RATIONAL_T;
|
||||
|
||||
/** Generic boolean parameter type. */
|
||||
typedef struct MMAL_PARAMETER_BOOLEAN_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_BOOL_T enable; /**< Parameter value */
|
||||
} MMAL_PARAMETER_BOOLEAN_T;
|
||||
|
||||
/** Generic string parameter type. */
|
||||
typedef struct MMAL_PARAMETER_STRING_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
char str[1]; /**< Null-terminated string */
|
||||
} MMAL_PARAMETER_STRING_T;
|
||||
|
||||
/** Generic array of bytes parameter type. */
|
||||
typedef struct MMAL_PARAMETER_BYTES_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint8_t data[1]; /**< Array of bytes */
|
||||
} MMAL_PARAMETER_BYTES_T;
|
||||
|
||||
/** The value 1 in 16.16 fixed point form */
|
||||
#define MMAL_FIXED_16_16_ONE (1 << 16)
|
||||
|
||||
/** Generic two-dimensional scaling factor type. */
|
||||
typedef struct MMAL_PARAMETER_SCALEFACTOR_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_FIXED_16_16_T scale_x; /**< Scaling factor in X-axis */
|
||||
MMAL_FIXED_16_16_T scale_y; /**< Scaling factor in Y-axis */
|
||||
} MMAL_PARAMETER_SCALEFACTOR_T;
|
||||
|
||||
/** Valid mirror modes */
|
||||
typedef enum MMAL_PARAM_MIRROR_T
|
||||
{
|
||||
MMAL_PARAM_MIRROR_NONE,
|
||||
MMAL_PARAM_MIRROR_VERTICAL,
|
||||
MMAL_PARAM_MIRROR_HORIZONTAL,
|
||||
MMAL_PARAM_MIRROR_BOTH,
|
||||
} MMAL_PARAM_MIRROR_T;
|
||||
|
||||
/** Generic mirror parameter type */
|
||||
typedef struct MMAL_PARAMETER_MIRROR_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_MIRROR_T value; /**< Mirror mode */
|
||||
} MMAL_PARAMETER_MIRROR_T;
|
||||
|
||||
/** URI parameter type.
|
||||
* The parameter may hold an arbitrary length, nul-terminated string as long
|
||||
* as the size is set appropriately.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_URI_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
char uri[1]; /**< URI string (null-terminated) */
|
||||
} MMAL_PARAMETER_URI_T;
|
||||
|
||||
/** Generic encoding parameter type.
|
||||
* The parameter may hold more than one encoding by overriding the size to
|
||||
* include a bigger array.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_ENCODING_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t encoding[1]; /**< Array of FourCC encodings, see \ref MmalEncodings */
|
||||
} MMAL_PARAMETER_ENCODING_T;
|
||||
|
||||
/** Generic frame-rate parameter type.
|
||||
* Frame rates are specified as a rational number, using a pair of integers.
|
||||
* Since there can be many valid pairs for the same ratio, a frame-rate may
|
||||
* not contain exactly the same pairs of values when read back as it was
|
||||
* when set.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_FRAME_RATE_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_RATIONAL_T frame_rate; /**< Frame-rate value */
|
||||
} MMAL_PARAMETER_FRAME_RATE_T;
|
||||
|
||||
/** Generic configuration-file setup type.
|
||||
* Configuration files are transferred in small chunks. The component can
|
||||
* save all the chunks into a buffer, then process the entire file later.
|
||||
* This parameter initialises a config file to have the given size.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_CONFIGFILE_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t file_size; /**< Size of complete file data */
|
||||
} MMAL_PARAMETER_CONFIGFILE_T;
|
||||
|
||||
/** Generic configuration-file chunk data type.
|
||||
* Once a config file has been initialised, this parameter can be used to
|
||||
* write an arbitrary chunk of the file data (limited by the maximum MMAL
|
||||
* message size).
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_CONFIGFILE_CHUNK_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t size; /**< Number of bytes being transferred in this chunk */
|
||||
uint32_t offset; /**< Offset of this chunk in the file */
|
||||
char data[1]; /**< Chunk data */
|
||||
} MMAL_PARAMETER_CONFIGFILE_CHUNK_T;
|
||||
|
||||
/* @} */
|
||||
|
||||
#endif /* MMAL_PARAMETERS_H */
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_PARAMETERS_AUDIO_H
|
||||
#define MMAL_PARAMETERS_AUDIO_H
|
||||
|
||||
#include "mmal_parameters_common.h"
|
||||
|
||||
/*************************************************
|
||||
* ALWAYS ADD NEW ENUMS AT THE END OF THIS LIST! *
|
||||
************************************************/
|
||||
|
||||
/** Audio-specific MMAL parameter IDs.
|
||||
* @ingroup MMAL_PARAMETER_IDS
|
||||
*/
|
||||
enum
|
||||
{
|
||||
MMAL_PARAMETER_AUDIO_DESTINATION /**< Takes a MMAL_PARAMETER_STRING_T */
|
||||
= MMAL_PARAMETER_GROUP_AUDIO,
|
||||
MMAL_PARAMETER_AUDIO_LATENCY_TARGET, /**< Takes a MMAL_PARAMETER_AUDIO_LATENCY_TARGET_T */
|
||||
MMAL_PARAMETER_AUDIO_SOURCE,
|
||||
MMAL_PARAMETER_AUDIO_PASSTHROUGH, /**< Takes a MMAL_PARAMETER_BOOLEAN_T */
|
||||
};
|
||||
|
||||
/** Audio latency target to maintain.
|
||||
* These settings are used to adjust the clock speed in order
|
||||
* to match the measured audio latency to a specified value. */
|
||||
typedef struct MMAL_PARAMETER_AUDIO_LATENCY_TARGET_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_BOOL_T enable; /**< whether this mode is enabled */
|
||||
uint32_t filter; /**< number of latency samples to filter on, good value: 1 */
|
||||
uint32_t target; /**< target latency (microseconds) */
|
||||
uint32_t shift; /**< shift for storing latency values, good value: 7 */
|
||||
int32_t speed_factor; /**< multiplier for speed changes, in 24.8 format, good value: 256-512 */
|
||||
int32_t inter_factor; /**< divider for comparing latency versus gradiant, good value: 300 */
|
||||
int32_t adj_cap; /**< limit for speed change before nSpeedFactor is applied, good value: 100 */
|
||||
} MMAL_PARAMETER_AUDIO_LATENCY_TARGET_T;
|
||||
|
||||
#endif /* MMAL_PARAMETERS_AUDIO_H */
|
||||
|
@ -1,755 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
Copyright (c) 2011 Broadcom Europe Limited.
|
||||
All rights reserved.
|
||||
=============================================================================*/
|
||||
/** \file
|
||||
* Multi-Media Abstraction Layer - Definition of some standard parameters.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_PARAMETERS_CAMERA_H
|
||||
#define MMAL_PARAMETERS_CAMERA_H
|
||||
|
||||
#include "mmal_parameters_common.h"
|
||||
|
||||
/*************************************************
|
||||
* ALWAYS ADD NEW ENUMS AT THE END OF THIS LIST! *
|
||||
************************************************/
|
||||
|
||||
/** Camera-specific MMAL parameter IDs.
|
||||
* @ingroup MMAL_PARAMETER_IDS
|
||||
*/
|
||||
enum {
|
||||
/* 0 */
|
||||
MMAL_PARAMETER_THUMBNAIL_CONFIGURATION /**< Takes a @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
|
||||
= MMAL_PARAMETER_GROUP_CAMERA,
|
||||
MMAL_PARAMETER_CAPTURE_QUALITY, /**< Unused? */
|
||||
MMAL_PARAMETER_ROTATION, /**< Takes a @ref MMAL_PARAMETER_INT32_T */
|
||||
MMAL_PARAMETER_EXIF_DISABLE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_EXIF, /**< Takes a @ref MMAL_PARAMETER_EXIF_T */
|
||||
MMAL_PARAMETER_AWB_MODE, /**< Takes a @ref MMAL_PARAM_AWBMODE_T */
|
||||
MMAL_PARAMETER_IMAGE_EFFECT, /**< Takes a @ref MMAL_PARAMETER_IMAGEFX_T */
|
||||
MMAL_PARAMETER_COLOUR_EFFECT, /**< Takes a @ref MMAL_PARAMETER_COLOURFX_T */
|
||||
MMAL_PARAMETER_FLICKER_AVOID, /**< Takes a @ref MMAL_PARAMETER_FLICKERAVOID_T */
|
||||
MMAL_PARAMETER_FLASH, /**< Takes a @ref MMAL_PARAMETER_FLASH_T */
|
||||
MMAL_PARAMETER_REDEYE, /**< Takes a @ref MMAL_PARAMETER_REDEYE_T */
|
||||
MMAL_PARAMETER_FOCUS, /**< Takes a @ref MMAL_PARAMETER_FOCUS_T */
|
||||
MMAL_PARAMETER_FOCAL_LENGTHS, /**< Unused? */
|
||||
MMAL_PARAMETER_EXPOSURE_COMP, /**< Takes a @ref MMAL_PARAMETER_INT32_T or MMAL_PARAMETER_RATIONAL_T */
|
||||
MMAL_PARAMETER_ZOOM, /**< Takes a @ref MMAL_PARAMETER_SCALEFACTOR_T */
|
||||
MMAL_PARAMETER_MIRROR, /**< Takes a @ref MMAL_PARAMETER_MIRROR_T */
|
||||
|
||||
/* 0x10 */
|
||||
MMAL_PARAMETER_CAMERA_NUM, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
|
||||
MMAL_PARAMETER_CAPTURE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_EXPOSURE_MODE, /**< Takes a @ref MMAL_PARAMETER_EXPOSUREMODE_T */
|
||||
MMAL_PARAMETER_EXP_METERING_MODE, /**< Takes a @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
|
||||
MMAL_PARAMETER_FOCUS_STATUS, /**< Takes a @ref MMAL_PARAMETER_FOCUS_STATUS_T */
|
||||
MMAL_PARAMETER_CAMERA_CONFIG, /**< Takes a @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
|
||||
MMAL_PARAMETER_CAPTURE_STATUS, /**< Takes a @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
|
||||
MMAL_PARAMETER_FACE_TRACK, /**< Takes a @ref MMAL_PARAMETER_FACE_TRACK_T */
|
||||
MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_JPEG_Q_FACTOR, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
|
||||
MMAL_PARAMETER_FRAME_RATE, /**< Takes a @ref MMAL_PARAMETER_FRAME_RATE_T */
|
||||
MMAL_PARAMETER_USE_STC, /**< Takes a @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
|
||||
MMAL_PARAMETER_CAMERA_INFO, /**< Takes a @ref MMAL_PARAMETER_CAMERA_INFO_T */
|
||||
MMAL_PARAMETER_VIDEO_STABILISATION, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_FACE_TRACK_RESULTS, /**< Takes a @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
|
||||
MMAL_PARAMETER_ENABLE_RAW_CAPTURE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
|
||||
/* 0x20 */
|
||||
MMAL_PARAMETER_DPF_FILE, /**< Takes a @ref MMAL_PARAMETER_URI_T */
|
||||
MMAL_PARAMETER_ENABLE_DPF_FILE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_DPF_FAIL_IS_FATAL, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_CAPTURE_MODE, /**< Takes a @ref MMAL_PARAMETER_CAPTUREMODE_T */
|
||||
MMAL_PARAMETER_FOCUS_REGIONS, /**< Takes a @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
|
||||
MMAL_PARAMETER_INPUT_CROP, /**< Takes a @ref MMAL_PARAMETER_INPUT_CROP_T */
|
||||
MMAL_PARAMETER_SENSOR_INFORMATION, /**< Takes a @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
|
||||
MMAL_PARAMETER_FLASH_SELECT, /**< Takes a @ref MMAL_PARAMETER_FLASH_SELECT_T */
|
||||
MMAL_PARAMETER_FIELD_OF_VIEW, /**< Takes a @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
|
||||
MMAL_PARAMETER_HIGH_DYNAMIC_RANGE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, /**< Takes a @ref MMAL_PARAMETER_DRC_T */
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL, /**< Takes a @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
|
||||
MMAL_PARAMETER_SHARPNESS, /**< Takes a @ref MMAL_PARAMETER_RATIONAL_T */
|
||||
MMAL_PARAMETER_CONTRAST, /**< Takes a @ref MMAL_PARAMETER_RATIONAL_T */
|
||||
MMAL_PARAMETER_BRIGHTNESS, /**< Takes a @ref MMAL_PARAMETER_RATIONAL_T */
|
||||
MMAL_PARAMETER_SATURATION, /**< Takes a @ref MMAL_PARAMETER_RATIONAL_T */
|
||||
|
||||
/* 0x30 */
|
||||
MMAL_PARAMETER_ISO, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
|
||||
MMAL_PARAMETER_ANTISHAKE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, /**< Takes a @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
|
||||
MMAL_PARAMETER_CAMERA_BURST_CAPTURE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_CAMERA_MIN_ISO, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
|
||||
MMAL_PARAMETER_CAMERA_USE_CASE, /**< Takes a @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
|
||||
MMAL_PARAMETER_CAPTURE_STATS_PASS, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
|
||||
MMAL_PARAMETER_ENABLE_REGISTER_FILE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_CONFIGFILE_REGISTERS, /**< Takes a @ref MMAL_PARAMETER_CONFIGFILE_T */
|
||||
MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,/**< Takes a @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
|
||||
MMAL_PARAMETER_JPEG_ATTACH_LOG, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_ZERO_SHUTTER_LAG, /**< Takes a @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
|
||||
MMAL_PARAMETER_FPS_RANGE, /**< Takes a @ref MMAL_PARAMETER_FPS_RANGE_T */
|
||||
MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP, /**< Takes a @ref MMAL_PARAMETER_INT32_T */
|
||||
|
||||
/* 0x40 */
|
||||
MMAL_PARAMETER_SW_SHARPEN_DISABLE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_FLASH_REQUIRED, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_SW_SATURATION_DISABLE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_SHUTTER_SPEED, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
|
||||
MMAL_PARAMETER_CUSTOM_AWB_GAINS, /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
|
||||
MMAL_PARAMETER_CAMERA_SETTINGS, /**< Takes a @ref MMAL_PARAMETER_CAMERA_SETTINGS_T */
|
||||
MMAL_PARAMETER_PRIVACY_INDICATOR, /**< Takes a @ref MMAL_PARAMETER_PRIVACY_INDICATOR_T */
|
||||
MMAL_PARAMETER_VIDEO_DENOISE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_STILLS_DENOISE, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_ANNOTATE, /**< Takes a @ref MMAL_PARAMETER_CAMERA_ANNOTATE_T */
|
||||
MMAL_PARAMETER_STEREOSCOPIC_MODE, /**< Takes a @ref MMAL_PARAMETER_STEREOSCOPIC_MODE_T */
|
||||
};
|
||||
|
||||
/** Thumbnail configuration parameter type */
|
||||
typedef struct MMAL_PARAMETER_THUMBNAIL_CONFIG_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t enable; /**< Enable generation of thumbnails during still capture */
|
||||
uint32_t width; /**< Desired width of the thumbnail */
|
||||
uint32_t height; /**< Desired height of the thumbnail */
|
||||
uint32_t quality; /**< Desired compression quality of the thumbnail */
|
||||
} MMAL_PARAMETER_THUMBNAIL_CONFIG_T;
|
||||
|
||||
/** EXIF parameter type. */
|
||||
typedef struct MMAL_PARAMETER_EXIF_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t keylen; /**< If 0, assume key is terminated by '=', otherwise length of key and treat data as binary */
|
||||
uint32_t value_offset; /**< Offset within data buffer of the start of the value. If 0, look for a "key=value" string */
|
||||
uint32_t valuelen; /**< If 0, assume value is null-terminated, otherwise length of value and treat data as binary */
|
||||
uint8_t data[1]; /**< EXIF key/value string. Variable length */
|
||||
} MMAL_PARAMETER_EXIF_T;
|
||||
|
||||
/** Exposure modes. */
|
||||
typedef enum
|
||||
{
|
||||
MMAL_PARAM_EXPOSUREMODE_OFF,
|
||||
MMAL_PARAM_EXPOSUREMODE_AUTO,
|
||||
MMAL_PARAM_EXPOSUREMODE_NIGHT,
|
||||
MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
|
||||
MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
|
||||
MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
|
||||
MMAL_PARAM_EXPOSUREMODE_SPORTS,
|
||||
MMAL_PARAM_EXPOSUREMODE_SNOW,
|
||||
MMAL_PARAM_EXPOSUREMODE_BEACH,
|
||||
MMAL_PARAM_EXPOSUREMODE_VERYLONG,
|
||||
MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
|
||||
MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
|
||||
MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
|
||||
MMAL_PARAM_EXPOSUREMODE_MAX = 0x7fffffff
|
||||
} MMAL_PARAM_EXPOSUREMODE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_EXPOSUREMODE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_EXPOSUREMODE_T value; /**< exposure mode */
|
||||
} MMAL_PARAMETER_EXPOSUREMODE_T;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
|
||||
MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
|
||||
MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
|
||||
MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX,
|
||||
MMAL_PARAM_EXPOSUREMETERINGMODE_MAX = 0x7fffffff
|
||||
} MMAL_PARAM_EXPOSUREMETERINGMODE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_EXPOSUREMETERINGMODE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_EXPOSUREMETERINGMODE_T value; /**< metering mode */
|
||||
} MMAL_PARAMETER_EXPOSUREMETERINGMODE_T;
|
||||
|
||||
/** AWB parameter modes. */
|
||||
typedef enum MMAL_PARAM_AWBMODE_T
|
||||
{
|
||||
MMAL_PARAM_AWBMODE_OFF,
|
||||
MMAL_PARAM_AWBMODE_AUTO,
|
||||
MMAL_PARAM_AWBMODE_SUNLIGHT,
|
||||
MMAL_PARAM_AWBMODE_CLOUDY,
|
||||
MMAL_PARAM_AWBMODE_SHADE,
|
||||
MMAL_PARAM_AWBMODE_TUNGSTEN,
|
||||
MMAL_PARAM_AWBMODE_FLUORESCENT,
|
||||
MMAL_PARAM_AWBMODE_INCANDESCENT,
|
||||
MMAL_PARAM_AWBMODE_FLASH,
|
||||
MMAL_PARAM_AWBMODE_HORIZON,
|
||||
MMAL_PARAM_AWBMODE_MAX = 0x7fffffff
|
||||
} MMAL_PARAM_AWBMODE_T;
|
||||
|
||||
/** AWB parameter type. */
|
||||
typedef struct MMAL_PARAMETER_AWBMODE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_AWBMODE_T value; /**< AWB mode */
|
||||
} MMAL_PARAMETER_AWBMODE_T;
|
||||
|
||||
/** Image effect */
|
||||
typedef enum MMAL_PARAM_IMAGEFX_T
|
||||
{
|
||||
MMAL_PARAM_IMAGEFX_NONE,
|
||||
MMAL_PARAM_IMAGEFX_NEGATIVE,
|
||||
MMAL_PARAM_IMAGEFX_SOLARIZE,
|
||||
MMAL_PARAM_IMAGEFX_POSTERIZE,
|
||||
MMAL_PARAM_IMAGEFX_WHITEBOARD,
|
||||
MMAL_PARAM_IMAGEFX_BLACKBOARD,
|
||||
MMAL_PARAM_IMAGEFX_SKETCH,
|
||||
MMAL_PARAM_IMAGEFX_DENOISE,
|
||||
MMAL_PARAM_IMAGEFX_EMBOSS,
|
||||
MMAL_PARAM_IMAGEFX_OILPAINT,
|
||||
MMAL_PARAM_IMAGEFX_HATCH,
|
||||
MMAL_PARAM_IMAGEFX_GPEN,
|
||||
MMAL_PARAM_IMAGEFX_PASTEL,
|
||||
MMAL_PARAM_IMAGEFX_WATERCOLOUR,
|
||||
MMAL_PARAM_IMAGEFX_FILM,
|
||||
MMAL_PARAM_IMAGEFX_BLUR,
|
||||
MMAL_PARAM_IMAGEFX_SATURATION,
|
||||
MMAL_PARAM_IMAGEFX_COLOURSWAP,
|
||||
MMAL_PARAM_IMAGEFX_WASHEDOUT,
|
||||
MMAL_PARAM_IMAGEFX_POSTERISE,
|
||||
MMAL_PARAM_IMAGEFX_COLOURPOINT,
|
||||
MMAL_PARAM_IMAGEFX_COLOURBALANCE,
|
||||
MMAL_PARAM_IMAGEFX_CARTOON,
|
||||
MMAL_PARAM_IMAGEFX_DEINTERLACE_DOUBLE,
|
||||
MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV,
|
||||
MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST,
|
||||
MMAL_PARAM_IMAGEFX_MAX = 0x7fffffff
|
||||
} MMAL_PARAM_IMAGEFX_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_IMAGEFX_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_IMAGEFX_T value; /**< Image effect mode */
|
||||
} MMAL_PARAMETER_IMAGEFX_T;
|
||||
|
||||
#define MMAL_MAX_IMAGEFX_PARAMETERS 6 /* Image effects library currently uses a maximum of 5 parameters per effect */
|
||||
|
||||
typedef struct MMAL_PARAMETER_IMAGEFX_PARAMETERS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_IMAGEFX_T effect; /**< Image effect mode */
|
||||
uint32_t num_effect_params; /**< Number of used elements in */
|
||||
uint32_t effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS]; /**< Array of parameters */
|
||||
} MMAL_PARAMETER_IMAGEFX_PARAMETERS_T;
|
||||
|
||||
/** Colour effect parameter type*/
|
||||
typedef struct MMAL_PARAMETER_COLOURFX_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
int32_t enable;
|
||||
uint32_t u;
|
||||
uint32_t v;
|
||||
} MMAL_PARAMETER_COLOURFX_T;
|
||||
|
||||
typedef enum MMAL_CAMERA_STC_MODE_T
|
||||
{
|
||||
MMAL_PARAM_STC_MODE_OFF, /**< Frames do not have STCs, as needed in OpenMAX/IL */
|
||||
MMAL_PARAM_STC_MODE_RAW, /**< Use raw clock STC, needed for true pause/resume support */
|
||||
MMAL_PARAM_STC_MODE_COOKED, /**< Start the STC from the start of capture, only for quick demo code */
|
||||
MMAL_PARAM_STC_MODE_MAX = 0x7fffffff
|
||||
} MMAL_CAMERA_STC_MODE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_CAMERA_STC_MODE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_CAMERA_STC_MODE_T value;
|
||||
} MMAL_PARAMETER_CAMERA_STC_MODE_T;
|
||||
|
||||
typedef enum MMAL_PARAM_FLICKERAVOID_T
|
||||
{
|
||||
MMAL_PARAM_FLICKERAVOID_OFF,
|
||||
MMAL_PARAM_FLICKERAVOID_AUTO,
|
||||
MMAL_PARAM_FLICKERAVOID_50HZ,
|
||||
MMAL_PARAM_FLICKERAVOID_60HZ,
|
||||
MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF
|
||||
} MMAL_PARAM_FLICKERAVOID_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FLICKERAVOID_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_FLICKERAVOID_T value; /**< Flicker avoidance mode */
|
||||
} MMAL_PARAMETER_FLICKERAVOID_T;
|
||||
|
||||
typedef enum MMAL_PARAM_FLASH_T
|
||||
{
|
||||
MMAL_PARAM_FLASH_OFF,
|
||||
MMAL_PARAM_FLASH_AUTO,
|
||||
MMAL_PARAM_FLASH_ON,
|
||||
MMAL_PARAM_FLASH_REDEYE,
|
||||
MMAL_PARAM_FLASH_FILLIN,
|
||||
MMAL_PARAM_FLASH_TORCH,
|
||||
MMAL_PARAM_FLASH_MAX = 0x7FFFFFFF
|
||||
} MMAL_PARAM_FLASH_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FLASH_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_FLASH_T value; /**< Flash mode */
|
||||
} MMAL_PARAMETER_FLASH_T;
|
||||
|
||||
typedef enum MMAL_PARAM_REDEYE_T
|
||||
{
|
||||
MMAL_PARAM_REDEYE_OFF,
|
||||
MMAL_PARAM_REDEYE_ON,
|
||||
MMAL_PARAM_REDEYE_SIMPLE,
|
||||
MMAL_PARAM_REDEYE_MAX = 0x7FFFFFFF
|
||||
} MMAL_PARAM_REDEYE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_REDEYE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_REDEYE_T value; /**< Red eye reduction mode */
|
||||
} MMAL_PARAMETER_REDEYE_T;
|
||||
|
||||
typedef enum MMAL_PARAM_FOCUS_T
|
||||
{
|
||||
MMAL_PARAM_FOCUS_AUTO,
|
||||
MMAL_PARAM_FOCUS_AUTO_NEAR,
|
||||
MMAL_PARAM_FOCUS_AUTO_MACRO,
|
||||
MMAL_PARAM_FOCUS_CAF,
|
||||
MMAL_PARAM_FOCUS_CAF_NEAR,
|
||||
MMAL_PARAM_FOCUS_FIXED_INFINITY,
|
||||
MMAL_PARAM_FOCUS_FIXED_HYPERFOCAL,
|
||||
MMAL_PARAM_FOCUS_FIXED_NEAR,
|
||||
MMAL_PARAM_FOCUS_FIXED_MACRO,
|
||||
MMAL_PARAM_FOCUS_EDOF,
|
||||
MMAL_PARAM_FOCUS_CAF_MACRO,
|
||||
MMAL_PARAM_FOCUS_CAF_FAST,
|
||||
MMAL_PARAM_FOCUS_CAF_NEAR_FAST,
|
||||
MMAL_PARAM_FOCUS_CAF_MACRO_FAST,
|
||||
MMAL_PARAM_FOCUS_FIXED_CURRENT,
|
||||
MMAL_PARAM_FOCUS_MAX = 0x7FFFFFFF
|
||||
} MMAL_PARAM_FOCUS_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FOCUS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_FOCUS_T value; /**< Focus mode */
|
||||
} MMAL_PARAMETER_FOCUS_T;
|
||||
|
||||
typedef enum MMAL_PARAM_CAPTURE_STATUS_T
|
||||
{
|
||||
MMAL_PARAM_CAPTURE_STATUS_NOT_CAPTURING,
|
||||
MMAL_PARAM_CAPTURE_STATUS_CAPTURE_STARTED,
|
||||
MMAL_PARAM_CAPTURE_STATUS_CAPTURE_ENDED,
|
||||
|
||||
MMAL_PARAM_CAPTURE_STATUS_MAX = 0x7FFFFFFF
|
||||
} MMAL_PARAM_CAPTURE_STATUS_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_CAPTURE_STATUS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_CAPTURE_STATUS_T status; /**< Capture status */
|
||||
} MMAL_PARAMETER_CAPTURE_STATUS_T;
|
||||
|
||||
typedef enum MMAL_PARAM_FOCUS_STATUS_T
|
||||
{
|
||||
MMAL_PARAM_FOCUS_STATUS_OFF,
|
||||
MMAL_PARAM_FOCUS_STATUS_REQUEST,
|
||||
MMAL_PARAM_FOCUS_STATUS_REACHED,
|
||||
MMAL_PARAM_FOCUS_STATUS_UNABLE_TO_REACH,
|
||||
MMAL_PARAM_FOCUS_STATUS_LOST,
|
||||
MMAL_PARAM_FOCUS_STATUS_CAF_MOVING,
|
||||
MMAL_PARAM_FOCUS_STATUS_CAF_SUCCESS,
|
||||
MMAL_PARAM_FOCUS_STATUS_CAF_FAILED,
|
||||
MMAL_PARAM_FOCUS_STATUS_MANUAL_MOVING,
|
||||
MMAL_PARAM_FOCUS_STATUS_MANUAL_REACHED,
|
||||
MMAL_PARAM_FOCUS_STATUS_CAF_WATCHING,
|
||||
MMAL_PARAM_FOCUS_STATUS_CAF_SCENE_CHANGED,
|
||||
|
||||
MMAL_PARAM_FOCUS_STATUS_MAX = 0x7FFFFFFF
|
||||
} MMAL_PARAM_FOCUS_STATUS_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FOCUS_STATUS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_FOCUS_STATUS_T status; /**< Focus status */
|
||||
} MMAL_PARAMETER_FOCUS_STATUS_T;
|
||||
|
||||
typedef enum MMAL_PARAM_FACE_TRACK_MODE_T
|
||||
{
|
||||
MMAL_PARAM_FACE_DETECT_NONE, /**< Disables face detection */
|
||||
MMAL_PARAM_FACE_DETECT_ON, /**< Enables face detection */
|
||||
MMAL_PARAM_FACE_DETECT_MAX = 0x7FFFFFFF
|
||||
} MMAL_PARAM_FACE_TRACK_MODE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FACE_TRACK_T /* face tracking control */
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_PARAM_FACE_TRACK_MODE_T mode;
|
||||
uint32_t maxRegions;
|
||||
uint32_t frames;
|
||||
uint32_t quality;
|
||||
} MMAL_PARAMETER_FACE_TRACK_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FACE_TRACK_FACE_T /* face tracking face information */
|
||||
{
|
||||
int32_t face_id; /**< Face ID. Should remain the same whilst the face is detected to remain in the scene */
|
||||
int32_t score; /**< Confidence of the face detection. Range 1-100 (1=unsure, 100=positive). */
|
||||
MMAL_RECT_T face_rect; /**< Rectangle around the whole face */
|
||||
|
||||
MMAL_RECT_T eye_rect[2]; /**< Rectangle around the eyes ([0] = left eye, [1] = right eye) */
|
||||
MMAL_RECT_T mouth_rect; /**< Rectangle around the mouth */
|
||||
} MMAL_PARAMETER_FACE_TRACK_FACE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FACE_TRACK_RESULTS_T /* face tracking results */
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t num_faces; /**< Number of faces detected */
|
||||
uint32_t frame_width; /**< Width of the frame on which the faces were detected (allows scaling) */
|
||||
uint32_t frame_height; /**< Height of the frame on which the faces were detected (allows scaling) */
|
||||
|
||||
MMAL_PARAMETER_FACE_TRACK_FACE_T faces[1]; /**< Face information (variable length array */
|
||||
} MMAL_PARAMETER_FACE_TRACK_RESULTS_T;
|
||||
|
||||
typedef enum MMAL_PARAMETER_CAMERA_CONFIG_TIMESTAMP_MODE_T
|
||||
{
|
||||
MMAL_PARAM_TIMESTAMP_MODE_ZERO, /**< Always timestamp frames as 0 */
|
||||
MMAL_PARAM_TIMESTAMP_MODE_RAW_STC, /**< Use the raw STC value for the frame timestamp */
|
||||
MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /**< Use the STC timestamp but subtract the timestamp
|
||||
* of the first frame sent to give a zero based timestamp.
|
||||
*/
|
||||
MMAL_PARAM_TIMESTAMP_MODE_MAX = 0x7FFFFFFF
|
||||
} MMAL_PARAMETER_CAMERA_CONFIG_TIMESTAMP_MODE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_CAMERA_CONFIG_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
/* Parameters for setting up the image pools */
|
||||
uint32_t max_stills_w; /**< Max size of stills capture */
|
||||
uint32_t max_stills_h;
|
||||
uint32_t stills_yuv422; /**< Allow YUV422 stills capture */
|
||||
uint32_t one_shot_stills; /**< Continuous or one shot stills captures. */
|
||||
|
||||
uint32_t max_preview_video_w; /**< Max size of the preview or video capture frames */
|
||||
uint32_t max_preview_video_h;
|
||||
uint32_t num_preview_video_frames;
|
||||
|
||||
uint32_t stills_capture_circular_buffer_height; /**< Sets the height of the circular buffer for stills capture. */
|
||||
|
||||
uint32_t fast_preview_resume; /**< Allows preview/encode to resume as fast as possible after the stills input frame
|
||||
* has been received, and then processes the still frame in the background
|
||||
* whilst preview/encode has resumed.
|
||||
* Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE.
|
||||
*/
|
||||
|
||||
MMAL_PARAMETER_CAMERA_CONFIG_TIMESTAMP_MODE_T use_stc_timestamp;
|
||||
/**< Selects algorithm for timestamping frames if there is no clock component connected.
|
||||
*/
|
||||
|
||||
|
||||
} MMAL_PARAMETER_CAMERA_CONFIG_T;
|
||||
|
||||
#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4
|
||||
#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2
|
||||
|
||||
typedef struct MMAL_PARAMETER_CAMERA_INFO_CAMERA_T
|
||||
{
|
||||
uint32_t port_id;
|
||||
uint32_t max_width;
|
||||
uint32_t max_height;
|
||||
MMAL_BOOL_T lens_present;
|
||||
} MMAL_PARAMETER_CAMERA_INFO_CAMERA_T;
|
||||
|
||||
typedef enum MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_T
|
||||
{
|
||||
MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0, /* Make values explicit */
|
||||
MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED = 1, /* to ensure they match */
|
||||
MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2, /* values in config ini */
|
||||
MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF
|
||||
} MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_CAMERA_INFO_FLASH_T
|
||||
{
|
||||
MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_T flash_type;
|
||||
} MMAL_PARAMETER_CAMERA_INFO_FLASH_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_CAMERA_INFO_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
uint32_t num_cameras;
|
||||
uint32_t num_flashes;
|
||||
MMAL_PARAMETER_CAMERA_INFO_CAMERA_T cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS];
|
||||
MMAL_PARAMETER_CAMERA_INFO_FLASH_T flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES];
|
||||
} MMAL_PARAMETER_CAMERA_INFO_T;
|
||||
|
||||
typedef enum MMAL_PARAMETER_CAPTUREMODE_MODE_T
|
||||
{
|
||||
MMAL_PARAM_CAPTUREMODE_WAIT_FOR_END, /**< Resumes preview once capture is completed. */
|
||||
MMAL_PARAM_CAPTUREMODE_WAIT_FOR_END_AND_HOLD, /**< Resumes preview once capture is completed, and hold the image for subsequent reprocessing. */
|
||||
MMAL_PARAM_CAPTUREMODE_RESUME_VF_IMMEDIATELY, /**< Resumes preview as soon as possible once capture frame is received from the sensor.
|
||||
* Requires fast_preview_resume to be set via MMAL_PARAMETER_CAMERA_CONFIG.
|
||||
*/
|
||||
} MMAL_PARAMETER_CAPTUREMODE_MODE_T;
|
||||
|
||||
/** Stills capture mode control. */
|
||||
typedef struct MMAL_PARAMETER_CAPTUREMODE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_PARAMETER_CAPTUREMODE_MODE_T mode;
|
||||
} MMAL_PARAMETER_CAPTUREMODE_T;
|
||||
|
||||
typedef enum MMAL_PARAMETER_FOCUS_REGION_TYPE_T
|
||||
{
|
||||
MMAL_PARAMETER_FOCUS_REGION_TYPE_NORMAL, /**< Region defines a generic region */
|
||||
MMAL_PARAMETER_FOCUS_REGION_TYPE_FACE, /**< Region defines a face */
|
||||
MMAL_PARAMETER_FOCUS_REGION_TYPE_MAX
|
||||
} MMAL_PARAMETER_FOCUS_REGION_TYPE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FOCUS_REGION_T
|
||||
{
|
||||
MMAL_RECT_T rect; /**< Focus rectangle as 0P16 fixed point values. */
|
||||
uint32_t weight; /**< Region weighting. */
|
||||
uint32_t mask; /**< Mask for multi-stage regions */
|
||||
MMAL_PARAMETER_FOCUS_REGION_TYPE_T type; /**< Region type */
|
||||
} MMAL_PARAMETER_FOCUS_REGION_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FOCUS_REGIONS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
uint32_t num_regions; /**< Number of regions defined */
|
||||
MMAL_BOOL_T lock_to_faces; /**< If region is within tolerance of a face, adopt face rect instead of defined region */
|
||||
MMAL_PARAMETER_FOCUS_REGION_T regions[1]; /**< Variable number of regions */
|
||||
} MMAL_PARAMETER_FOCUS_REGIONS_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_INPUT_CROP_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_RECT_T rect; /**< Crop rectangle as 16P16 fixed point values */
|
||||
} MMAL_PARAMETER_INPUT_CROP_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_SENSOR_INFORMATION_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_RATIONAL_T f_number; /**< Lens f-number */
|
||||
MMAL_RATIONAL_T focal_length; /**< Lens focal length */
|
||||
uint32_t model_id; /**< Sensor reported model id */
|
||||
uint32_t manufacturer_id; /**< Sensor reported manufacturer id */
|
||||
uint32_t revision; /**< Sensor reported revision */
|
||||
} MMAL_PARAMETER_SENSOR_INFORMATION_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FLASH_SELECT_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_T flash_type; /**< Flash type to use */
|
||||
} MMAL_PARAMETER_FLASH_SELECT_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FIELD_OF_VIEW_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_RATIONAL_T fov_h; /**< Horizontal field of view */
|
||||
MMAL_RATIONAL_T fov_v; /**< Vertical field of view */
|
||||
} MMAL_PARAMETER_FIELD_OF_VIEW_T;
|
||||
|
||||
typedef enum MMAL_PARAMETER_DRC_STRENGTH_T
|
||||
{
|
||||
MMAL_PARAMETER_DRC_STRENGTH_OFF,
|
||||
MMAL_PARAMETER_DRC_STRENGTH_LOW,
|
||||
MMAL_PARAMETER_DRC_STRENGTH_MEDIUM,
|
||||
MMAL_PARAMETER_DRC_STRENGTH_HIGH,
|
||||
MMAL_PARAMETER_DRC_STRENGTH_MAX = 0x7fffffff
|
||||
} MMAL_PARAMETER_DRC_STRENGTH_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_DRC_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_PARAMETER_DRC_STRENGTH_T strength; /**< DRC strength */
|
||||
} MMAL_PARAMETER_DRC_T;
|
||||
|
||||
typedef enum MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_T
|
||||
{
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_FACETRACKING,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_REDEYE_REDUCTION,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_VIDEO_STABILISATION,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_WRITE_RAW,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_VIDEO_DENOISE,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_STILLS_DENOISE,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_TEMPORAL_DENOISE,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_ANTISHAKE,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_IMAGE_EFFECTS,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_DYNAMIC_RANGE_COMPRESSION,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_FACE_RECOGNITION,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_FACE_BEAUTIFICATION,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_SCENE_DETECTION,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_HIGH_DYNAMIC_RANGE,
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_MAX = 0x7fffffff
|
||||
} MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_ALGORITHM_CONTROL_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_T algorithm;
|
||||
MMAL_BOOL_T enabled;
|
||||
} MMAL_PARAMETER_ALGORITHM_CONTROL_T;
|
||||
|
||||
|
||||
typedef enum MMAL_PARAM_CAMERA_USE_CASE_T
|
||||
{
|
||||
MMAL_PARAM_CAMERA_USE_CASE_UNKNOWN, /**< Compromise on behaviour as use case totally unknown */
|
||||
MMAL_PARAM_CAMERA_USE_CASE_STILLS_CAPTURE, /**< Stills capture use case */
|
||||
MMAL_PARAM_CAMERA_USE_CASE_VIDEO_CAPTURE, /**< Video encode (camcorder) use case */
|
||||
|
||||
MMAL_PARAM_CAMERA_USE_CASE_MAX = 0x7fffffff
|
||||
} MMAL_PARAM_CAMERA_USE_CASE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_CAMERA_USE_CASE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_CAMERA_USE_CASE_T use_case; /**< Use case */
|
||||
} MMAL_PARAMETER_CAMERA_USE_CASE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_FPS_RANGE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_RATIONAL_T fps_low; /**< Low end of the permitted framerate range */
|
||||
MMAL_RATIONAL_T fps_high; /**< High end of the permitted framerate range */
|
||||
} MMAL_PARAMETER_FPS_RANGE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_ZEROSHUTTERLAG_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_BOOL_T zero_shutter_lag_mode; /**< Select zero shutter lag mode from sensor */
|
||||
MMAL_BOOL_T concurrent_capture; /**< Activate full zero shutter lag mode and
|
||||
* use the last preview raw image for the stills capture
|
||||
*/
|
||||
} MMAL_PARAMETER_ZEROSHUTTERLAG_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_AWB_GAINS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_RATIONAL_T r_gain; /**< Red gain */
|
||||
MMAL_RATIONAL_T b_gain; /**< Blue gain */
|
||||
} MMAL_PARAMETER_AWB_GAINS_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_CAMERA_SETTINGS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t exposure;
|
||||
MMAL_RATIONAL_T analog_gain;
|
||||
MMAL_RATIONAL_T digital_gain;
|
||||
MMAL_RATIONAL_T awb_red_gain;
|
||||
MMAL_RATIONAL_T awb_blue_gain;
|
||||
uint32_t focus_position;
|
||||
} MMAL_PARAMETER_CAMERA_SETTINGS_T;
|
||||
|
||||
typedef enum MMAL_PARAM_PRIVACY_INDICATOR_T
|
||||
{
|
||||
MMAL_PARAMETER_PRIVACY_INDICATOR_OFF, /**< Indicator will be off. */
|
||||
MMAL_PARAMETER_PRIVACY_INDICATOR_ON, /**< Indicator will come on just after a stills capture and
|
||||
* and remain on for 2seconds, or will be on whilst output[1]
|
||||
* is actively producing images.
|
||||
*/
|
||||
MMAL_PARAMETER_PRIVACY_INDICATOR_FORCE_ON, /**< Turns indicator of for 2s independent of capture status.
|
||||
* Set this mode repeatedly to keep the indicator on for a
|
||||
* longer period.
|
||||
*/
|
||||
MMAL_PARAMETER_PRIVACY_INDICATOR_MAX = 0x7fffffff
|
||||
} MMAL_PARAM_PRIVACY_INDICATOR_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_PRIVACY_INDICATOR_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_PARAM_PRIVACY_INDICATOR_T mode;
|
||||
} MMAL_PARAMETER_PRIVACY_INDICATOR_T;
|
||||
|
||||
#define MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN 32
|
||||
typedef struct MMAL_PARAMETER_CAMERA_ANNOTATE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_BOOL_T enable;
|
||||
char text[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN];
|
||||
MMAL_BOOL_T show_shutter;
|
||||
MMAL_BOOL_T show_analog_gain;
|
||||
MMAL_BOOL_T show_lens;
|
||||
MMAL_BOOL_T show_caf;
|
||||
MMAL_BOOL_T show_motion;
|
||||
} MMAL_PARAMETER_CAMERA_ANNOTATE_T;
|
||||
|
||||
#define MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V2 256
|
||||
typedef struct MMAL_PARAMETER_CAMERA_ANNOTATE_V2_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_BOOL_T enable;
|
||||
MMAL_BOOL_T show_shutter;
|
||||
MMAL_BOOL_T show_analog_gain;
|
||||
MMAL_BOOL_T show_lens;
|
||||
MMAL_BOOL_T show_caf;
|
||||
MMAL_BOOL_T show_motion;
|
||||
MMAL_BOOL_T show_frame_num;
|
||||
MMAL_BOOL_T black_text_background;
|
||||
char text[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V2];
|
||||
} MMAL_PARAMETER_CAMERA_ANNOTATE_V2_T;
|
||||
|
||||
typedef enum MMAL_STEREOSCOPIC_MODE_T {
|
||||
MMAL_STEREOSCOPIC_MODE_NONE = 0,
|
||||
MMAL_STEREOSCOPIC_MODE_SIDE_BY_SIDE = 1,
|
||||
MMAL_STEREOSCOPIC_MODE_TOP_BOTTOM = 2,
|
||||
MMAL_STEREOSCOPIC_MODE_MAX = 0x7FFFFFFF,
|
||||
} MMAL_STEREOSCOPIC_MODE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_STEREOSCOPIC_MODE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_STEREOSCOPIC_MODE_T mode;
|
||||
MMAL_BOOL_T decimate;
|
||||
MMAL_BOOL_T swap_eyes;
|
||||
} MMAL_PARAMETER_STEREOSCOPIC_MODE_T;
|
||||
|
||||
#endif /* MMAL_PARAMETERS_CAMERA_H */
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_PARAMETERS_CLOCK_H
|
||||
#define MMAL_PARAMETERS_CLOCK_H
|
||||
|
||||
#include "mmal_clock.h"
|
||||
#include "mmal_parameters_common.h"
|
||||
|
||||
/*************************************************
|
||||
* ALWAYS ADD NEW ENUMS AT THE END OF THIS LIST! *
|
||||
************************************************/
|
||||
|
||||
/** Clock-specific MMAL parameter IDs.
|
||||
* @ingroup MMAL_PARAMETER_IDS
|
||||
*/
|
||||
enum
|
||||
{
|
||||
MMAL_PARAMETER_CLOCK_REFERENCE /**< Takes a MMAL_PARAMETER_BOOLEAN_T */
|
||||
= MMAL_PARAMETER_GROUP_CLOCK,
|
||||
MMAL_PARAMETER_CLOCK_ACTIVE, /**< Takes a MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_CLOCK_SCALE, /**< Takes a MMAL_PARAMETER_RATIONAL_T */
|
||||
MMAL_PARAMETER_CLOCK_TIME, /**< Takes a MMAL_PARAMETER_INT64_T */
|
||||
MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD, /**< Takes a MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD_T */
|
||||
MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD, /**< Takes a MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD_T */
|
||||
MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD, /**< Takes a MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD_T */
|
||||
MMAL_PARAMETER_CLOCK_ENABLE_BUFFER_INFO, /**< Takes a MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_CLOCK_FRAME_RATE, /**< Takes a MMAL_PARAMETER_RATIONAL_T */
|
||||
MMAL_PARAMETER_CLOCK_LATENCY, /**< Takes a MMAL_PARAMETER_CLOCK_LATENCY_T */
|
||||
};
|
||||
|
||||
/** Media-time update thresholds */
|
||||
typedef struct MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_CLOCK_UPDATE_THRESHOLD_T value;
|
||||
} MMAL_PARAMETER_CLOCK_UPDATE_THRESHOLD_T;
|
||||
|
||||
/** Media-time discontinuity settings */
|
||||
typedef struct MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_CLOCK_DISCONT_THRESHOLD_T value;
|
||||
} MMAL_PARAMETER_CLOCK_DISCONT_THRESHOLD_T;
|
||||
|
||||
/** Media-time future frame drop settings */
|
||||
typedef struct MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_CLOCK_REQUEST_THRESHOLD_T value;
|
||||
} MMAL_PARAMETER_CLOCK_REQUEST_THRESHOLD_T;
|
||||
|
||||
/** Clock latency parameter */
|
||||
typedef struct MMAL_PARAMETER_CLOCK_LATENCY_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_CLOCK_LATENCY_T value;
|
||||
} MMAL_PARAMETER_CLOCK_LATENCY_T;
|
||||
|
||||
#endif /* MMAL_PARAMETERS_CLOCK_H */
|
@ -1,191 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_PARAMETERS_COMMON_H
|
||||
#define MMAL_PARAMETERS_COMMON_H
|
||||
|
||||
/** @defgroup MMAL_PARAMETER_IDS Pre-defined MMAL parameter IDs
|
||||
* @ingroup MmalParameters
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @name Parameter groups
|
||||
* Parameters are divided into groups, and then allocated sequentially within
|
||||
* a group using an enum.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Common parameter ID group, used with many types of component. */
|
||||
#define MMAL_PARAMETER_GROUP_COMMON (0<<16)
|
||||
/** Camera-specific parameter ID group. */
|
||||
#define MMAL_PARAMETER_GROUP_CAMERA (1<<16)
|
||||
/** Video-specific parameter ID group. */
|
||||
#define MMAL_PARAMETER_GROUP_VIDEO (2<<16)
|
||||
/** Audio-specific parameter ID group. */
|
||||
#define MMAL_PARAMETER_GROUP_AUDIO (3<<16)
|
||||
/** Clock-specific parameter ID group. */
|
||||
#define MMAL_PARAMETER_GROUP_CLOCK (4<<16)
|
||||
/** Miracast-specific parameter ID group. */
|
||||
#define MMAL_PARAMETER_GROUP_MIRACAST (5<<16)
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** Common MMAL parameter IDs.
|
||||
*/
|
||||
enum {
|
||||
MMAL_PARAMETER_UNUSED /**< Never a valid parameter ID */
|
||||
= MMAL_PARAMETER_GROUP_COMMON,
|
||||
MMAL_PARAMETER_SUPPORTED_ENCODINGS, /**< Takes a MMAL_PARAMETER_ENCODING_T */
|
||||
MMAL_PARAMETER_URI, /**< Takes a MMAL_PARAMETER_URI_T */
|
||||
MMAL_PARAMETER_CHANGE_EVENT_REQUEST, /**< Takes a MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
|
||||
MMAL_PARAMETER_ZERO_COPY, /**< Takes a MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_BUFFER_REQUIREMENTS, /**< Takes a MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
|
||||
MMAL_PARAMETER_STATISTICS, /**< Takes a MMAL_PARAMETER_STATISTICS_T */
|
||||
MMAL_PARAMETER_CORE_STATISTICS, /**< Takes a MMAL_PARAMETER_CORE_STATISTICS_T */
|
||||
MMAL_PARAMETER_MEM_USAGE, /**< Takes a MMAL_PARAMETER_MEM_USAGE_T */
|
||||
MMAL_PARAMETER_BUFFER_FLAG_FILTER, /**< Takes a MMAL_PARAMETER_UINT32_T */
|
||||
MMAL_PARAMETER_SEEK, /**< Takes a MMAL_PARAMETER_SEEK_T */
|
||||
MMAL_PARAMETER_POWERMON_ENABLE, /**< Takes a MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_LOGGING, /**< Takes a MMAL_PARAMETER_LOGGING_T */
|
||||
MMAL_PARAMETER_SYSTEM_TIME, /**< Takes a MMAL_PARAMETER_UINT64_T */
|
||||
MMAL_PARAMETER_NO_IMAGE_PADDING, /**< Takes a MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_LOCKSTEP_ENABLE /**< Takes a MMAL_PARAMETER_BOOLEAN_T */
|
||||
};
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** Parameter header type. All parameter structures need to begin with this type.
|
||||
* The \ref id field must be set to a parameter ID, such as one of those listed on
|
||||
* the \ref MMAL_PARAMETER_IDS "Pre-defined MMAL parameter IDs" page.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_HEADER_T
|
||||
{
|
||||
uint32_t id; /**< Parameter ID. */
|
||||
uint32_t size; /**< Size in bytes of the parameter (including the header) */
|
||||
} MMAL_PARAMETER_HEADER_T;
|
||||
|
||||
/** Change event request parameter type.
|
||||
* This is used to control whether a \ref MMAL_EVENT_PARAMETER_CHANGED_T event
|
||||
* is issued should a given parameter change.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t change_id; /**< ID of parameter that may change, see \ref MMAL_PARAMETER_IDS */
|
||||
MMAL_BOOL_T enable; /**< True if the event is enabled, false if disabled */
|
||||
} MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T;
|
||||
|
||||
/** Buffer requirements parameter.
|
||||
* This is mainly used to increase the requirements of a component. */
|
||||
typedef struct MMAL_PARAMETER_BUFFER_REQUIREMENTS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t buffer_num_min; /**< Minimum number of buffers the port requires */
|
||||
uint32_t buffer_size_min; /**< Minimum size of buffers the port requires */
|
||||
uint32_t buffer_alignment_min; /**< Minimum alignment requirement for the buffers.
|
||||
A value of zero means no special alignment requirements. */
|
||||
uint32_t buffer_num_recommended; /**< Number of buffers the port recommends for optimal performance.
|
||||
A value of zero means no special recommendation. */
|
||||
uint32_t buffer_size_recommended; /**< Size of buffers the port recommends for optimal performance.
|
||||
A value of zero means no special recommendation. */
|
||||
} MMAL_PARAMETER_BUFFER_REQUIREMENTS_T;
|
||||
|
||||
/** Seek request parameter type.
|
||||
* This is used to issue a seek request to a source component.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_SEEK_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
int64_t offset; /**< Offset (in microseconds) to seek to */
|
||||
uint32_t flags; /**< Seeking flags */
|
||||
|
||||
#define MMAL_PARAM_SEEK_FLAG_PRECISE 0x1 /**< Choose precise seeking even if slower */
|
||||
#define MMAL_PARAM_SEEK_FLAG_FORWARD 0x2 /**< Seek to the next keyframe following the specified offset */
|
||||
|
||||
} MMAL_PARAMETER_SEEK_T;
|
||||
|
||||
/** Port statistics for debugging/test purposes.
|
||||
* Ports may support query of this parameter to return statistics for debugging or
|
||||
* test purposes. Not all values may be relevant for a given port.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_STATISTICS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t buffer_count; /**< Total number of buffers processed */
|
||||
uint32_t frame_count; /**< Total number of frames processed */
|
||||
uint32_t frames_skipped; /**< Number of frames without expected PTS based on frame rate */
|
||||
uint32_t frames_discarded; /**< Number of frames discarded */
|
||||
uint32_t eos_seen; /**< Set if the end of stream has been reached */
|
||||
uint32_t maximum_frame_bytes; /**< Maximum frame size in bytes */
|
||||
int64_t total_bytes; /**< Total number of bytes processed */
|
||||
uint32_t corrupt_macroblocks; /**< Number of corrupt macroblocks in the stream */
|
||||
} MMAL_PARAMETER_STATISTICS_T;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MMAL_CORE_STATS_RX,
|
||||
MMAL_CORE_STATS_TX,
|
||||
MMAL_CORE_STATS_MAX = 0x7fffffff /* Force 32 bit size for this enum */
|
||||
} MMAL_CORE_STATS_DIR;
|
||||
|
||||
/** MMAL core statistics. These are collected by the core itself.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_CORE_STATISTICS_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_CORE_STATS_DIR dir;
|
||||
MMAL_BOOL_T reset; /**< Reset to zero after reading */
|
||||
MMAL_CORE_STATISTICS_T stats; /**< The statistics */
|
||||
} MMAL_PARAMETER_CORE_STATISTICS_T;
|
||||
|
||||
/**
|
||||
* Component memory usage statistics.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_MEM_USAGE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
/**< The amount of memory allocated in image pools by the component */
|
||||
uint32_t pool_mem_alloc_size;
|
||||
} MMAL_PARAMETER_MEM_USAGE_T;
|
||||
|
||||
/**
|
||||
* Logging control.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_LOGGING_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
uint32_t set; /**< Logging bits to set */
|
||||
uint32_t clear; /**< Logging bits to clear */
|
||||
} MMAL_PARAMETER_LOGGING_T;
|
||||
|
||||
#endif /* MMAL_PARAMETERS_COMMON_H */
|
||||
|
@ -1,486 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_PARAMETERS_VIDEO_H
|
||||
#define MMAL_PARAMETERS_VIDEO_H
|
||||
|
||||
#include "mmal_parameters_common.h"
|
||||
|
||||
/*************************************************
|
||||
* ALWAYS ADD NEW ENUMS AT THE END OF THIS LIST! *
|
||||
************************************************/
|
||||
|
||||
/** Video-specific MMAL parameter IDs.
|
||||
* @ingroup MMAL_PARAMETER_IDS
|
||||
*/
|
||||
enum {
|
||||
MMAL_PARAMETER_DISPLAYREGION /**< Takes a @ref MMAL_DISPLAYREGION_T */
|
||||
= MMAL_PARAMETER_GROUP_VIDEO,
|
||||
MMAL_PARAMETER_SUPPORTED_PROFILES, /**< Takes a @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
|
||||
MMAL_PARAMETER_PROFILE, /**< Takes a @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
|
||||
MMAL_PARAMETER_INTRAPERIOD, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
|
||||
MMAL_PARAMETER_RATECONTROL, /**< Takes a @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
|
||||
MMAL_PARAMETER_NALUNITFORMAT, /**< Takes a @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
|
||||
MMAL_PARAMETER_MINIMISE_FRAGMENTATION, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_MB_ROWS_PER_SLICE, /**< Takes a @ref MMAL_PARAMETER_UINT32_T.
|
||||
* Setting the value to zero resets to the default (one slice per frame). */
|
||||
MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION, /**< Takes a @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
|
||||
MMAL_PARAMETER_VIDEO_EEDE_ENABLE, /**< Takes a @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
|
||||
MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE, /**< Takes a @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
|
||||
MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T.
|
||||
* Request an I-frame. */
|
||||
MMAL_PARAMETER_VIDEO_INTRA_REFRESH, /**< Takes a @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */
|
||||
MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_BIT_RATE, /**< Takes a @ref MMAL_PARAMETER_UINT32_T.
|
||||
* Run-time bit rate control */
|
||||
MMAL_PARAMETER_VIDEO_FRAME_RATE, /**< Takes a @ref MMAL_PARAMETER_FRAME_RATE_T */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, /**< Takes a @ref MMAL_PARAMETER_UINT32_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, /**< Takes a @ref MMAL_PARAMETER_UINT32_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL, /**< Takes a @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
|
||||
MMAL_PARAMETER_EXTRA_BUFFERS, /**< Takes a @ref MMAL_PARAMETER_UINT32_T. */
|
||||
MMAL_PARAMETER_VIDEO_ALIGN_HORIZ, /**< Takes a @ref MMAL_PARAMETER_UINT32_T.
|
||||
Changing this paramater from the default can reduce frame rate
|
||||
because image buffers need to be re-pitched.*/
|
||||
MMAL_PARAMETER_VIDEO_ALIGN_VERT, /**< Takes a @ref MMAL_PARAMETER_UINT32_T.
|
||||
Changing this paramater from the default can reduce frame rate
|
||||
because image buffers need to be re-pitched.*/
|
||||
MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES, /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, /**< Takes a @ref MMAL_PARAMETER_UINT32_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_QP_P, /**< Takes a @ref MMAL_PARAMETER_UINT32_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT, /**< Takes a @ref MMAL_PARAMETER_UINT32_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE, /**< Takes a @ref MMAL_PARAMETER_UINT32_T. */
|
||||
|
||||
/*H264 specific parameters*/
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC, /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY, /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS, /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC, /**< Takes a @ref MMAL_PARAMETER_UINT32_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE, /**< Takes a @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
|
||||
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
|
||||
MMAL_PARAMETER_VIDEO_DRM_INIT_INFO, /**< Takes a @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
|
||||
MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT, /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
|
||||
MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER, /**< Takes a @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
|
||||
|
||||
MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3, /**< Takes a @ref MMAL_PARAMETER_BYTES_T */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS, /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG, /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_SEI_ENABLE, /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS, /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T. */
|
||||
MMAL_PARAMETER_VIDEO_RENDER_STATS, /**< Take a @ref MMAL_PARAMETER_VIDEO_RENDER_STATS_T. */
|
||||
MMAL_PARAMETER_VIDEO_INTERLACE_TYPE, /**< Take a @ref MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T. */
|
||||
};
|
||||
|
||||
/** Display transformations.
|
||||
* Although an enumeration, the values correspond to combinations of:
|
||||
* \li 1 Reflect in a vertical axis
|
||||
* \li 2 180 degree rotation
|
||||
* \li 4 Reflect in the leading diagonal
|
||||
*/
|
||||
typedef enum MMAL_DISPLAYTRANSFORM_T {
|
||||
MMAL_DISPLAY_ROT0 = 0,
|
||||
MMAL_DISPLAY_MIRROR_ROT0 = 1,
|
||||
MMAL_DISPLAY_MIRROR_ROT180 = 2,
|
||||
MMAL_DISPLAY_ROT180 = 3,
|
||||
MMAL_DISPLAY_MIRROR_ROT90 = 4,
|
||||
MMAL_DISPLAY_ROT270 = 5,
|
||||
MMAL_DISPLAY_ROT90 = 6,
|
||||
MMAL_DISPLAY_MIRROR_ROT270 = 7,
|
||||
MMAL_DISPLAY_DUMMY = 0x7FFFFFFF
|
||||
} MMAL_DISPLAYTRANSFORM_T;
|
||||
|
||||
/** Display modes. */
|
||||
typedef enum MMAL_DISPLAYMODE_T {
|
||||
MMAL_DISPLAY_MODE_FILL = 0,
|
||||
MMAL_DISPLAY_MODE_LETTERBOX = 1,
|
||||
// these allow a left eye source->dest to be specified and the right eye mapping will be inferred by symmetry
|
||||
MMAL_DISPLAY_MODE_STEREO_LEFT_TO_LEFT = 2,
|
||||
MMAL_DISPLAY_MODE_STEREO_TOP_TO_TOP = 3,
|
||||
MMAL_DISPLAY_MODE_STEREO_LEFT_TO_TOP = 4,
|
||||
MMAL_DISPLAY_MODE_STEREO_TOP_TO_LEFT = 5,
|
||||
MMAL_DISPLAY_MODE_DUMMY = 0x7FFFFFFF
|
||||
} MMAL_DISPLAYMODE_T;
|
||||
|
||||
/** Values used to indicate which fields are used when setting the
|
||||
* display configuration */
|
||||
typedef enum MMAL_DISPLAYSET_T {
|
||||
MMAL_DISPLAY_SET_NONE = 0,
|
||||
MMAL_DISPLAY_SET_NUM = 1,
|
||||
MMAL_DISPLAY_SET_FULLSCREEN = 2,
|
||||
MMAL_DISPLAY_SET_TRANSFORM = 4,
|
||||
MMAL_DISPLAY_SET_DEST_RECT = 8,
|
||||
MMAL_DISPLAY_SET_SRC_RECT = 0x10,
|
||||
MMAL_DISPLAY_SET_MODE = 0x20,
|
||||
MMAL_DISPLAY_SET_PIXEL = 0x40,
|
||||
MMAL_DISPLAY_SET_NOASPECT = 0x80,
|
||||
MMAL_DISPLAY_SET_LAYER = 0x100,
|
||||
MMAL_DISPLAY_SET_COPYPROTECT = 0x200,
|
||||
MMAL_DISPLAY_SET_ALPHA = 0x400,
|
||||
MMAL_DISPLAY_SET_DUMMY = 0x7FFFFFFF
|
||||
} MMAL_DISPLAYSET_T;
|
||||
|
||||
/**
|
||||
This config sets the output display device, as well as the region used
|
||||
on the output display, any display transformation, and some flags to
|
||||
indicate how to scale the image.
|
||||
*/
|
||||
|
||||
typedef struct MMAL_DISPLAYREGION_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
/** Bitfield that indicates which fields are set and should be used. All
|
||||
* other fields will maintain their current value.
|
||||
* \ref MMAL_DISPLAYSET_T defines the bits that can be combined.
|
||||
*/
|
||||
uint32_t set;
|
||||
/** Describes the display output device, with 0 typically being a directly
|
||||
* connected LCD display. The actual values will depend on the hardware.
|
||||
* Code using hard-wired numbers (e.g. 2) is certain to fail.
|
||||
*/
|
||||
uint32_t display_num;
|
||||
/** Indicates that we are using the full device screen area, rather than
|
||||
* a window of the display. If zero, then dest_rect is used to specify a
|
||||
* region of the display to use.
|
||||
*/
|
||||
MMAL_BOOL_T fullscreen;
|
||||
/** Indicates any rotation or flipping used to map frames onto the natural
|
||||
* display orientation.
|
||||
*/
|
||||
MMAL_DISPLAYTRANSFORM_T transform;
|
||||
/** Where to display the frame within the screen, if fullscreen is zero.
|
||||
*/
|
||||
MMAL_RECT_T dest_rect;
|
||||
/** Indicates which area of the frame to display. If all values are zero,
|
||||
* the whole frame will be used.
|
||||
*/
|
||||
MMAL_RECT_T src_rect;
|
||||
/** If set to non-zero, indicates that any display scaling should disregard
|
||||
* the aspect ratio of the frame region being displayed.
|
||||
*/
|
||||
MMAL_BOOL_T noaspect;
|
||||
/** Indicates how the image should be scaled to fit the display. \code
|
||||
* MMAL_DISPLAY_MODE_FILL \endcode indicates that the image should fill the
|
||||
* screen by potentially cropping the frames. Setting \code mode \endcode
|
||||
* to \code MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the source
|
||||
* region should be displayed and black bars added if necessary.
|
||||
*/
|
||||
MMAL_DISPLAYMODE_T mode;
|
||||
/** If non-zero, defines the width of a source pixel relative to \code pixel_y
|
||||
* \endcode. If zero, then pixels default to being square.
|
||||
*/
|
||||
uint32_t pixel_x;
|
||||
/** If non-zero, defines the height of a source pixel relative to \code pixel_x
|
||||
* \endcode. If zero, then pixels default to being square.
|
||||
*/
|
||||
uint32_t pixel_y;
|
||||
/** Sets the relative depth of the images, with greater values being in front
|
||||
* of smaller values.
|
||||
*/
|
||||
int32_t layer;
|
||||
/** Set to non-zero to ensure copy protection is used on output.
|
||||
*/
|
||||
MMAL_BOOL_T copyprotect_required;
|
||||
/** Level of opacity of the layer, where zero is fully transparent and
|
||||
* 255 is fully opaque.
|
||||
*/
|
||||
uint32_t alpha;
|
||||
} MMAL_DISPLAYREGION_T;
|
||||
|
||||
/** Video profiles.
|
||||
* Only certain combinations of profile and level will be valid.
|
||||
* @ref MMAL_VIDEO_LEVEL_T
|
||||
*/
|
||||
typedef enum MMAL_VIDEO_PROFILE_T {
|
||||
MMAL_VIDEO_PROFILE_H263_BASELINE,
|
||||
MMAL_VIDEO_PROFILE_H263_H320CODING,
|
||||
MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE,
|
||||
MMAL_VIDEO_PROFILE_H263_ISWV2,
|
||||
MMAL_VIDEO_PROFILE_H263_ISWV3,
|
||||
MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION,
|
||||
MMAL_VIDEO_PROFILE_H263_INTERNET,
|
||||
MMAL_VIDEO_PROFILE_H263_INTERLACE,
|
||||
MMAL_VIDEO_PROFILE_H263_HIGHLATENCY,
|
||||
MMAL_VIDEO_PROFILE_MP4V_SIMPLE,
|
||||
MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE,
|
||||
MMAL_VIDEO_PROFILE_MP4V_CORE,
|
||||
MMAL_VIDEO_PROFILE_MP4V_MAIN,
|
||||
MMAL_VIDEO_PROFILE_MP4V_NBIT,
|
||||
MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE,
|
||||
MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE,
|
||||
MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA,
|
||||
MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED,
|
||||
MMAL_VIDEO_PROFILE_MP4V_HYBRID,
|
||||
MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME,
|
||||
MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE,
|
||||
MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING,
|
||||
MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE,
|
||||
MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE,
|
||||
MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE,
|
||||
MMAL_VIDEO_PROFILE_H264_BASELINE,
|
||||
MMAL_VIDEO_PROFILE_H264_MAIN,
|
||||
MMAL_VIDEO_PROFILE_H264_EXTENDED,
|
||||
MMAL_VIDEO_PROFILE_H264_HIGH,
|
||||
MMAL_VIDEO_PROFILE_H264_HIGH10,
|
||||
MMAL_VIDEO_PROFILE_H264_HIGH422,
|
||||
MMAL_VIDEO_PROFILE_H264_HIGH444,
|
||||
MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE,
|
||||
MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF
|
||||
} MMAL_VIDEO_PROFILE_T;
|
||||
|
||||
/** Video levels.
|
||||
* Only certain combinations of profile and level will be valid.
|
||||
* @ref MMAL_VIDEO_PROFILE_T
|
||||
*/
|
||||
typedef enum MMAL_VIDEO_LEVEL_T {
|
||||
MMAL_VIDEO_LEVEL_H263_10,
|
||||
MMAL_VIDEO_LEVEL_H263_20,
|
||||
MMAL_VIDEO_LEVEL_H263_30,
|
||||
MMAL_VIDEO_LEVEL_H263_40,
|
||||
MMAL_VIDEO_LEVEL_H263_45,
|
||||
MMAL_VIDEO_LEVEL_H263_50,
|
||||
MMAL_VIDEO_LEVEL_H263_60,
|
||||
MMAL_VIDEO_LEVEL_H263_70,
|
||||
MMAL_VIDEO_LEVEL_MP4V_0,
|
||||
MMAL_VIDEO_LEVEL_MP4V_0b,
|
||||
MMAL_VIDEO_LEVEL_MP4V_1,
|
||||
MMAL_VIDEO_LEVEL_MP4V_2,
|
||||
MMAL_VIDEO_LEVEL_MP4V_3,
|
||||
MMAL_VIDEO_LEVEL_MP4V_4,
|
||||
MMAL_VIDEO_LEVEL_MP4V_4a,
|
||||
MMAL_VIDEO_LEVEL_MP4V_5,
|
||||
MMAL_VIDEO_LEVEL_MP4V_6,
|
||||
MMAL_VIDEO_LEVEL_H264_1,
|
||||
MMAL_VIDEO_LEVEL_H264_1b,
|
||||
MMAL_VIDEO_LEVEL_H264_11,
|
||||
MMAL_VIDEO_LEVEL_H264_12,
|
||||
MMAL_VIDEO_LEVEL_H264_13,
|
||||
MMAL_VIDEO_LEVEL_H264_2,
|
||||
MMAL_VIDEO_LEVEL_H264_21,
|
||||
MMAL_VIDEO_LEVEL_H264_22,
|
||||
MMAL_VIDEO_LEVEL_H264_3,
|
||||
MMAL_VIDEO_LEVEL_H264_31,
|
||||
MMAL_VIDEO_LEVEL_H264_32,
|
||||
MMAL_VIDEO_LEVEL_H264_4,
|
||||
MMAL_VIDEO_LEVEL_H264_41,
|
||||
MMAL_VIDEO_LEVEL_H264_42,
|
||||
MMAL_VIDEO_LEVEL_H264_5,
|
||||
MMAL_VIDEO_LEVEL_H264_51,
|
||||
MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF
|
||||
} MMAL_VIDEO_LEVEL_T;
|
||||
|
||||
/** Video profile and level setting.
|
||||
* This is a variable length structure when querying the supported profiles and
|
||||
* levels. To get more than one, pass a structure with more profile/level pairs.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_VIDEO_PROFILE_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
struct
|
||||
{
|
||||
MMAL_VIDEO_PROFILE_T profile;
|
||||
MMAL_VIDEO_LEVEL_T level;
|
||||
} profile[1];
|
||||
} MMAL_PARAMETER_VIDEO_PROFILE_T;
|
||||
|
||||
/** Manner of video rate control */
|
||||
typedef enum MMAL_VIDEO_RATECONTROL_T {
|
||||
MMAL_VIDEO_RATECONTROL_DEFAULT,
|
||||
MMAL_VIDEO_RATECONTROL_VARIABLE,
|
||||
MMAL_VIDEO_RATECONTROL_CONSTANT,
|
||||
MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES,
|
||||
MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES,
|
||||
MMAL_VIDEO_RATECONTROL_DUMMY = 0x7fffffff
|
||||
} MMAL_VIDEO_RATECONTROL_T;
|
||||
|
||||
/** Intra refresh modes */
|
||||
typedef enum MMAL_VIDEO_INTRA_REFRESH_T {
|
||||
MMAL_VIDEO_INTRA_REFRESH_CYCLIC,
|
||||
MMAL_VIDEO_INTRA_REFRESH_ADAPTIVE,
|
||||
MMAL_VIDEO_INTRA_REFRESH_BOTH,
|
||||
MMAL_VIDEO_INTRA_REFRESH_KHRONOSEXTENSIONS = 0x6F000000,
|
||||
MMAL_VIDEO_INTRA_REFRESH_VENDORSTARTUNUSED = 0x7F000000,
|
||||
MMAL_VIDEO_INTRA_REFRESH_CYCLIC_MROWS,
|
||||
MMAL_VIDEO_INTRA_REFRESH_PSEUDO_RAND,
|
||||
MMAL_VIDEO_INTRA_REFRESH_MAX,
|
||||
MMAL_VIDEO_INTRA_REFRESH_DUMMY = 0x7FFFFFFF
|
||||
} MMAL_VIDEO_INTRA_REFRESH_T;
|
||||
|
||||
/*Encode RC Models Supported*/
|
||||
typedef enum MMAL_VIDEO_ENCODE_RC_MODEL_T {
|
||||
MMAL_VIDEO_ENCODER_RC_MODEL_DEFAULT = 0,
|
||||
MMAL_VIDEO_ENCODER_RC_MODEL_JVT = MMAL_VIDEO_ENCODER_RC_MODEL_DEFAULT,
|
||||
MMAL_VIDEO_ENCODER_RC_MODEL_VOWIFI,
|
||||
MMAL_VIDEO_ENCODER_RC_MODEL_CBR,
|
||||
MMAL_VIDEO_ENCODER_RC_MODEL_LAST,
|
||||
MMAL_VIDEO_ENCODER_RC_MODEL_DUMMY = 0x7FFFFFFF
|
||||
} MMAL_VIDEO_ENCODE_RC_MODEL_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_VIDEO_ENCODE_RC_MODEL_T rc_model;
|
||||
}MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T;
|
||||
|
||||
/** Video rate control setting */
|
||||
typedef struct MMAL_PARAMETER_VIDEO_RATECONTROL_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_VIDEO_RATECONTROL_T control;
|
||||
} MMAL_PARAMETER_VIDEO_RATECONTROL_T;
|
||||
|
||||
/*H264 INTRA MB MODES*/
|
||||
typedef enum MMAL_VIDEO_ENCODE_H264_MB_INTRA_MODES_T {
|
||||
MMAL_VIDEO_ENCODER_H264_MB_4x4_INTRA = 1,
|
||||
MMAL_VIDEO_ENCODER_H264_MB_8x8_INTRA = 2,
|
||||
MMAL_VIDEO_ENCODER_H264_MB_16x16_INTRA = 4,
|
||||
MMAL_VIDEO_ENCODER_H264_MB_INTRA_DUMMY = 0x7fffffff
|
||||
} MMAL_VIDEO_ENCODE_H264_MB_INTRA_MODES_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
MMAL_VIDEO_ENCODE_H264_MB_INTRA_MODES_T mb_mode;
|
||||
}MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T;
|
||||
|
||||
/** NAL unit formats */
|
||||
typedef enum MMAL_VIDEO_NALUNITFORMAT_T {
|
||||
MMAL_VIDEO_NALUNITFORMAT_STARTCODES = 1,
|
||||
MMAL_VIDEO_NALUNITFORMAT_NALUNITPERBUFFER = 2,
|
||||
MMAL_VIDEO_NALUNITFORMAT_ONEBYTEINTERLEAVELENGTH = 4,
|
||||
MMAL_VIDEO_NALUNITFORMAT_TWOBYTEINTERLEAVELENGTH = 8,
|
||||
MMAL_VIDEO_NALUNITFORMAT_FOURBYTEINTERLEAVELENGTH = 16,
|
||||
MMAL_VIDEO_NALUNITFORMAT_DUMMY = 0x7fffffff
|
||||
} MMAL_VIDEO_NALUNITFORMAT_T;
|
||||
|
||||
/** NAL unit format setting */
|
||||
typedef struct MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_VIDEO_NALUNITFORMAT_T format;
|
||||
} MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T;
|
||||
|
||||
/** H264 Only: Overrides for max macro-blocks per second, max framesize,
|
||||
* and max bitrates. This overrides the default maximums for the configured level.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t custom_max_mbps;
|
||||
uint32_t custom_max_fs;
|
||||
uint32_t custom_max_br_and_cpb;
|
||||
} MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T;
|
||||
|
||||
/** H264 Only: Overrides for max macro-blocks per second, max framesize,
|
||||
* and max bitrates. This overrides the default maximums for the configured level.
|
||||
*/
|
||||
typedef struct MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_VIDEO_INTRA_REFRESH_T refresh_mode;
|
||||
uint32_t air_mbs;
|
||||
uint32_t air_ref;
|
||||
uint32_t cir_mbs;
|
||||
uint32_t pir_mbs;
|
||||
} MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T;
|
||||
|
||||
/** Structure for enabling EEDE, we keep it like this for now, there could be extra fields in the future */
|
||||
typedef struct MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t enable;
|
||||
} MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T;
|
||||
|
||||
/** Structure for setting lossrate for EEDE, we keep it like this for now, there could be extra fields in the future */
|
||||
typedef struct MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t loss_rate;
|
||||
} MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T;
|
||||
|
||||
/** Structure for setting inital DRM parameters */
|
||||
typedef struct MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t current_time;
|
||||
uint32_t ticks_per_sec;
|
||||
uint8_t lhs[32];
|
||||
} MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T;
|
||||
|
||||
/** Structure for requesting a hardware-protected memory buffer **/
|
||||
typedef struct MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
uint32_t size_wanted; /**< Input. Zero size means internal video decoder buffer,
|
||||
mem_handle and phys_addr not returned in this case */
|
||||
uint32_t protect; /**< Input. 1 = protect, 0 = unprotect */
|
||||
|
||||
uint32_t mem_handle; /**< Output. Handle for protected buffer */
|
||||
void * phys_addr; /**< Output. Physical memory address of protected buffer */
|
||||
|
||||
} MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_VIDEO_RENDER_STATS_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_BOOL_T valid;
|
||||
uint32_t match;
|
||||
uint32_t period;
|
||||
uint32_t phase;
|
||||
uint32_t pixel_clock_nominal;
|
||||
uint32_t pixel_clock;
|
||||
uint32_t hvs_status;
|
||||
uint32_t dummy[2];
|
||||
} MMAL_PARAMETER_VIDEO_RENDER_STATS_T;
|
||||
|
||||
typedef enum MMAL_INTERLACETYPE_T {
|
||||
MMAL_InterlaceProgressive, /**< The data is not interlaced, it is progressive scan */
|
||||
MMAL_InterlaceFieldSingleUpperFirst, /**< The data is interlaced, fields sent
|
||||
separately in temporal order, with upper field first */
|
||||
MMAL_InterlaceFieldSingleLowerFirst, /**< The data is interlaced, fields sent
|
||||
separately in temporal order, with lower field first */
|
||||
MMAL_InterlaceFieldsInterleavedUpperFirst, /**< The data is interlaced, two fields sent together line
|
||||
interleaved, with the upper field temporally earlier */
|
||||
MMAL_InterlaceFieldsInterleavedLowerFirst, /**< The data is interlaced, two fields sent together line
|
||||
interleaved, with the lower field temporally earlier */
|
||||
MMAL_InterlaceMixed, /**< The stream may contain a mixture of progressive
|
||||
and interlaced frames */
|
||||
MMAL_InterlaceKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
|
||||
MMAL_InterlaceVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
|
||||
MMAL_InterlaceMax = 0x7FFFFFFF
|
||||
} MMAL_INTERLACETYPE_T;
|
||||
|
||||
typedef struct MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T {
|
||||
MMAL_PARAMETER_HEADER_T hdr;
|
||||
|
||||
MMAL_INTERLACETYPE_T eMode; /**< The interlace type of the content */
|
||||
MMAL_BOOL_T bRepeatFirstField; /**< Whether to repeat the first field */
|
||||
} MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T;
|
||||
|
||||
#endif
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_POOL_H
|
||||
#define MMAL_POOL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup MmalPool Pools of buffer headers
|
||||
* A pool of buffer headers is composed of a queue (\ref MMAL_QUEUE_T) and a user
|
||||
* specified number of buffer headers (\ref MMAL_BUFFER_HEADER_T). */
|
||||
/* @{ */
|
||||
|
||||
#include "mmal_queue.h"
|
||||
|
||||
/** Definition of a pool */
|
||||
typedef struct MMAL_POOL_T
|
||||
{
|
||||
MMAL_QUEUE_T *queue; /**< Queue used by the pool */
|
||||
uint32_t headers_num; /**< Number of buffer headers in the pool */
|
||||
MMAL_BUFFER_HEADER_T **header; /**< Array of buffer headers belonging to the pool */
|
||||
} MMAL_POOL_T;
|
||||
|
||||
/** Allocator alloc prototype
|
||||
*
|
||||
* @param context The context pointer passed in on pool creation.
|
||||
* @param size The size of the allocation required, in bytes.
|
||||
* @return The pointer to the newly allocated memory, or NULL on failure.
|
||||
*/
|
||||
typedef void *(*mmal_pool_allocator_alloc_t)(void *context, uint32_t size);
|
||||
/** Allocator free prototype
|
||||
*
|
||||
* @param context The context pointer passed in on pool creation.
|
||||
* @param mem The pointer to the memory to be released.
|
||||
*/
|
||||
typedef void (*mmal_pool_allocator_free_t)(void *context, void *mem);
|
||||
|
||||
/** Create a pool of MMAL_BUFFER_HEADER_T.
|
||||
* After allocation, all allocated buffer headers will have been added to the queue.
|
||||
*
|
||||
* It is valid to create a pool with no buffer headers, or with zero size payload buffers.
|
||||
* The mmal_pool_resize() function can be used to increase or decrease the number of buffer
|
||||
* headers, or the size of the payload buffers, after creation of the pool.
|
||||
*
|
||||
* The payload buffers may also be allocated independently by the client, and assigned
|
||||
* to the buffer headers, but it will be the responsibility of the client to deal with
|
||||
* resizing and releasing the memory. It is recommended that mmal_pool_create_with_allocator()
|
||||
* is used in this case, supplying allocator function pointers that will be used as
|
||||
* necessary by MMAL.
|
||||
*
|
||||
* @param headers Number of buffer headers to be allocated with the pool.
|
||||
* @param payload_size Size of the payload buffer that will be allocated in
|
||||
* each of the buffer headers.
|
||||
* @return Pointer to the newly created pool or NULL on failure.
|
||||
*/
|
||||
MMAL_POOL_T *mmal_pool_create(unsigned int headers, uint32_t payload_size);
|
||||
|
||||
/** Create a pool of MMAL_BUFFER_HEADER_T.
|
||||
* After allocation, all allocated buffer headers will have been added to the queue.
|
||||
*
|
||||
* It is valid to create a pool with no buffer headers, or with zero size payload buffers.
|
||||
* The mmal_pool_resize() function can be used to increase or decrease the number of buffer
|
||||
* headers, or the size of the payload buffers, after creation of the pool. The allocators
|
||||
* passed during creation shall be used when resizing the payload buffers.
|
||||
*
|
||||
* @param headers Number of buffer headers to be allocated with the pool.
|
||||
* @param payload_size Size of the payload buffer that will be allocated in
|
||||
* each of the buffer headers.
|
||||
* @param allocator_context Pointer to the context of the allocator.
|
||||
* @param allocator_alloc Function pointer for the alloc call of the allocator.
|
||||
* @param allocator_free Function pointer for the free call of the allocator.
|
||||
*
|
||||
* @return Pointer to the newly created pool or NULL on failure.
|
||||
*/
|
||||
MMAL_POOL_T *mmal_pool_create_with_allocator(unsigned int headers, uint32_t payload_size,
|
||||
void *allocator_context, mmal_pool_allocator_alloc_t allocator_alloc,
|
||||
mmal_pool_allocator_free_t allocator_free);
|
||||
|
||||
/** Destroy a pool of MMAL_BUFFER_HEADER_T.
|
||||
* This will also deallocate all of the memory which was allocated when creating or
|
||||
* resizing the pool.
|
||||
*
|
||||
* If payload buffers have been allocated independently by the client, they should be
|
||||
* released prior to calling this function. If the client provided allocator functions,
|
||||
* the allocator_free function shall be called for each payload buffer.
|
||||
*
|
||||
* @param pool Pointer to a pool
|
||||
*/
|
||||
void mmal_pool_destroy(MMAL_POOL_T *pool);
|
||||
|
||||
/** Resize a pool of MMAL_BUFFER_HEADER_T.
|
||||
* This allows modifying either the number of allocated buffers, the payload size or both at the
|
||||
* same time.
|
||||
*
|
||||
* @param pool Pointer to the pool
|
||||
* @param headers New number of buffer headers to be allocated in the pool.
|
||||
* It is not valid to pass zero for the number of buffers.
|
||||
* @param payload_size Size of the payload buffer that will be allocated in
|
||||
* each of the buffer headers.
|
||||
* If this is set to 0, all payload buffers shall be released.
|
||||
* @return MMAL_SUCCESS or an error on failure.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_pool_resize(MMAL_POOL_T *pool, unsigned int headers, uint32_t payload_size);
|
||||
|
||||
/** Definition of the callback used by a pool to signal back to the user that a buffer header
|
||||
* has been released back to the pool.
|
||||
*
|
||||
* @param pool Pointer to the pool
|
||||
* @param buffer Buffer header just released
|
||||
* @param userdata User specific data passed in when setting the callback
|
||||
* @return True to have the buffer header put back in the pool's queue, false if the buffer
|
||||
* header has been taken within the callback.
|
||||
*/
|
||||
typedef MMAL_BOOL_T (*MMAL_POOL_BH_CB_T)(MMAL_POOL_T *pool, MMAL_BUFFER_HEADER_T *buffer, void *userdata);
|
||||
|
||||
/** Set a buffer header release callback to the pool.
|
||||
* Each time a buffer header is released to the pool, the callback will be triggered.
|
||||
*
|
||||
* @param pool Pointer to a pool
|
||||
* @param cb Callback function
|
||||
* @param userdata User specific data which will be passed with each callback
|
||||
*/
|
||||
void mmal_pool_callback_set(MMAL_POOL_T *pool, MMAL_POOL_BH_CB_T cb, void *userdata);
|
||||
|
||||
/** Set a pre-release callback for all buffer headers in the pool.
|
||||
* Each time a buffer header is about to be released to the pool, the callback
|
||||
* will be triggered.
|
||||
*
|
||||
* @param pool Pointer to the pool
|
||||
* @param cb Pre-release callback function
|
||||
* @param userdata User-specific data passed back with each callback
|
||||
*/
|
||||
void mmal_pool_pre_release_callback_set(MMAL_POOL_T *pool, MMAL_BH_PRE_RELEASE_CB_T cb, void *userdata);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_POOL_H */
|
@ -1,286 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_PORT_H
|
||||
#define MMAL_PORT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup MmalPort Ports
|
||||
* Definition of a MMAL port and its associated API */
|
||||
/* @{ */
|
||||
|
||||
#include "mmal_types.h"
|
||||
#include "mmal_format.h"
|
||||
#include "mmal_buffer.h"
|
||||
#include "mmal_parameters.h"
|
||||
|
||||
/** List of port types */
|
||||
typedef enum
|
||||
{
|
||||
MMAL_PORT_TYPE_UNKNOWN = 0, /**< Unknown port type */
|
||||
MMAL_PORT_TYPE_CONTROL, /**< Control port */
|
||||
MMAL_PORT_TYPE_INPUT, /**< Input port */
|
||||
MMAL_PORT_TYPE_OUTPUT, /**< Output port */
|
||||
MMAL_PORT_TYPE_CLOCK, /**< Clock port */
|
||||
MMAL_PORT_TYPE_INVALID = 0xffffffff /**< Dummy value to force 32bit enum */
|
||||
|
||||
} MMAL_PORT_TYPE_T;
|
||||
|
||||
/** \name Port capabilities
|
||||
* \anchor portcapabilities
|
||||
* The following flags describe the capabilities advertised by a port */
|
||||
/* @{ */
|
||||
/** The port is pass-through and doesn't need buffer headers allocated */
|
||||
#define MMAL_PORT_CAPABILITY_PASSTHROUGH 0x01
|
||||
/** The port wants to allocate the buffer payloads. This signals a preference that
|
||||
* payload allocation should be done on this port for efficiency reasons. */
|
||||
#define MMAL_PORT_CAPABILITY_ALLOCATION 0x02
|
||||
/** The port supports format change events. This applies to input ports and is used
|
||||
* to let the client know whether the port supports being reconfigured via a format
|
||||
* change event (i.e. without having to disable the port). */
|
||||
#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE 0x04
|
||||
/* @} */
|
||||
|
||||
/** Definition of a port.
|
||||
* A port is the entity that is exposed by components to receive or transmit
|
||||
* buffer headers (\ref MMAL_BUFFER_HEADER_T). A port is defined by its
|
||||
* \ref MMAL_ES_FORMAT_T.
|
||||
*
|
||||
* It may be possible to override the buffer requirements of a port by using
|
||||
* the MMAL_PARAMETER_BUFFER_REQUIREMENTS parameter.
|
||||
*/
|
||||
typedef struct MMAL_PORT_T
|
||||
{
|
||||
struct MMAL_PORT_PRIVATE_T *priv; /**< Private member used by the framework */
|
||||
const char *name; /**< Port name. Used for debugging purposes (Read Only) */
|
||||
|
||||
MMAL_PORT_TYPE_T type; /**< Type of the port (Read Only) */
|
||||
uint16_t index; /**< Index of the port in its type list (Read Only) */
|
||||
uint16_t index_all; /**< Index of the port in the list of all ports (Read Only) */
|
||||
|
||||
uint32_t is_enabled; /**< Indicates whether the port is enabled or not (Read Only) */
|
||||
MMAL_ES_FORMAT_T *format; /**< Format of the elementary stream */
|
||||
|
||||
uint32_t buffer_num_min; /**< Minimum number of buffers the port requires (Read Only).
|
||||
This is set by the component. */
|
||||
uint32_t buffer_size_min; /**< Minimum size of buffers the port requires (Read Only).
|
||||
This is set by the component. */
|
||||
uint32_t buffer_alignment_min; /**< Minimum alignment requirement for the buffers (Read Only).
|
||||
A value of zero means no special alignment requirements.
|
||||
This is set by the component. */
|
||||
uint32_t buffer_num_recommended; /**< Number of buffers the port recommends for optimal performance (Read Only).
|
||||
A value of zero means no special recommendation.
|
||||
This is set by the component. */
|
||||
uint32_t buffer_size_recommended; /**< Size of buffers the port recommends for optimal performance (Read Only).
|
||||
A value of zero means no special recommendation.
|
||||
This is set by the component. */
|
||||
uint32_t buffer_num; /**< Actual number of buffers the port will use.
|
||||
This is set by the client. */
|
||||
uint32_t buffer_size; /**< Actual maximum size of the buffers that will be sent
|
||||
to the port. This is set by the client. */
|
||||
|
||||
struct MMAL_COMPONENT_T *component; /**< Component this port belongs to (Read Only) */
|
||||
struct MMAL_PORT_USERDATA_T *userdata; /**< Field reserved for use by the client */
|
||||
|
||||
uint32_t capabilities; /**< Flags describing the capabilities of a port (Read Only).
|
||||
* Bitwise combination of \ref portcapabilities "Port capabilities"
|
||||
* values.
|
||||
*/
|
||||
|
||||
} MMAL_PORT_T;
|
||||
|
||||
/** Commit format changes on a port.
|
||||
*
|
||||
* @param port The port for which format changes are to be committed.
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_format_commit(MMAL_PORT_T *port);
|
||||
|
||||
/** Definition of the callback used by a port to send a \ref MMAL_BUFFER_HEADER_T
|
||||
* back to the user.
|
||||
*
|
||||
* @param port The port sending the buffer header.
|
||||
* @param buffer The buffer header being sent.
|
||||
*/
|
||||
typedef void (*MMAL_PORT_BH_CB_T)(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
|
||||
|
||||
/** Enable processing on a port
|
||||
*
|
||||
* If this port is connected to another, the given callback must be NULL, while for a
|
||||
* disconnected port, the callback must be non-NULL.
|
||||
*
|
||||
* If this is a connected output port and is successfully enabled:
|
||||
* <ul>
|
||||
* <li>The port shall be populated with a pool of buffers, allocated as required, according
|
||||
* to the buffer_num and buffer_size values.
|
||||
* <li>The input port to which it is connected shall be set to the same buffer
|
||||
* configuration and then be enabled. Should that fail, the original port shall be
|
||||
* disabled.
|
||||
* </ul>
|
||||
*
|
||||
* @param port port to enable
|
||||
* @param cb callback use by the port to send a \ref MMAL_BUFFER_HEADER_T back
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb);
|
||||
|
||||
/** Disable processing on a port
|
||||
*
|
||||
* Disabling a port will stop all processing on this port and return all (non-processed)
|
||||
* buffer headers to the client.
|
||||
*
|
||||
* If this is a connected output port, the input port to which it is connected shall
|
||||
* also be disabled. Any buffer pool shall be released.
|
||||
*
|
||||
* @param port port to disable
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_disable(MMAL_PORT_T *port);
|
||||
|
||||
/** Ask a port to release all the buffer headers it currently has.
|
||||
*
|
||||
* Flushing a port will ask the port to send all the buffer headers it currently has
|
||||
* to the client. Flushing is an asynchronous request and the flush call will
|
||||
* return before all the buffer headers are returned to the client.
|
||||
* It is up to the client to keep a count on the buffer headers to know when the
|
||||
* flush operation has completed.
|
||||
* It is also important to note that flushing will also reset the state of the port
|
||||
* and any processing which was buffered by the port will be lost.
|
||||
*
|
||||
* \attention Flushing a connected port behaviour TBD.
|
||||
*
|
||||
* @param port The port to flush.
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_flush(MMAL_PORT_T *port);
|
||||
|
||||
/** Set a parameter on a port.
|
||||
*
|
||||
* @param port The port to which the request is sent.
|
||||
* @param param The pointer to the header of the parameter to set.
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_set(MMAL_PORT_T *port,
|
||||
const MMAL_PARAMETER_HEADER_T *param);
|
||||
|
||||
/** Get a parameter from a port.
|
||||
* The size field must be set on input to the maximum size of the parameter
|
||||
* (including the header) and will be set on output to the actual size of the
|
||||
* parameter retrieved.
|
||||
*
|
||||
* \note If MMAL_ENOSPC is returned, the parameter is larger than the size
|
||||
* given. The given parameter will have been filled up to its size and then
|
||||
* the size field set to the full parameter's size. This can be used to
|
||||
* resize the parameter buffer so that a second call should succeed.
|
||||
*
|
||||
* @param port The port to which the request is sent.
|
||||
* @param param The pointer to the header of the parameter to get.
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_get(MMAL_PORT_T *port,
|
||||
MMAL_PARAMETER_HEADER_T *param);
|
||||
|
||||
/** Send a buffer header to a port.
|
||||
*
|
||||
* @param port The port to which the buffer header is to be sent.
|
||||
* @param buffer The buffer header to send.
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_send_buffer(MMAL_PORT_T *port,
|
||||
MMAL_BUFFER_HEADER_T *buffer);
|
||||
|
||||
/** Connect an output port to an input port.
|
||||
*
|
||||
* When connected and enabled, buffers will automatically progress from the
|
||||
* output port to the input port when they become available, and released back
|
||||
* to the output port when no longer required by the input port.
|
||||
*
|
||||
* Ports can be given either way around, but one must be an output port and
|
||||
* the other must be an input port. Neither can be connected or enabled
|
||||
* already. The format of the output port will be applied to the input port
|
||||
* on connection.
|
||||
*
|
||||
* @param port One of the ports to connect.
|
||||
* @param other_port The other port to connect.
|
||||
* @return MMAL_SUCCESS on success.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_connect(MMAL_PORT_T *port, MMAL_PORT_T *other_port);
|
||||
|
||||
/** Disconnect a connected port.
|
||||
*
|
||||
* If the port is not connected, an error will be returned. Otherwise, if the
|
||||
* ports are enabled, they will be disabled and any buffer pool created will be
|
||||
* freed.
|
||||
*
|
||||
* @param port The ports to disconnect.
|
||||
* @return MMAL_SUCCESS on success.
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_disconnect(MMAL_PORT_T *port);
|
||||
|
||||
/** Allocate a payload buffer.
|
||||
* This allows a client to allocate memory for a payload buffer based on the preferences
|
||||
* of a port. This for instance will allow the port to allocate memory which can be shared
|
||||
* between the host processor and videocore.
|
||||
*
|
||||
* See \ref mmal_pool_create_with_allocator().
|
||||
*
|
||||
* @param port Port responsible for allocating the memory.
|
||||
* @param payload_size Size of the payload buffer which will be allocated.
|
||||
*
|
||||
* @return Pointer to the allocated memory.
|
||||
*/
|
||||
uint8_t *mmal_port_payload_alloc(MMAL_PORT_T *port, uint32_t payload_size);
|
||||
|
||||
/** Free a payload buffer.
|
||||
* This allows a client to free memory allocated by a previous call to \ref mmal_port_payload_alloc.
|
||||
*
|
||||
* See \ref mmal_pool_create_with_allocator().
|
||||
*
|
||||
* @param port Port responsible for allocating the memory.
|
||||
* @param payload Pointer to the memory to free.
|
||||
*/
|
||||
void mmal_port_payload_free(MMAL_PORT_T *port, uint8_t *payload);
|
||||
|
||||
/** Get an empty event buffer header from a port
|
||||
*
|
||||
* @param port The port from which to get the event buffer header.
|
||||
* @param buffer The address of a buffer header pointer, which will be set on return.
|
||||
* @param event The specific event FourCC required. See the \ref MmalEvents "pre-defined events".
|
||||
* @return MMAL_SUCCESS on success
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_event_get(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T **buffer, uint32_t event);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_PORT_H */
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_QUEUE_H
|
||||
#define MMAL_QUEUE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup MmalQueue Queues of buffer headers
|
||||
* This provides a thread-safe implementation of a queue of buffer headers
|
||||
* (\ref MMAL_BUFFER_HEADER_T). The queue works in a first-in, first-out basis
|
||||
* so the buffer headers will be dequeued in the order they have been queued. */
|
||||
/* @{ */
|
||||
|
||||
#include "mmal_buffer.h"
|
||||
|
||||
typedef struct MMAL_QUEUE_T MMAL_QUEUE_T;
|
||||
|
||||
/** Create a queue of MMAL_BUFFER_HEADER_T
|
||||
*
|
||||
* @return Pointer to the newly created queue or NULL on failure.
|
||||
*/
|
||||
MMAL_QUEUE_T *mmal_queue_create(void);
|
||||
|
||||
/** Put a MMAL_BUFFER_HEADER_T into a queue
|
||||
*
|
||||
* @param queue Pointer to a queue
|
||||
* @param buffer Pointer to the MMAL_BUFFER_HEADER_T to add to the queue
|
||||
*/
|
||||
void mmal_queue_put(MMAL_QUEUE_T *queue, MMAL_BUFFER_HEADER_T *buffer);
|
||||
|
||||
/** Put a MMAL_BUFFER_HEADER_T back at the start of a queue.
|
||||
* This is used when a buffer header was removed from the queue but not
|
||||
* fully processed and needs to be put back where it was originally taken.
|
||||
*
|
||||
* @param queue Pointer to a queue
|
||||
* @param buffer Pointer to the MMAL_BUFFER_HEADER_T to add to the queue
|
||||
*/
|
||||
void mmal_queue_put_back(MMAL_QUEUE_T *queue, MMAL_BUFFER_HEADER_T *buffer);
|
||||
|
||||
/** Get a MMAL_BUFFER_HEADER_T from a queue
|
||||
*
|
||||
* @param queue Pointer to a queue
|
||||
*
|
||||
* @return pointer to the next MMAL_BUFFER_HEADER_T or NULL if the queue is empty.
|
||||
*/
|
||||
MMAL_BUFFER_HEADER_T *mmal_queue_get(MMAL_QUEUE_T *queue);
|
||||
|
||||
/** Wait for a MMAL_BUFFER_HEADER_T from a queue.
|
||||
* This is the same as a get except that this will block until a buffer header is
|
||||
* available.
|
||||
*
|
||||
* @param queue Pointer to a queue
|
||||
*
|
||||
* @return pointer to the next MMAL_BUFFER_HEADER_T.
|
||||
*/
|
||||
MMAL_BUFFER_HEADER_T *mmal_queue_wait(MMAL_QUEUE_T *queue);
|
||||
|
||||
/** Wait for a MMAL_BUFFER_HEADER_T from a queue, up to a given timeout.
|
||||
* This is the same as a wait, except that it will abort in case of timeout.
|
||||
*
|
||||
* @param queue Pointer to a queue
|
||||
* @param timeout Number of milliseconds to wait before
|
||||
* returning if the semaphore can't be acquired.
|
||||
*
|
||||
* @return pointer to the next MMAL_BUFFER_HEADER_T.
|
||||
*/
|
||||
MMAL_BUFFER_HEADER_T *mmal_queue_timedwait(MMAL_QUEUE_T *queue, VCOS_UNSIGNED timeout);
|
||||
|
||||
/** Get the number of MMAL_BUFFER_HEADER_T currently in a queue.
|
||||
*
|
||||
* @param queue Pointer to a queue
|
||||
*
|
||||
* @return length (in elements) of the queue.
|
||||
*/
|
||||
unsigned int mmal_queue_length(MMAL_QUEUE_T *queue);
|
||||
|
||||
/** Destroy a queue of MMAL_BUFFER_HEADER_T.
|
||||
*
|
||||
* @param queue Pointer to a queue
|
||||
*/
|
||||
void mmal_queue_destroy(MMAL_QUEUE_T *queue);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_QUEUE_H */
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_TYPES_H
|
||||
#define MMAL_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup MmalTypes Common types
|
||||
* Definition for common types */
|
||||
/* @{ */
|
||||
|
||||
#include "mmal_common.h"
|
||||
|
||||
/** Status return codes from the API.
|
||||
*
|
||||
* \internal Please try to keep this similar to the standard POSIX codes
|
||||
* rather than making up new ones!
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MMAL_SUCCESS = 0, /**< Success */
|
||||
MMAL_ENOMEM, /**< Out of memory */
|
||||
MMAL_ENOSPC, /**< Out of resources (other than memory) */
|
||||
MMAL_EINVAL, /**< Argument is invalid */
|
||||
MMAL_ENOSYS, /**< Function not implemented */
|
||||
MMAL_ENOENT, /**< No such file or directory */
|
||||
MMAL_ENXIO, /**< No such device or address */
|
||||
MMAL_EIO, /**< I/O error */
|
||||
MMAL_ESPIPE, /**< Illegal seek */
|
||||
MMAL_ECORRUPT, /**< Data is corrupt \attention FIXME: not POSIX */
|
||||
MMAL_ENOTREADY, /**< Component is not ready \attention FIXME: not POSIX */
|
||||
MMAL_ECONFIG, /**< Component is not configured \attention FIXME: not POSIX */
|
||||
MMAL_EISCONN, /**< Port is already connected */
|
||||
MMAL_ENOTCONN, /**< Port is disconnected */
|
||||
MMAL_EAGAIN, /**< Resource temporarily unavailable. Try again later*/
|
||||
MMAL_EFAULT, /**< Bad address */
|
||||
/* Do not add new codes here unless they match something from POSIX */
|
||||
MMAL_STATUS_MAX = 0x7FFFFFFF /**< Force to 32 bit */
|
||||
} MMAL_STATUS_T;
|
||||
|
||||
/** Describes a rectangle */
|
||||
typedef struct
|
||||
{
|
||||
int32_t x; /**< x coordinate (from left) */
|
||||
int32_t y; /**< y coordinate (from top) */
|
||||
int32_t width; /**< width */
|
||||
int32_t height; /**< height */
|
||||
} MMAL_RECT_T;
|
||||
|
||||
/** Describes a rational number */
|
||||
typedef struct
|
||||
{
|
||||
int32_t num; /**< Numerator */
|
||||
int32_t den; /**< Denominator */
|
||||
} MMAL_RATIONAL_T;
|
||||
|
||||
/** \name Special Unknown Time Value
|
||||
* Timestamps in MMAL are defined as signed 64 bits integer values representing microseconds.
|
||||
* However a pre-defined special value is used to signal that a timestamp is not known. */
|
||||
/* @{ */
|
||||
#define MMAL_TIME_UNKNOWN (INT64_C(1)<<63) /**< Special value signalling that time is not known */
|
||||
/* @} */
|
||||
|
||||
/** Four Character Code type */
|
||||
typedef uint32_t MMAL_FOURCC_T;
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMAL_TYPES_H */
|
@ -1,173 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_UTIL_H
|
||||
#define MMAL_UTIL_H
|
||||
|
||||
#include "mmal.h"
|
||||
|
||||
/** \defgroup MmalUtilities Utility functions
|
||||
* The utility functions provide helpers for common functionality that is not part
|
||||
* of the core MMAL API.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Offset in bytes of FIELD in TYPE. */
|
||||
#define MMAL_OFFSET(TYPE, FIELD) ((size_t)((uint8_t *)&((TYPE*)0)->FIELD - (uint8_t *)0))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Convert a status to a statically-allocated string.
|
||||
*
|
||||
* @param status The MMAL status code.
|
||||
* @return A C string describing the status code.
|
||||
*/
|
||||
const char *mmal_status_to_string(MMAL_STATUS_T status);
|
||||
|
||||
/** Convert stride to pixel width for a given pixel encoding.
|
||||
*
|
||||
* @param encoding The pixel encoding (such as one of the \ref MmalEncodings "pre-defined encodings")
|
||||
* @param stride The stride in bytes.
|
||||
* @return The width in pixels.
|
||||
*/
|
||||
uint32_t mmal_encoding_stride_to_width(uint32_t encoding, uint32_t stride);
|
||||
|
||||
/** Convert pixel width to stride for a given pixel encoding
|
||||
*
|
||||
* @param encoding The pixel encoding (such as one of the \ref MmalEncodings "pre-defined encodings")
|
||||
* @param width The width in pixels.
|
||||
* @return The stride in bytes.
|
||||
*/
|
||||
uint32_t mmal_encoding_width_to_stride(uint32_t encoding, uint32_t width);
|
||||
|
||||
/** Convert a port type to a string.
|
||||
*
|
||||
* @param type The MMAL port type.
|
||||
* @return A NULL-terminated string describing the port type.
|
||||
*/
|
||||
const char* mmal_port_type_to_string(MMAL_PORT_TYPE_T type);
|
||||
|
||||
/** Get a parameter from a port allocating the required amount of memory
|
||||
* for the parameter (i.e. for variable length parameters like URI or arrays).
|
||||
* The size field will be set on output to the actual size of the
|
||||
* parameter allocated and retrieved.
|
||||
*
|
||||
* The pointer returned must be released by a call to \ref mmal_port_parameter_free().
|
||||
*
|
||||
* @param port port to send request to
|
||||
* @param id parameter id
|
||||
* @param size initial size hint for allocation (can be 0)
|
||||
* @param status status of the parameter get operation (can be 0)
|
||||
* @return pointer to the header of the parameter or NULL on failure.
|
||||
*/
|
||||
MMAL_PARAMETER_HEADER_T *mmal_port_parameter_alloc_get(MMAL_PORT_T *port,
|
||||
uint32_t id, uint32_t size, MMAL_STATUS_T *status);
|
||||
|
||||
/** Free a parameter structure previously allocated via
|
||||
* \ref mmal_port_parameter_alloc_get().
|
||||
*
|
||||
* @param param pointer to header of the parameter
|
||||
*/
|
||||
void mmal_port_parameter_free(MMAL_PARAMETER_HEADER_T *param);
|
||||
|
||||
/** Copy buffer header metadata from source to destination.
|
||||
*
|
||||
* @param dest The destination buffer header.
|
||||
* @param src The source buffer header.
|
||||
*/
|
||||
void mmal_buffer_header_copy_header(MMAL_BUFFER_HEADER_T *dest, const MMAL_BUFFER_HEADER_T *src);
|
||||
|
||||
/** Create a pool of MMAL_BUFFER_HEADER_T associated with a specific port.
|
||||
* This allows a client to allocate memory for the payload buffers based on the preferences
|
||||
* of a port. This for instance will allow the port to allocate memory which can be shared
|
||||
* between the host processor and videocore.
|
||||
* After allocation, all allocated buffer headers will have been added to the queue.
|
||||
*
|
||||
* It is valid to create a pool with no buffer headers, or with zero size payload buffers.
|
||||
* The mmal_pool_resize() function can be used to increase or decrease the number of buffer
|
||||
* headers, or the size of the payload buffers, after creation of the pool.
|
||||
*
|
||||
* @param port Port responsible for creating the pool.
|
||||
* @param headers Number of buffers which will be allocated with the pool.
|
||||
* @param payload_size Size of the payload buffer which will be allocated in
|
||||
* each of the buffer headers.
|
||||
* @return Pointer to the newly created pool or NULL on failure.
|
||||
*/
|
||||
MMAL_POOL_T *mmal_port_pool_create(MMAL_PORT_T *port,
|
||||
unsigned int headers, uint32_t payload_size);
|
||||
|
||||
/** Destroy a pool of MMAL_BUFFER_HEADER_T associated with a specific port.
|
||||
* This will also deallocate all of the memory which was allocated when creating or
|
||||
* resizing the pool.
|
||||
*
|
||||
* @param port Pointer to the port responsible for creating the pool.
|
||||
* @param pool Pointer to the pool to be destroyed.
|
||||
*/
|
||||
void mmal_port_pool_destroy(MMAL_PORT_T *port, MMAL_POOL_T *pool);
|
||||
|
||||
/** Log the content of a \ref MMAL_PORT_T structure.
|
||||
*
|
||||
* @param port Pointer to the port to dump.
|
||||
*/
|
||||
void mmal_log_dump_port(MMAL_PORT_T *port);
|
||||
|
||||
/** Log the content of a \ref MMAL_ES_FORMAT_T structure.
|
||||
*
|
||||
* @param format Pointer to the format to dump.
|
||||
*/
|
||||
void mmal_log_dump_format(MMAL_ES_FORMAT_T *format);
|
||||
|
||||
/** Return the nth port.
|
||||
*
|
||||
* @param comp component to query
|
||||
* @param index port index
|
||||
* @param type port type
|
||||
*
|
||||
* @return port or NULL if not found
|
||||
*/
|
||||
MMAL_PORT_T *mmal_util_get_port(MMAL_COMPONENT_T *comp, MMAL_PORT_TYPE_T type, unsigned index);
|
||||
|
||||
/** Convert a 4cc into a string.
|
||||
*
|
||||
* @param buf Destination for result
|
||||
* @param len Size of result buffer
|
||||
* @param fourcc 4cc to be converted
|
||||
* @return converted string (buf)
|
||||
*
|
||||
*/
|
||||
char *mmal_4cc_to_string(char *buf, size_t len, uint32_t fourcc);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
@ -1,210 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMAL_UTIL_PARAMS_H
|
||||
#define MMAL_UTIL_PARAMS_H
|
||||
|
||||
#include "mmal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Utility functions to set some common parameters.
|
||||
*/
|
||||
|
||||
/** Helper function to set the value of a boolean parameter.
|
||||
* @param port port on which to set the parameter
|
||||
* @param id parameter id
|
||||
* @param value value to set the parameter to
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_set_boolean(MMAL_PORT_T *port, uint32_t id, MMAL_BOOL_T value);
|
||||
|
||||
/** Helper function to get the value of a boolean parameter.
|
||||
* @param port port on which to get the parameter
|
||||
* @param id parameter id
|
||||
* @param value pointer to where the value will be returned
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_get_boolean(MMAL_PORT_T *port, uint32_t id, MMAL_BOOL_T *value);
|
||||
|
||||
/** Helper function to set the value of a 64 bits unsigned integer parameter.
|
||||
* @param port port on which to set the parameter
|
||||
* @param id parameter id
|
||||
* @param value value to set the parameter to
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_set_uint64(MMAL_PORT_T *port, uint32_t id, uint64_t value);
|
||||
|
||||
/** Helper function to get the value of a 64 bits unsigned integer parameter.
|
||||
* @param port port on which to get the parameter
|
||||
* @param id parameter id
|
||||
* @param value pointer to where the value will be returned
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_get_uint64(MMAL_PORT_T *port, uint32_t id, uint64_t *value);
|
||||
|
||||
/** Helper function to set the value of a 64 bits signed integer parameter.
|
||||
* @param port port on which to set the parameter
|
||||
* @param id parameter id
|
||||
* @param value value to set the parameter to
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_set_int64(MMAL_PORT_T *port, uint32_t id, int64_t value);
|
||||
|
||||
/** Helper function to get the value of a 64 bits signed integer parameter.
|
||||
* @param port port on which to get the parameter
|
||||
* @param id parameter id
|
||||
* @param value pointer to where the value will be returned
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_get_int64(MMAL_PORT_T *port, uint32_t id, int64_t *value);
|
||||
|
||||
/** Helper function to set the value of a 32 bits unsigned integer parameter.
|
||||
* @param port port on which to set the parameter
|
||||
* @param id parameter id
|
||||
* @param value value to set the parameter to
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_set_uint32(MMAL_PORT_T *port, uint32_t id, uint32_t value);
|
||||
|
||||
/** Helper function to get the value of a 32 bits unsigned integer parameter.
|
||||
* @param port port on which to get the parameter
|
||||
* @param id parameter id
|
||||
* @param value pointer to where the value will be returned
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_get_uint32(MMAL_PORT_T *port, uint32_t id, uint32_t *value);
|
||||
|
||||
/** Helper function to set the value of a 32 bits signed integer parameter.
|
||||
* @param port port on which to set the parameter
|
||||
* @param id parameter id
|
||||
* @param value value to set the parameter to
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_set_int32(MMAL_PORT_T *port, uint32_t id, int32_t value);
|
||||
|
||||
/** Helper function to get the value of a 32 bits signed integer parameter.
|
||||
* @param port port on which to get the parameter
|
||||
* @param id parameter id
|
||||
* @param value pointer to where the value will be returned
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_get_int32(MMAL_PORT_T *port, uint32_t id, int32_t *value);
|
||||
|
||||
/** Helper function to set the value of a rational parameter.
|
||||
* @param port port on which to set the parameter
|
||||
* @param id parameter id
|
||||
* @param value value to set the parameter to
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_set_rational(MMAL_PORT_T *port, uint32_t id, MMAL_RATIONAL_T value);
|
||||
|
||||
/** Helper function to get the value of a rational parameter.
|
||||
* @param port port on which to get the parameter
|
||||
* @param id parameter id
|
||||
* @param value pointer to where the value will be returned
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_get_rational(MMAL_PORT_T *port, uint32_t id, MMAL_RATIONAL_T *value);
|
||||
|
||||
/** Helper function to set the value of a string parameter.
|
||||
* @param port port on which to set the parameter
|
||||
* @param id parameter id
|
||||
* @param value null-terminated string value
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_set_string(MMAL_PORT_T *port, uint32_t id, const char *value);
|
||||
|
||||
/** Helper function to set the value of an array of bytes parameter.
|
||||
* @param port port on which to set the parameter
|
||||
* @param id parameter id
|
||||
* @param data pointer to the array of bytes
|
||||
* @param size size of the array of bytes
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_port_parameter_set_bytes(MMAL_PORT_T *port, uint32_t id,
|
||||
const uint8_t *data, unsigned int size);
|
||||
|
||||
/** Helper function to set a MMAL_PARAMETER_URI_T parameter on a port.
|
||||
* @param port port on which to set the parameter
|
||||
* @param uri URI string
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_util_port_set_uri(MMAL_PORT_T *port, const char *uri);
|
||||
|
||||
/** Set the display region.
|
||||
* @param port port to configure
|
||||
* @param region region
|
||||
*
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_util_set_display_region(MMAL_PORT_T *port,
|
||||
MMAL_DISPLAYREGION_T *region);
|
||||
|
||||
/** Tell the camera to use the STC for timestamps rather than the clock.
|
||||
*
|
||||
* @param port port to configure
|
||||
* @param mode STC mode to use
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_util_camera_use_stc_timestamp(MMAL_PORT_T *port, MMAL_CAMERA_STC_MODE_T mode);
|
||||
|
||||
/** Get the MMAL core statistics for a given port.
|
||||
*
|
||||
* @param port port to query
|
||||
* @param dir port direction
|
||||
* @param reset reset the stats as well
|
||||
* @param stats filled in with results
|
||||
* @return MMAL_SUCCESS or error
|
||||
*/
|
||||
MMAL_STATUS_T mmal_util_get_core_port_stats(MMAL_PORT_T *port, MMAL_CORE_STATS_DIR dir, MMAL_BOOL_T reset,
|
||||
MMAL_CORE_STATISTICS_T *stats);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,20 +0,0 @@
|
||||
add_library (mmal_omx ${LIBRARY_TYPE}
|
||||
mmalomx_core.c
|
||||
mmalomx_logging.c
|
||||
mmalomx_commands.c
|
||||
mmalomx_buffer.c
|
||||
mmalomx_marks.c
|
||||
mmalomx_roles.c
|
||||
mmalomx_parameters.c
|
||||
mmalomx_registry.c
|
||||
)
|
||||
|
||||
add_library (mmal_omxutil ${LIBRARY_TYPE}
|
||||
mmalomx_util_params.c
|
||||
mmalomx_util_params_audio.c
|
||||
mmalomx_util_params_video.c
|
||||
mmalomx_util_params_camera.c
|
||||
mmalomx_util_params_misc.c
|
||||
)
|
||||
|
||||
target_link_libraries (mmal_omx mmal_omxutil mmal_core mmal_util vcos)
|
@ -1,130 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL
|
||||
*/
|
||||
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Core.h"
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Component.h"
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Video.h"
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Audio.h"
|
||||
#include <mmal.h>
|
||||
#include <util/mmal_il.h>
|
||||
|
||||
/* Define this to 1 if you want to log all buffer transfers */
|
||||
#define ENABLE_MMAL_EXTRA_LOGGING 0
|
||||
|
||||
#ifndef MMALOMX_EXPORT
|
||||
# define MMALOMX_EXPORT(a) a
|
||||
#endif
|
||||
#ifndef MMALOMX_IMPORT
|
||||
# define MMALOMX_IMPORT(a) a
|
||||
#endif
|
||||
|
||||
#define MAX_MARKS_NUM 2
|
||||
#define MAX_ENCODINGS_NUM 20
|
||||
|
||||
/** Per-port context data */
|
||||
typedef struct MMALOMX_PORT_T
|
||||
{
|
||||
struct MMALOMX_COMPONENT_T *component;
|
||||
MMAL_PORT_T *mmal;
|
||||
OMX_DIRTYPE direction;
|
||||
unsigned int index;
|
||||
unsigned int buffers;
|
||||
unsigned int buffers_in_transit;
|
||||
|
||||
MMAL_BOOL_T buffers_allocated:1;
|
||||
MMAL_BOOL_T enabled:1;
|
||||
MMAL_BOOL_T populated:1;
|
||||
MMAL_BOOL_T zero_copy:1;
|
||||
MMAL_BOOL_T no_cropping:1;
|
||||
MMAL_BOOL_T format_changed:1;
|
||||
MMAL_POOL_T *pool;
|
||||
|
||||
uint32_t actions;
|
||||
|
||||
OMX_MARKTYPE marks[MAX_MARKS_NUM];
|
||||
unsigned int marks_first:8;
|
||||
unsigned int marks_num:8;
|
||||
|
||||
OMX_FORMAT_PARAM_TYPE format_param;
|
||||
|
||||
MMAL_PARAMETER_HEADER_T encodings_header;
|
||||
MMAL_FOURCC_T encodings[MAX_ENCODINGS_NUM];
|
||||
unsigned int encodings_num;
|
||||
|
||||
} MMALOMX_PORT_T;
|
||||
|
||||
/** Component context data */
|
||||
typedef struct MMALOMX_COMPONENT_T {
|
||||
OMX_COMPONENTTYPE omx; /**< OMX component type structure */
|
||||
|
||||
unsigned int registry_id;
|
||||
const char *name;
|
||||
uint32_t role;
|
||||
OMX_CALLBACKTYPE callbacks;
|
||||
OMX_PTR callbacks_data;
|
||||
|
||||
struct MMAL_COMPONENT_T *mmal;
|
||||
OMX_STATETYPE state;
|
||||
unsigned int state_transition;
|
||||
|
||||
MMALOMX_PORT_T *ports;
|
||||
unsigned int ports_num;
|
||||
unsigned int ports_domain_num[4];
|
||||
|
||||
MMAL_BOOL_T actions_running;
|
||||
|
||||
OMX_U32 group_id;
|
||||
OMX_U32 group_priority;
|
||||
|
||||
/* Support for command queues */
|
||||
MMAL_POOL_T *cmd_pool;
|
||||
MMAL_QUEUE_T *cmd_queue;
|
||||
VCOS_THREAD_T cmd_thread;
|
||||
MMAL_BOOL_T cmd_thread_used;
|
||||
VCOS_SEMAPHORE_T cmd_sema;
|
||||
|
||||
VCOS_MUTEX_T lock; /**< Used to protect component state */
|
||||
VCOS_MUTEX_T lock_port; /**< Used to protect port state */
|
||||
|
||||
} MMALOMX_COMPONENT_T;
|
||||
|
||||
OMX_ERRORTYPE mmalomx_callback_event_handler(
|
||||
MMALOMX_COMPONENT_T *component,
|
||||
OMX_EVENTTYPE eEvent,
|
||||
OMX_U32 nData1,
|
||||
OMX_U32 nData2,
|
||||
OMX_PTR pEventData);
|
||||
|
||||
#define MMALOMX_LOCK(a) vcos_mutex_lock(&a->lock)
|
||||
#define MMALOMX_UNLOCK(a) vcos_mutex_unlock(&a->lock)
|
||||
#define MMALOMX_LOCK_PORT(a,b) vcos_mutex_lock(&a->lock_port)
|
||||
#define MMALOMX_UNLOCK_PORT(a,b) vcos_mutex_unlock(&a->lock_port)
|
||||
|
@ -1,235 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_buffer.h"
|
||||
#include "mmalomx_commands.h"
|
||||
#include "mmalomx_marks.h"
|
||||
#include "mmalomx_logging.h"
|
||||
|
||||
#include <util/mmal_util.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_buffer_send(
|
||||
MMALOMX_COMPONENT_T *component,
|
||||
OMX_BUFFERHEADERTYPE *omx_buffer,
|
||||
OMX_DIRTYPE direction)
|
||||
{
|
||||
OMX_ERRORTYPE status = OMX_ErrorNone;
|
||||
MMAL_BUFFER_HEADER_T *mmal_buffer;
|
||||
MMAL_STATUS_T mmal_status;
|
||||
MMALOMX_PORT_T *port;
|
||||
unsigned int index;
|
||||
|
||||
/* Sanity checks */
|
||||
if (!component)
|
||||
return OMX_ErrorInvalidComponent;
|
||||
if (component->state == OMX_StateInvalid)
|
||||
return OMX_ErrorInvalidState;
|
||||
|
||||
if (!omx_buffer || omx_buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE) ||
|
||||
omx_buffer->nOffset + omx_buffer->nFilledLen > omx_buffer->nAllocLen)
|
||||
return OMX_ErrorBadParameter;
|
||||
|
||||
index = direction == OMX_DirInput ? omx_buffer->nInputPortIndex : omx_buffer->nOutputPortIndex;
|
||||
if (index >= component->ports_num)
|
||||
return OMX_ErrorBadPortIndex;
|
||||
|
||||
port = &component->ports[index];
|
||||
if (port->direction != direction)
|
||||
return OMX_ErrorBadPortIndex;
|
||||
|
||||
MMALOMX_LOCK_PORT(component, port);
|
||||
|
||||
if (component->state != OMX_StatePause && component->state != OMX_StateExecuting)
|
||||
status = OMX_ErrorIncorrectStateOperation;
|
||||
if (!port->enabled /* FIXME: || flushing || pending idle */)
|
||||
status = OMX_ErrorIncorrectStateOperation;
|
||||
if (status != OMX_ErrorNone)
|
||||
goto error;
|
||||
|
||||
mmal_buffer = mmal_queue_get( port->pool->queue );
|
||||
if (!vcos_verify(mmal_buffer)) /* Should never happen */
|
||||
{
|
||||
status = OMX_ErrorUndefined;
|
||||
goto error;
|
||||
}
|
||||
|
||||
mmalomx_mark_process_incoming(component, port, omx_buffer);
|
||||
|
||||
mmal_buffer->user_data = (void *)omx_buffer;
|
||||
mmalil_buffer_header_to_mmal(mmal_buffer, omx_buffer);
|
||||
|
||||
mmal_status = mmal_port_send_buffer(port->mmal, mmal_buffer);
|
||||
if (!vcos_verify(mmal_status == MMAL_SUCCESS))
|
||||
{
|
||||
LOG_ERROR("failed to send buffer on %s", port->mmal->name);
|
||||
mmal_queue_put_back( port->pool->queue, mmal_buffer );
|
||||
status = mmalil_error_to_omx(mmal_status);
|
||||
}
|
||||
else
|
||||
{
|
||||
port->buffers_in_transit++;
|
||||
}
|
||||
|
||||
error:
|
||||
MMALOMX_UNLOCK_PORT(component, port);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void mmalomx_buffer_event(
|
||||
MMALOMX_PORT_T *port,
|
||||
MMAL_BUFFER_HEADER_T *mmal_buffer)
|
||||
{
|
||||
MMALOMX_COMPONENT_T *component = port->component;
|
||||
MMAL_EVENT_FORMAT_CHANGED_T *event;
|
||||
|
||||
LOG_TRACE("hComponent %p, port %i, event %4.4s", component, port->index,
|
||||
(char *)&mmal_buffer->cmd);
|
||||
|
||||
if (mmal_buffer->cmd == MMAL_EVENT_ERROR )
|
||||
{
|
||||
mmalomx_callback_event_handler(component, OMX_EventError,
|
||||
mmalil_error_to_omx(*(MMAL_STATUS_T *)mmal_buffer->data), 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
event = mmal_event_format_changed_get(mmal_buffer);
|
||||
if (event && port->mmal->type == MMAL_PORT_TYPE_OUTPUT &&
|
||||
port->mmal->format->type == MMAL_ES_TYPE_VIDEO)
|
||||
{
|
||||
uint32_t diff = mmal_format_compare(event->format, port->mmal->format);
|
||||
MMAL_ES_FORMAT_T *format = port->mmal->format;
|
||||
MMAL_VIDEO_FORMAT_T video = format->es->video;
|
||||
|
||||
/* Update the port settings with the new values */
|
||||
mmal_format_copy(format, event->format);
|
||||
port->mmal->buffer_num_min = event->buffer_num_min;
|
||||
port->mmal->buffer_size_min = event->buffer_size_min;
|
||||
port->format_changed = MMAL_TRUE;
|
||||
|
||||
if ((diff & MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_ASPECT_RATIO) &&
|
||||
/* Do not report a change if going from unspecified to 1:1 */
|
||||
!(format->es->video.par.num == format->es->video.par.den && !video.par.num))
|
||||
{
|
||||
LOG_DEBUG("aspect ratio change %ix%i->%ix%i", (int)video.par.num, (int)video.par.den,
|
||||
(int)format->es->video.par.num, (int)format->es->video.par.den);
|
||||
mmalomx_callback_event_handler(component, OMX_EventPortSettingsChanged,
|
||||
port->index, OMX_IndexParamBrcmPixelAspectRatio, NULL);
|
||||
}
|
||||
|
||||
if (diff & (MMAL_ES_FORMAT_COMPARE_FLAG_ENCODING|
|
||||
MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_RESOLUTION|
|
||||
MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_CROPPING))
|
||||
{
|
||||
LOG_DEBUG("format change %ix%i(%ix%i) -> %ix%i(%ix%i)",
|
||||
(int)video.width, (int)video.height,
|
||||
(int)video.crop.width, (int)video.crop.height,
|
||||
(int)format->es->video.width, (int)format->es->video.height,
|
||||
(int)format->es->video.crop.width, (int)format->es->video.crop.height);
|
||||
mmalomx_callback_event_handler(component, OMX_EventPortSettingsChanged,
|
||||
port->index, 0, NULL);
|
||||
}
|
||||
}
|
||||
else if (event && port->mmal->type == MMAL_PORT_TYPE_OUTPUT &&
|
||||
port->mmal->format->type == MMAL_ES_TYPE_AUDIO)
|
||||
{
|
||||
uint32_t diff = mmal_format_compare(event->format, port->mmal->format);
|
||||
MMAL_ES_FORMAT_T *format = port->mmal->format;
|
||||
MMAL_AUDIO_FORMAT_T audio = format->es->audio;
|
||||
|
||||
/* Update the port settings with the new values */
|
||||
mmal_format_copy(format, event->format);
|
||||
port->mmal->buffer_num_min = event->buffer_num_min;
|
||||
port->mmal->buffer_size_min = event->buffer_size_min;
|
||||
port->format_changed = MMAL_TRUE;
|
||||
|
||||
if (diff)
|
||||
{
|
||||
LOG_DEBUG("format change %ich, %iHz, %ibps -> %ich, %iHz, %ibps",
|
||||
(int)audio.channels, (int)audio.sample_rate,
|
||||
(int)audio.bits_per_sample,
|
||||
(int)format->es->audio.channels,
|
||||
(int)format->es->audio.sample_rate,
|
||||
(int)format->es->audio.bits_per_sample);
|
||||
mmalomx_callback_event_handler(component, OMX_EventPortSettingsChanged,
|
||||
port->index, 0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_buffer_return(
|
||||
MMALOMX_PORT_T *port,
|
||||
MMAL_BUFFER_HEADER_T *mmal_buffer)
|
||||
{
|
||||
MMALOMX_COMPONENT_T *component = port->component;
|
||||
OMX_BUFFERHEADERTYPE *omx_buffer = (OMX_BUFFERHEADERTYPE *)mmal_buffer->user_data;
|
||||
MMAL_BOOL_T signal;
|
||||
|
||||
if (mmal_buffer->cmd)
|
||||
{
|
||||
mmalomx_buffer_event(port, mmal_buffer);
|
||||
mmal_buffer_header_release(mmal_buffer);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
if (ENABLE_MMAL_EXTRA_LOGGING)
|
||||
LOG_TRACE("hComponent %p, port %i, pBuffer %p", component,
|
||||
port->index, omx_buffer);
|
||||
|
||||
vcos_assert(omx_buffer->pBuffer == mmal_buffer->data);
|
||||
mmalil_buffer_header_to_omx(omx_buffer, mmal_buffer);
|
||||
mmal_buffer_header_release(mmal_buffer);
|
||||
|
||||
if ((omx_buffer->nFlags & OMX_BUFFERFLAG_EOS) && port->direction == OMX_DirOutput)
|
||||
{
|
||||
mmalomx_callback_event_handler(component, OMX_EventBufferFlag,
|
||||
port->index, omx_buffer->nFlags, NULL);
|
||||
}
|
||||
|
||||
mmalomx_mark_process_outgoing(component, port, omx_buffer);
|
||||
|
||||
if (port->direction == OMX_DirInput)
|
||||
component->callbacks.EmptyBufferDone((OMX_HANDLETYPE)&component->omx,
|
||||
component->callbacks_data, omx_buffer );
|
||||
else
|
||||
component->callbacks.FillBufferDone((OMX_HANDLETYPE)&component->omx,
|
||||
component->callbacks_data, omx_buffer );
|
||||
|
||||
MMALOMX_LOCK_PORT(component, port);
|
||||
signal = port->actions & MMALOMX_ACTION_CHECK_FLUSHED;
|
||||
port->buffers_in_transit--;
|
||||
MMALOMX_UNLOCK_PORT(component, port);
|
||||
|
||||
if (signal)
|
||||
mmalomx_commands_actions_signal(component);
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Buffer related functions
|
||||
*/
|
||||
|
||||
OMX_ERRORTYPE mmalomx_buffer_send(
|
||||
MMALOMX_COMPONENT_T *component,
|
||||
OMX_BUFFERHEADERTYPE *omx_buffer,
|
||||
OMX_DIRTYPE direction);
|
||||
|
||||
OMX_ERRORTYPE mmalomx_buffer_return(
|
||||
MMALOMX_PORT_T *port,
|
||||
MMAL_BUFFER_HEADER_T *mmal_buffer);
|
@ -1,462 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_commands.h"
|
||||
#include "mmalomx_buffer.h"
|
||||
#include "mmalomx_logging.h"
|
||||
|
||||
typedef struct {
|
||||
OMX_STATETYPE state;
|
||||
OMX_STATETYPE request;
|
||||
uint32_t actions;
|
||||
} MMALOMX_STATE_TRANSITION_T;
|
||||
|
||||
MMALOMX_STATE_TRANSITION_T state_transition_table[] =
|
||||
{
|
||||
{OMX_StateInvalid, OMX_StateInvalid, 0},
|
||||
{OMX_StateLoaded, OMX_StateIdle, MMALOMX_ACTION_CHECK_ALLOCATED|MMALOMX_ACTION_ENABLE},
|
||||
{OMX_StateLoaded, OMX_StateWaitForResources, 0},
|
||||
{OMX_StateWaitForResources, OMX_StateLoaded, 0},
|
||||
{OMX_StateWaitForResources, OMX_StateIdle, MMALOMX_ACTION_CHECK_ALLOCATED|MMALOMX_ACTION_ENABLE},
|
||||
{OMX_StateIdle, OMX_StateLoaded, MMALOMX_ACTION_CHECK_DEALLOCATED|MMALOMX_ACTION_DISABLE},
|
||||
{OMX_StateIdle, OMX_StateExecuting, 0},
|
||||
{OMX_StateIdle, OMX_StatePause, 0},
|
||||
{OMX_StateExecuting, OMX_StateIdle, MMALOMX_ACTION_FLUSH|MMALOMX_ACTION_CHECK_FLUSHED},
|
||||
{OMX_StateExecuting, OMX_StatePause, 0},
|
||||
{OMX_StatePause, OMX_StateIdle, 0},
|
||||
{OMX_StatePause, OMX_StateExecuting, 0},
|
||||
{OMX_StateMax, OMX_StateMax, 0}
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
static unsigned int mmalomx_state_transition_get(OMX_STATETYPE state, OMX_STATETYPE request)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; state_transition_table[i].state != OMX_StateMax; i++)
|
||||
if (state_transition_table[i].state == state &&
|
||||
state_transition_table[i].request == request)
|
||||
break;
|
||||
|
||||
return state_transition_table[i].state != OMX_StateMax ? i : 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void mmalomx_buffer_cb_io(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
mmalomx_buffer_return((MMALOMX_PORT_T *)port->userdata, buffer);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void mmalomx_commands_check_port_actions(MMALOMX_COMPONENT_T *component,
|
||||
MMALOMX_PORT_T *port)
|
||||
{
|
||||
uint32_t exec_actions = 0;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
MMALOMX_LOCK_PORT(component, port);
|
||||
if (!port->actions)
|
||||
{
|
||||
MMALOMX_UNLOCK_PORT(component, port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (port->actions & MMALOMX_ACTION_FLUSH)
|
||||
{
|
||||
port->actions &= ~MMALOMX_ACTION_FLUSH;
|
||||
port->actions |= MMALOMX_ACTION_PENDING_FLUSH;
|
||||
exec_actions |= MMALOMX_ACTION_PENDING_FLUSH;
|
||||
}
|
||||
if ((port->actions & MMALOMX_ACTION_DISABLE) &&
|
||||
(!port->buffers_in_transit ||
|
||||
!(port->actions & MMALOMX_ACTION_CHECK_FLUSHED)))
|
||||
{
|
||||
port->actions &= ~MMALOMX_ACTION_DISABLE;
|
||||
port->actions |= MMALOMX_ACTION_PENDING_DISABLE;
|
||||
exec_actions |= MMALOMX_ACTION_PENDING_DISABLE;
|
||||
}
|
||||
if ((port->actions & MMALOMX_ACTION_ENABLE) &&
|
||||
port->buffers)
|
||||
{
|
||||
/* We defer enabling the mmal port until the first buffer allocation
|
||||
* has been done. Only at that point do we know for sure whether we
|
||||
* are going to use shared memory or not.
|
||||
* We might want to delay it to just before sending the event to the client ???
|
||||
*/
|
||||
port->actions &= ~MMALOMX_ACTION_ENABLE;
|
||||
port->actions |= MMALOMX_ACTION_PENDING_ENABLE;
|
||||
exec_actions |= MMALOMX_ACTION_PENDING_ENABLE;
|
||||
}
|
||||
MMALOMX_UNLOCK_PORT(component, port);
|
||||
|
||||
if (exec_actions & MMALOMX_ACTION_PENDING_FLUSH)
|
||||
mmal_port_flush(port->mmal);
|
||||
|
||||
if (exec_actions & MMALOMX_ACTION_PENDING_DISABLE)
|
||||
{
|
||||
mmal_port_disable(port->mmal);
|
||||
|
||||
/* If there was a port format changed event, we need to make sure
|
||||
* the new format has been committed */
|
||||
if (port->format_changed)
|
||||
{
|
||||
status = mmal_port_format_commit(port->mmal);
|
||||
if (status != MMAL_SUCCESS)
|
||||
LOG_WARN("could not commit new format (%i)", status);
|
||||
port->format_changed = MMAL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (exec_actions & MMALOMX_ACTION_PENDING_ENABLE)
|
||||
{
|
||||
status = mmal_port_enable(port->mmal, mmalomx_buffer_cb_io);
|
||||
if (status == MMAL_SUCCESS)
|
||||
status = mmal_pool_resize(port->pool, port->mmal->buffer_num, 0);
|
||||
if (status != MMAL_SUCCESS)
|
||||
mmalomx_callback_event_handler(component, OMX_EventError, mmalil_error_to_omx(status), 0, NULL);
|
||||
/* FIXME: we're still going to generate a cmd complete. Not sure if that's an issue. */
|
||||
}
|
||||
|
||||
MMALOMX_LOCK_PORT(component, port);
|
||||
|
||||
port->actions &= ~exec_actions;
|
||||
if ((port->actions & MMALOMX_ACTION_CHECK_ALLOCATED) && port->populated)
|
||||
port->actions &= ~MMALOMX_ACTION_CHECK_ALLOCATED;
|
||||
if ((port->actions & MMALOMX_ACTION_CHECK_DEALLOCATED) && !port->buffers)
|
||||
port->actions &= ~MMALOMX_ACTION_CHECK_DEALLOCATED;
|
||||
if ((port->actions & MMALOMX_ACTION_CHECK_FLUSHED) && !port->buffers_in_transit)
|
||||
port->actions &= ~MMALOMX_ACTION_CHECK_FLUSHED;
|
||||
exec_actions = port->actions;
|
||||
|
||||
if (port->actions == MMALOMX_ACTION_NOTIFY_FLUSH ||
|
||||
port->actions == MMALOMX_ACTION_NOTIFY_ENABLE ||
|
||||
port->actions == MMALOMX_ACTION_NOTIFY_DISABLE)
|
||||
port->actions = 0; /* We're done */
|
||||
|
||||
MMALOMX_UNLOCK_PORT(component, port);
|
||||
|
||||
if (exec_actions == MMALOMX_ACTION_NOTIFY_FLUSH)
|
||||
mmalomx_callback_event_handler(component, OMX_EventCmdComplete,
|
||||
OMX_CommandFlush, port->index, NULL);
|
||||
else if (exec_actions == MMALOMX_ACTION_NOTIFY_ENABLE)
|
||||
mmalomx_callback_event_handler(component, OMX_EventCmdComplete,
|
||||
OMX_CommandPortEnable, port->index, NULL);
|
||||
else if (exec_actions == MMALOMX_ACTION_NOTIFY_DISABLE)
|
||||
mmalomx_callback_event_handler(component, OMX_EventCmdComplete,
|
||||
OMX_CommandPortDisable, port->index, NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void mmalomx_commands_actions_check(MMALOMX_COMPONENT_T *component)
|
||||
{
|
||||
uint32_t actions_left = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < component->ports_num; i++)
|
||||
mmalomx_commands_check_port_actions(component, &component->ports[i]);
|
||||
|
||||
MMALOMX_LOCK(component);
|
||||
for (i = 0; i < component->ports_num; i++)
|
||||
actions_left |= component->ports[i].actions;
|
||||
|
||||
if (!actions_left && component->state_transition)
|
||||
{
|
||||
component->state = state_transition_table[component->state_transition].request;
|
||||
component->state_transition = 0;
|
||||
actions_left = MMALOMX_ACTION_NOTIFY_STATE;
|
||||
}
|
||||
MMALOMX_UNLOCK(component);
|
||||
|
||||
if (actions_left == MMALOMX_ACTION_NOTIFY_STATE)
|
||||
{
|
||||
mmalomx_callback_event_handler(component, OMX_EventCmdComplete,
|
||||
OMX_CommandStateSet, component->state, NULL);
|
||||
actions_left = 0;
|
||||
}
|
||||
|
||||
/* If we're not currently processing a command, we can start processing
|
||||
* the next one. */
|
||||
if (!actions_left)
|
||||
mmalomx_commands_actions_next(component);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void mmalomx_commands_actions_signal(MMALOMX_COMPONENT_T *component)
|
||||
{
|
||||
if (component->cmd_thread_used)
|
||||
vcos_semaphore_post(&component->cmd_sema);
|
||||
else
|
||||
mmalomx_commands_actions_check(component);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_command_state_set(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_STATETYPE state)
|
||||
{
|
||||
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
||||
unsigned int i, transition;
|
||||
|
||||
if (component->state == state)
|
||||
{
|
||||
mmalomx_callback_event_handler(component, OMX_EventError, OMX_ErrorSameState, 0, NULL);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/* We're asked to transition to StateInvalid */
|
||||
if (state == OMX_StateInvalid)
|
||||
{
|
||||
component->state = state;
|
||||
mmalomx_callback_event_handler(component, OMX_EventError, OMX_ErrorInvalidState, 0, NULL);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/* Commands are being queued so we should never get into that state */
|
||||
vcos_assert(!component->state_transition);
|
||||
|
||||
/* Check the transition is valid */
|
||||
transition = mmalomx_state_transition_get(component->state, state);
|
||||
if (!transition)
|
||||
{
|
||||
mmalomx_callback_event_handler(component, OMX_EventError, OMX_ErrorIncorrectStateTransition, 0, NULL);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/* Special case for transition in and out of Executing */
|
||||
if (state == OMX_StateExecuting || component->state == OMX_StateExecuting)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
if (state == OMX_StateExecuting)
|
||||
status = mmal_component_enable(component->mmal);
|
||||
else
|
||||
status = mmal_component_disable(component->mmal);
|
||||
|
||||
if (status != MMAL_SUCCESS)
|
||||
{
|
||||
LOG_ERROR("could not %s %s", state == OMX_StateExecuting ? "enable" : "disable", component->name);
|
||||
mmalomx_callback_event_handler(component, OMX_EventError, mmalil_error_to_omx(status), 0, NULL);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
}
|
||||
|
||||
MMALOMX_LOCK(component);
|
||||
component->state_transition = transition;
|
||||
|
||||
for (i = 0; i < component->ports_num; i++)
|
||||
{
|
||||
if (!component->ports[i].enabled)
|
||||
continue;
|
||||
|
||||
MMALOMX_LOCK_PORT(component, component->ports + i);
|
||||
component->ports[i].actions = state_transition_table[transition].actions;
|
||||
|
||||
/* If we're transitionning from Idle to Loaded we'd rather do a flush first
|
||||
* to avoid the cmd thread to block for too long (mmal_disable is a
|
||||
* blocking call). */
|
||||
if (state_transition_table[transition].state == OMX_StateIdle &&
|
||||
state_transition_table[transition].request == OMX_StateLoaded &&
|
||||
component->cmd_thread_used)
|
||||
component->ports[i].actions |= MMALOMX_ACTION_FLUSH|MMALOMX_ACTION_CHECK_FLUSHED;
|
||||
MMALOMX_UNLOCK_PORT(component, component->ports + i);
|
||||
}
|
||||
MMALOMX_UNLOCK(component);
|
||||
|
||||
mmalomx_commands_actions_check(component);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_command_port_mark(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_U32 nPortIndex,
|
||||
OMX_PTR *pCmdData)
|
||||
{
|
||||
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
||||
OMX_MARKTYPE *mark = (OMX_MARKTYPE *)pCmdData;
|
||||
MMALOMX_PORT_T *port;
|
||||
|
||||
if (nPortIndex >= component->ports_num)
|
||||
return OMX_ErrorBadPortIndex;
|
||||
port = &component->ports[nPortIndex];
|
||||
|
||||
if (port->marks_num == MAX_MARKS_NUM)
|
||||
return OMX_ErrorInsufficientResources;
|
||||
|
||||
port->marks[(port->marks_first + port->marks_num) % MAX_MARKS_NUM] = *mark;
|
||||
port->marks_num++;
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_command_port_flush(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_U32 nPortIndex)
|
||||
{
|
||||
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
||||
|
||||
MMALOMX_LOCK_PORT(component, &component->ports[nPortIndex]);
|
||||
component->ports[nPortIndex].actions =
|
||||
MMALOMX_ACTION_FLUSH|MMALOMX_ACTION_CHECK_FLUSHED|MMALOMX_ACTION_NOTIFY_FLUSH;
|
||||
MMALOMX_UNLOCK_PORT(component, &component->ports[nPortIndex]);
|
||||
|
||||
mmalomx_commands_actions_check(component);
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_command_port_enable(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_U32 nPortIndex)
|
||||
{
|
||||
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
||||
component->ports[nPortIndex].enabled = MMAL_TRUE;
|
||||
|
||||
if (component->state == OMX_StateLoaded ||
|
||||
component->state == OMX_StateWaitForResources)
|
||||
{
|
||||
mmalomx_callback_event_handler(component, OMX_EventCmdComplete, OMX_CommandPortEnable, nPortIndex, NULL);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
MMALOMX_LOCK_PORT(component, &component->ports[nPortIndex]);
|
||||
component->ports[nPortIndex].actions =
|
||||
MMALOMX_ACTION_CHECK_ALLOCATED|MMALOMX_ACTION_ENABLE|MMALOMX_ACTION_NOTIFY_ENABLE;
|
||||
MMALOMX_UNLOCK_PORT(component, &component->ports[nPortIndex]);
|
||||
|
||||
mmalomx_commands_actions_check(component);
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_command_port_disable(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_U32 nPortIndex)
|
||||
{
|
||||
MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
|
||||
component->ports[nPortIndex].enabled = MMAL_FALSE;
|
||||
|
||||
if (component->state == OMX_StateLoaded ||
|
||||
component->state == OMX_StateWaitForResources)
|
||||
{
|
||||
mmalomx_callback_event_handler(component, OMX_EventCmdComplete, OMX_CommandPortDisable, nPortIndex, NULL);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
MMALOMX_LOCK_PORT(component, &component->ports[nPortIndex]);
|
||||
component->ports[nPortIndex].actions =
|
||||
MMALOMX_ACTION_DISABLE|MMALOMX_ACTION_CHECK_DEALLOCATED|MMALOMX_ACTION_NOTIFY_DISABLE;
|
||||
if (component->cmd_thread_used)
|
||||
component->ports[nPortIndex].actions |=
|
||||
MMALOMX_ACTION_FLUSH|MMALOMX_ACTION_CHECK_FLUSHED;
|
||||
MMALOMX_UNLOCK_PORT(component, &component->ports[nPortIndex]);
|
||||
|
||||
mmalomx_commands_actions_check(component);
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_command_queue(
|
||||
MMALOMX_COMPONENT_T *component,
|
||||
OMX_U32 arg1, OMX_U32 arg2)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *cmd = mmal_queue_get(component->cmd_pool->queue);
|
||||
|
||||
if (!vcos_verify(cmd))
|
||||
{
|
||||
LOG_ERROR("command queue too small");
|
||||
return OMX_ErrorInsufficientResources;
|
||||
}
|
||||
|
||||
cmd->cmd = arg1;
|
||||
cmd->offset = arg2;
|
||||
mmal_queue_put(component->cmd_queue, cmd);
|
||||
|
||||
mmalomx_commands_actions_signal(component);
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_command_dequeue(
|
||||
MMALOMX_COMPONENT_T *component,
|
||||
OMX_U32 *arg1, OMX_U32 *arg2)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *cmd = mmal_queue_get(component->cmd_queue);
|
||||
if (!cmd)
|
||||
return OMX_ErrorNoMore;
|
||||
|
||||
*arg1 = cmd->cmd;
|
||||
*arg2 = cmd->offset;
|
||||
mmal_buffer_header_release(cmd);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void mmalomx_commands_actions_next(MMALOMX_COMPONENT_T *component)
|
||||
{
|
||||
OMX_ERRORTYPE status = OMX_ErrorNone;
|
||||
OMX_COMMANDTYPE cmd;
|
||||
OMX_U32 arg1, arg2, nParam1;
|
||||
unsigned int i;
|
||||
|
||||
status = mmalomx_command_dequeue(component, &arg1, &arg2);
|
||||
if (status != OMX_ErrorNone)
|
||||
return;
|
||||
|
||||
cmd = (OMX_COMMANDTYPE)arg1;
|
||||
nParam1 = arg2;
|
||||
|
||||
if (cmd == OMX_CommandStateSet)
|
||||
{
|
||||
mmalomx_command_state_set((OMX_HANDLETYPE)&component->omx, nParam1);
|
||||
}
|
||||
else if (cmd == OMX_CommandFlush)
|
||||
{
|
||||
for (i = 0; i < component->ports_num; i++)
|
||||
if (i == nParam1 || nParam1 == OMX_ALL)
|
||||
mmalomx_command_port_flush((OMX_HANDLETYPE)&component->omx, i);
|
||||
}
|
||||
else if (cmd == OMX_CommandPortEnable)
|
||||
{
|
||||
for (i = 0; i < component->ports_num; i++)
|
||||
if (i == nParam1 || nParam1 == OMX_ALL)
|
||||
mmalomx_command_port_enable((OMX_HANDLETYPE)&component->omx, i);
|
||||
}
|
||||
else if (cmd == OMX_CommandPortDisable)
|
||||
{
|
||||
for (i = 0; i < component->ports_num; i++)
|
||||
if (i == nParam1 || nParam1 == OMX_ALL)
|
||||
mmalomx_command_port_disable((OMX_HANDLETYPE)&component->omx, i);
|
||||
}
|
||||
}
|
||||
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Commands related functions
|
||||
*/
|
||||
|
||||
OMX_ERRORTYPE mmalomx_command_state_set(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_STATETYPE state);
|
||||
|
||||
OMX_ERRORTYPE mmalomx_command_port_mark(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_U32 nPortIndex,
|
||||
OMX_PTR *pCmdData);
|
||||
|
||||
OMX_ERRORTYPE mmalomx_command_port_flush(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_U32 nPortIndex);
|
||||
|
||||
OMX_ERRORTYPE mmalomx_command_port_enable(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_U32 nPortIndex);
|
||||
|
||||
OMX_ERRORTYPE mmalomx_command_port_disable(
|
||||
OMX_HANDLETYPE hComponent,
|
||||
OMX_U32 nPortIndex);
|
||||
|
||||
#define MMALOMX_ACTION_ENABLE 0x01
|
||||
#define MMALOMX_ACTION_DISABLE 0x02
|
||||
#define MMALOMX_ACTION_FLUSH 0x04
|
||||
|
||||
#define MMALOMX_ACTION_PENDING_ENABLE 0x010
|
||||
#define MMALOMX_ACTION_PENDING_DISABLE 0x020
|
||||
#define MMALOMX_ACTION_PENDING_FLUSH 0x040
|
||||
|
||||
#define MMALOMX_ACTION_CHECK_ALLOCATED 0x0100
|
||||
#define MMALOMX_ACTION_CHECK_DEALLOCATED 0x0200
|
||||
#define MMALOMX_ACTION_CHECK_FLUSHED 0x0400
|
||||
|
||||
#define MMALOMX_ACTION_NOTIFY_DISABLE 0x1000
|
||||
#define MMALOMX_ACTION_NOTIFY_ENABLE 0x2000
|
||||
#define MMALOMX_ACTION_NOTIFY_FLUSH 0x4000
|
||||
#define MMALOMX_ACTION_NOTIFY_STATE 0x8000
|
||||
|
||||
#define MMALOMX_COMMAND_EXIT 0
|
||||
#define MMALOMX_COMMAND_STATE_SET 1
|
||||
#define MMALOMX_COMMAND_PORT_MARK 2
|
||||
#define MMALOMX_COMMAND_PORT_FLUSH 3
|
||||
#define MMALOMX_COMMAND_PORT_ENABLE 4
|
||||
#define MMALOMX_COMMAND_PORT_DISABLE 5
|
||||
|
||||
OMX_ERRORTYPE mmalomx_command_queue(
|
||||
MMALOMX_COMPONENT_T *component, OMX_U32 arg1, OMX_U32 arg2);
|
||||
OMX_ERRORTYPE mmalomx_command_dequeue(
|
||||
MMALOMX_COMPONENT_T *component, OMX_U32 *arg1, OMX_U32 *arg2);
|
||||
|
||||
void mmalomx_commands_actions_check(MMALOMX_COMPONENT_T *component);
|
||||
void mmalomx_commands_actions_signal(MMALOMX_COMPONENT_T *component);
|
||||
void mmalomx_commands_actions_next(MMALOMX_COMPONENT_T *component);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,176 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Core.h"
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Component.h"
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Video.h"
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Audio.h"
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Broadcom.h"
|
||||
#include "mmalomx_logging.h"
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_util_params.h"
|
||||
#include "interface/vcos/vcos_types.h"
|
||||
|
||||
VCOS_LOG_CAT_T mmalomx_log_category;
|
||||
static VCOS_LOG_LEVEL_T mmalomx_log_level = VCOS_LOG_ERROR;
|
||||
|
||||
#define MMALOMX_SAT(a,b,c) ((a)<(b)?(a):(a)>(c)?(c):(a))
|
||||
|
||||
void mmalomx_logging_init(void)
|
||||
{
|
||||
vcos_log_set_level(VCOS_LOG_CATEGORY, mmalomx_log_level);
|
||||
vcos_log_register("mmalomx", VCOS_LOG_CATEGORY);
|
||||
}
|
||||
|
||||
void mmalomx_logging_deinit(void)
|
||||
{
|
||||
mmalomx_log_level = mmalomx_log_category.level;
|
||||
vcos_log_unregister(VCOS_LOG_CATEGORY);
|
||||
}
|
||||
|
||||
const char *mmalomx_param_to_string(OMX_INDEXTYPE param)
|
||||
{
|
||||
static const struct {
|
||||
const char *string;
|
||||
const OMX_INDEXTYPE param;
|
||||
} param_to_names[] =
|
||||
{
|
||||
{"OMX_IndexParamPriorityMgmt", OMX_IndexParamPriorityMgmt},
|
||||
{"OMX_IndexParamAudioInit", OMX_IndexParamAudioInit},
|
||||
{"OMX_IndexParamImageInit", OMX_IndexParamImageInit},
|
||||
{"OMX_IndexParamVideoInit", OMX_IndexParamVideoInit},
|
||||
{"OMX_IndexParamOtherInit", OMX_IndexParamOtherInit},
|
||||
{"OMX_IndexParamPortDefinition", OMX_IndexParamPortDefinition},
|
||||
{"OMX_IndexParamCompBufferSupplier", OMX_IndexParamCompBufferSupplier},
|
||||
{"OMX_IndexParamAudioPortFormat", OMX_IndexParamAudioPortFormat},
|
||||
{"OMX_IndexParamVideoPortFormat", OMX_IndexParamVideoPortFormat},
|
||||
{"OMX_IndexParamImagePortFormat", OMX_IndexParamImagePortFormat},
|
||||
{"OMX_IndexParamOtherPortFormat", OMX_IndexParamOtherPortFormat},
|
||||
{"OMX_IndexParamAudioPcm", OMX_IndexParamAudioPcm},
|
||||
{"OMX_IndexParamAudioAac", OMX_IndexParamAudioAac},
|
||||
{"OMX_IndexParamAudioMp3", OMX_IndexParamAudioMp3},
|
||||
{"OMX_IndexParamVideoMpeg2", OMX_IndexParamVideoMpeg2},
|
||||
{"OMX_IndexParamVideoMpeg4", OMX_IndexParamVideoMpeg4},
|
||||
{"OMX_IndexParamVideoWmv", OMX_IndexParamVideoWmv},
|
||||
{"OMX_IndexParamVideoRv", OMX_IndexParamVideoRv},
|
||||
{"OMX_IndexParamVideoAvc", OMX_IndexParamVideoAvc},
|
||||
{"OMX_IndexParamVideoH263", OMX_IndexParamVideoH263},
|
||||
{"OMX_IndexParamStandardComponentRole", OMX_IndexParamStandardComponentRole},
|
||||
{"OMX_IndexParamContentURI", OMX_IndexParamContentURI},
|
||||
{"OMX_IndexParamCommonSensorMode", OMX_IndexParamCommonSensorMode},
|
||||
{"OMX_IndexConfigCommonWhiteBalance", OMX_IndexConfigCommonWhiteBalance},
|
||||
{"OMX_IndexConfigCommonDigitalZoom", OMX_IndexConfigCommonDigitalZoom},
|
||||
{"OMX_IndexConfigCommonExposureValue", OMX_IndexConfigCommonExposureValue},
|
||||
{"OMX_IndexConfigCapturing", OMX_IndexConfigCapturing},
|
||||
{"OMX_IndexAutoPauseAfterCapture", OMX_IndexAutoPauseAfterCapture},
|
||||
{"OMX_IndexConfigCommonRotate", OMX_IndexConfigCommonRotate},
|
||||
{"OMX_IndexConfigCommonMirror", OMX_IndexConfigCommonMirror},
|
||||
{"OMX_IndexConfigCommonScale", OMX_IndexConfigCommonScale},
|
||||
{"OMX_IndexConfigCommonInputCrop", OMX_IndexConfigCommonInputCrop},
|
||||
{"OMX_IndexConfigCommonOutputCrop", OMX_IndexConfigCommonOutputCrop},
|
||||
{"OMX_IndexParamNumAvailableStreams", OMX_IndexParamNumAvailableStreams},
|
||||
{"OMX_IndexParamActiveStream", OMX_IndexParamActiveStream},
|
||||
{"OMX_IndexParamVideoBitrate", OMX_IndexParamVideoBitrate},
|
||||
{"OMX_IndexParamVideoProfileLevelQuerySupported", OMX_IndexParamVideoProfileLevelQuerySupported},
|
||||
|
||||
{"OMX_IndexParam unknown", (OMX_INDEXTYPE)0}
|
||||
};
|
||||
const char *name = mmalomx_parameter_name_omx((uint32_t)param);
|
||||
int i;
|
||||
|
||||
if (name)
|
||||
return name;
|
||||
|
||||
for(i = 0; param_to_names[i].param &&
|
||||
param_to_names[i].param != param; i++);
|
||||
|
||||
return param_to_names[i].string;
|
||||
}
|
||||
|
||||
const char *mmalomx_cmd_to_string(OMX_COMMANDTYPE cmd)
|
||||
{
|
||||
static const char *names[] = {
|
||||
"OMX_CommandStateSet", "OMX_CommandFlush", "OMX_CommandPortDisable",
|
||||
"OMX_CommandPortEnable", "OMX_CommandMarkBuffer", "OMX_Command unknown"
|
||||
};
|
||||
|
||||
return names[MMALOMX_SAT((int)cmd, 0, (int)vcos_countof(names)-1)];
|
||||
}
|
||||
|
||||
const char *mmalomx_state_to_string(OMX_STATETYPE state)
|
||||
{
|
||||
static const char *names[] = {
|
||||
"OMX_StateInvalid", "OMX_StateLoaded", "OMX_StateIdle",
|
||||
"OMX_StateExecuting", "OMX_StatePause", "OMX_StateWaitForResources",
|
||||
"OMX_State unknown"
|
||||
};
|
||||
|
||||
return names[MMALOMX_SAT((int)state, 0, (int)vcos_countof(names)-1)];
|
||||
}
|
||||
|
||||
const char *mmalomx_event_to_string(OMX_EVENTTYPE event)
|
||||
{
|
||||
static const char *names[] = {
|
||||
"OMX_EventCmdComplete", "OMX_EventError", "OMX_EventMark",
|
||||
"OMX_EventPortSettingsChanged", "OMX_EventBufferFlag",
|
||||
"OMX_EventResourcesAcquired", "OMX_EventComponentResumed",
|
||||
"OMX_EventDynamicResourcesAvailable", "OMX_EventPortFormatDetected",
|
||||
"OMX_Event unknown"
|
||||
};
|
||||
|
||||
return names[MMALOMX_SAT((int)event, 0, (int)vcos_countof(names)-1)];
|
||||
}
|
||||
|
||||
const char *mmalomx_error_to_string(OMX_ERRORTYPE error)
|
||||
{
|
||||
static const char *names[] = {
|
||||
"OMX_ErrorInsufficientResources", "OMX_ErrorUndefined",
|
||||
"OMX_ErrorInvalidComponentName", "OMX_ErrorComponentNotFound",
|
||||
"OMX_ErrorInvalidComponent", "OMX_ErrorBadParameter",
|
||||
"OMX_ErrorNotImplemented", "OMX_ErrorUnderflow",
|
||||
"OMX_ErrorOverflow", "OMX_ErrorHardware", "OMX_ErrorInvalidState",
|
||||
"OMX_ErrorStreamCorrupt", "OMX_ErrorPortsNotCompatible",
|
||||
"OMX_ErrorResourcesLost", "OMX_ErrorNoMore", "OMX_ErrorVersionMismatch",
|
||||
"OMX_ErrorNotReady", "OMX_ErrorTimeout", "OMX_ErrorSameState",
|
||||
"OMX_ErrorResourcesPreempted", "OMX_ErrorPortUnresponsiveDuringAllocation",
|
||||
"OMX_ErrorPortUnresponsiveDuringDeallocation",
|
||||
"OMX_ErrorPortUnresponsiveDuringStop", "OMX_ErrorIncorrectStateTransition",
|
||||
"OMX_ErrorIncorrectStateOperation", "OMX_ErrorUnsupportedSetting",
|
||||
"OMX_ErrorUnsupportedIndex", "OMX_ErrorBadPortIndex",
|
||||
"OMX_ErrorPortUnpopulated", "OMX_ErrorComponentSuspended",
|
||||
"OMX_ErrorDynamicResourcesUnavailable", "OMX_ErrorMbErrorsInFrame",
|
||||
"OMX_ErrorFormatNotDetected", "OMX_ErrorContentPipeOpenFailed",
|
||||
"OMX_ErrorContentPipeCreationFailed", "OMX_ErrorSeperateTablesUsed",
|
||||
"OMX_ErrorTunnelingUnsupported",
|
||||
"OMX_Error unkown"
|
||||
};
|
||||
|
||||
if(error == OMX_ErrorNone) return "OMX_ErrorNone";
|
||||
|
||||
error -= OMX_ErrorInsufficientResources;
|
||||
return names[MMALOMX_SAT((int)error, 0, (int)vcos_countof(names)-1)];
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Logging functions
|
||||
*/
|
||||
|
||||
#include "mmal_common.h"
|
||||
#include "interface/vcos/vcos_logging.h"
|
||||
|
||||
#define VCOS_LOG_CATEGORY (&mmalomx_log_category)
|
||||
extern VCOS_LOG_CAT_T mmalomx_log_category;
|
||||
#include <mmal_logging.h>
|
||||
|
||||
void mmalomx_logging_init(void);
|
||||
void mmalomx_logging_deinit(void);
|
||||
|
||||
const char *mmalomx_param_to_string(OMX_INDEXTYPE param);
|
||||
const char *mmalomx_cmd_to_string(OMX_COMMANDTYPE cmd);
|
||||
const char *mmalomx_state_to_string(OMX_STATETYPE state);
|
||||
const char *mmalomx_event_to_string(OMX_EVENTTYPE event);
|
||||
const char *mmalomx_error_to_string(OMX_ERRORTYPE error);
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Marking related functions
|
||||
*
|
||||
* Note that we do not support buffer marks properly other than for conformance
|
||||
* testing. For input ports, we just move the mark over to the output port.
|
||||
*/
|
||||
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_buffer.h"
|
||||
#include "mmalomx_marks.h"
|
||||
#include "mmalomx_commands.h"
|
||||
#include "mmalomx_logging.h"
|
||||
|
||||
#define MMALOMX_GET_MARK(port, mark) \
|
||||
mark = &port->marks[port->marks_first]; \
|
||||
port->marks_num--; \
|
||||
port->marks_first = ++port->marks_first == MAX_MARKS_NUM ? 0 : port->marks_first
|
||||
#define MMALOMX_PUT_MARK(port, mark) \
|
||||
port->marks[(port->marks_first + port->marks_num) % MAX_MARKS_NUM] = *mark; \
|
||||
port->marks_num++;
|
||||
|
||||
void mmalomx_mark_process_incoming(MMALOMX_COMPONENT_T *component,
|
||||
MMALOMX_PORT_T *port, OMX_BUFFERHEADERTYPE *omx_buffer)
|
||||
{
|
||||
/* Tag buffers with OMX marks */
|
||||
if (!omx_buffer->hMarkTargetComponent && port->marks_num > 0 &&
|
||||
port->direction == OMX_DirInput)
|
||||
{
|
||||
OMX_MARKTYPE *mark;
|
||||
MMALOMX_GET_MARK(port, mark);
|
||||
omx_buffer->hMarkTargetComponent = mark->hMarkTargetComponent;
|
||||
omx_buffer->pMarkData = mark->pMarkData;
|
||||
|
||||
mmalomx_callback_event_handler(component, OMX_EventCmdComplete,
|
||||
OMX_CommandMarkBuffer, port->index, NULL);
|
||||
}
|
||||
/* We do not support buffer marks properly other than for conformance testing.
|
||||
* For input ports, we just move the mark over to the output port. */
|
||||
if (port->direction == OMX_DirInput && omx_buffer->hMarkTargetComponent)
|
||||
{
|
||||
OMX_MARKTYPE mark = {omx_buffer->hMarkTargetComponent, omx_buffer->pMarkData};
|
||||
unsigned int i;
|
||||
for (i = 0; i < component->ports_num; i++)
|
||||
{
|
||||
if (component->ports[i].direction != OMX_DirOutput ||
|
||||
component->ports[i].marks_num >= MAX_MARKS_NUM)
|
||||
continue;
|
||||
|
||||
MMALOMX_PUT_MARK((&component->ports[i]), (&mark));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mmalomx_mark_process_outgoing(MMALOMX_COMPONENT_T *component,
|
||||
MMALOMX_PORT_T *port, OMX_BUFFERHEADERTYPE *omx_buffer)
|
||||
{
|
||||
/* Tag buffers with OMX marks */
|
||||
if (port->direction == OMX_DirOutput &&
|
||||
!omx_buffer->hMarkTargetComponent && port->marks_num)
|
||||
{
|
||||
OMX_MARKTYPE *mark;
|
||||
MMALOMX_GET_MARK(port, mark);
|
||||
omx_buffer->hMarkTargetComponent = mark->hMarkTargetComponent;
|
||||
omx_buffer->pMarkData = mark->pMarkData;
|
||||
}
|
||||
/* Check if we need to trigger a Mark event */
|
||||
if (omx_buffer->hMarkTargetComponent &&
|
||||
omx_buffer->hMarkTargetComponent == (OMX_HANDLETYPE)&component->omx)
|
||||
{
|
||||
mmalomx_callback_event_handler(component, OMX_EventMark, 0, 0, omx_buffer->pMarkData);
|
||||
omx_buffer->hMarkTargetComponent = NULL;
|
||||
omx_buffer->pMarkData = NULL;
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Marking related functions
|
||||
*/
|
||||
|
||||
void mmalomx_mark_process_incoming(MMALOMX_COMPONENT_T *component,
|
||||
MMALOMX_PORT_T *port, OMX_BUFFERHEADERTYPE *omx_buffer);
|
||||
void mmalomx_mark_process_outgoing(MMALOMX_COMPONENT_T *component,
|
||||
MMALOMX_PORT_T *port, OMX_BUFFERHEADERTYPE *omx_buffer);
|
||||
|
@ -1,578 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Broadcom.h"
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_parameters.h"
|
||||
#include "mmalomx_util_params.h"
|
||||
#include "mmalomx_roles.h"
|
||||
#include "mmalomx_registry.h"
|
||||
#include "mmalomx_logging.h"
|
||||
#include <util/mmal_util.h>
|
||||
#include <util/mmal_util_params.h>
|
||||
#include <util/mmal_util_rational.h>
|
||||
|
||||
#define PARAM_GET_PORT(port, component, index) \
|
||||
if (index >= component->ports_num) return OMX_ErrorBadPortIndex; \
|
||||
port = &component->ports[index]
|
||||
|
||||
#define MMALOMX_PARAM_GENERIC_MAX 256
|
||||
|
||||
/** A structure capable of holding any OMX parameter that contains a port */
|
||||
typedef struct MMALOMX_PARAM_OMX_GENERIC_T
|
||||
{
|
||||
MMALOMX_PARAM_OMX_HEADER_T header;
|
||||
uint8_t data[MMALOMX_PARAM_GENERIC_MAX];
|
||||
} MMALOMX_PARAM_OMX_GENERIC_T;
|
||||
|
||||
/** A structure capable of holding any OMX parameter that doesn't contain a port */
|
||||
typedef struct MMALOMX_PARAM_OMX_GENERIC_PORTLESS_T
|
||||
{
|
||||
MMALOMX_PARAM_OMX_HEADER_PORTLESS_T hdr;
|
||||
uint8_t data[MMALOMX_PARAM_GENERIC_MAX];
|
||||
} MMALOMX_PARAM_OMX_GENERIC_PORTLESS_T;
|
||||
|
||||
/** A structure capable of holding any MMAL parameter */
|
||||
typedef struct MMALOMX_PARAM_MMAL_GENERIC_T
|
||||
{
|
||||
MMAL_PARAMETER_HEADER_T header;
|
||||
uint8_t data[MMALOMX_PARAM_GENERIC_MAX];
|
||||
} MMALOMX_PARAM_MMAL_GENERIC_T;
|
||||
|
||||
static OMX_ERRORTYPE mmalomx_parameter_set_xlat(MMALOMX_COMPONENT_T *component,
|
||||
OMX_INDEXTYPE nParamIndex, OMX_PTR pParam)
|
||||
{
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat = mmalomx_find_parameter_from_omx_id(nParamIndex);
|
||||
MMALOMX_PARAM_OMX_HEADER_T *omx_header = (MMALOMX_PARAM_OMX_HEADER_T *)pParam;
|
||||
MMALOMX_PARAM_MMAL_GENERIC_T mmal_generic;
|
||||
MMAL_PARAMETER_HEADER_T *mmal_header = &mmal_generic.header;
|
||||
MMAL_PORT_T *mmal_port = component->mmal->control;
|
||||
MMAL_STATUS_T status;
|
||||
|
||||
if (!xlat)
|
||||
{
|
||||
LOG_DEBUG("no translation for omx id 0x%08x", nParamIndex);
|
||||
return OMX_ErrorNotImplemented;
|
||||
}
|
||||
|
||||
if (!xlat->portless)
|
||||
{
|
||||
if (omx_header->nSize < sizeof(*omx_header))
|
||||
return OMX_ErrorBadParameter;
|
||||
if (omx_header->nPortIndex >= component->ports_num)
|
||||
return OMX_ErrorBadPortIndex;
|
||||
mmal_port = component->ports[omx_header->nPortIndex].mmal;
|
||||
}
|
||||
|
||||
if (omx_header->nSize < xlat->omx_size)
|
||||
return OMX_ErrorBadParameter;
|
||||
|
||||
/* Handle the direct case first */
|
||||
if (xlat->type == MMALOMX_PARAM_TRANSLATION_TYPE_DIRECT)
|
||||
{
|
||||
mmal_header = (MMAL_PARAMETER_HEADER_T *)(((uint8_t *)pParam) + (xlat->portless ? 0 : 4));
|
||||
mmal_generic.header = *mmal_header;
|
||||
mmal_header->size = omx_header->nSize - (xlat->portless ? 0 : 4);
|
||||
mmal_header->id = xlat->mmal_id;
|
||||
status = mmal_port_parameter_set(mmal_port, mmal_header);
|
||||
*mmal_header = mmal_generic.header;
|
||||
return mmalil_error_to_omx(status);
|
||||
}
|
||||
|
||||
if (!xlat->fn.generic && !xlat->fn.simple)
|
||||
{
|
||||
// FIXME
|
||||
return OMX_ErrorNotImplemented;
|
||||
}
|
||||
|
||||
// FIXME: check size of mmal_generic is sufficient
|
||||
if (sizeof(mmal_generic) < xlat->mmal_size)
|
||||
return OMX_ErrorBadParameter;
|
||||
|
||||
mmal_header->size = xlat->mmal_size;
|
||||
mmal_header->id = xlat->mmal_id;
|
||||
if (xlat->fn.generic)
|
||||
status = xlat->fn.generic(MMALOMX_PARAM_MAPPING_TO_MMAL, xlat, mmal_header, pParam, mmal_port);
|
||||
else
|
||||
status = xlat->fn.simple(MMALOMX_PARAM_MAPPING_TO_MMAL, mmal_header, pParam);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
status = mmal_port_parameter_set(mmal_port, mmal_header);
|
||||
|
||||
error:
|
||||
return mmalil_error_to_omx(status);
|
||||
}
|
||||
|
||||
static OMX_ERRORTYPE mmalomx_parameter_get_xlat(MMALOMX_COMPONENT_T *component,
|
||||
OMX_INDEXTYPE nParamIndex, OMX_PTR pParam)
|
||||
{
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat = mmalomx_find_parameter_from_omx_id(nParamIndex);
|
||||
MMALOMX_PARAM_OMX_HEADER_T *omx_header = (MMALOMX_PARAM_OMX_HEADER_T *)pParam;
|
||||
MMALOMX_PARAM_MMAL_GENERIC_T mmal_generic;
|
||||
MMAL_PARAMETER_HEADER_T *mmal_header = &mmal_generic.header;
|
||||
MMAL_PORT_T *mmal_port = component->mmal->control;
|
||||
MMAL_STATUS_T status = MMAL_SUCCESS;
|
||||
|
||||
if (!xlat)
|
||||
return OMX_ErrorNotImplemented;
|
||||
|
||||
if (!xlat->portless)
|
||||
{
|
||||
if (omx_header->nSize < sizeof(*omx_header))
|
||||
return OMX_ErrorBadParameter;
|
||||
if (omx_header->nPortIndex >= component->ports_num)
|
||||
return OMX_ErrorBadPortIndex;
|
||||
mmal_port = component->ports[omx_header->nPortIndex].mmal;
|
||||
}
|
||||
|
||||
if (omx_header->nSize < xlat->omx_size)
|
||||
return OMX_ErrorBadParameter;
|
||||
|
||||
/* Handle the direct case first */
|
||||
if (xlat->type == MMALOMX_PARAM_TRANSLATION_TYPE_DIRECT)
|
||||
{
|
||||
OMX_U32 size;
|
||||
mmal_header = (MMAL_PARAMETER_HEADER_T *)(((uint8_t *)pParam) + (xlat->portless ? 0 : 4));
|
||||
mmal_generic.header = *mmal_header;
|
||||
mmal_header->size = omx_header->nSize - (xlat->portless ? 0 : 4);
|
||||
mmal_header->id = xlat->mmal_id;
|
||||
status = mmal_port_parameter_get(mmal_port, mmal_header);
|
||||
*mmal_header = mmal_generic.header;
|
||||
size = mmal_header->size + (xlat->portless ? 0 : 4);
|
||||
omx_header->nSize = size;
|
||||
return mmalil_error_to_omx(status);
|
||||
}
|
||||
|
||||
if (xlat->fn.custom)
|
||||
{
|
||||
return xlat->fn.custom(MMALOMX_PARAM_MAPPING_TO_OMX, xlat, mmal_header,
|
||||
pParam, mmal_port);
|
||||
}
|
||||
|
||||
if (xlat->fn.list)
|
||||
{
|
||||
OMX_U32 index, elements;
|
||||
mmal_header = mmal_port_parameter_alloc_get(mmal_port, xlat->mmal_id,
|
||||
10*xlat->mmal_size, &status);
|
||||
if (!mmal_header)
|
||||
return OMX_ErrorInsufficientResources;
|
||||
|
||||
/* Check we're not requesting too much */
|
||||
index = *(OMX_U32 *)(((uint8_t *)pParam) + xlat->xlat_enum_num);
|
||||
elements = (mmal_header->size - sizeof(MMAL_PARAMETER_HEADER_T)) /
|
||||
(xlat->mmal_size - sizeof(MMAL_PARAMETER_HEADER_T));
|
||||
if (index >= elements)
|
||||
{
|
||||
vcos_free(mmal_header);
|
||||
return OMX_ErrorNoMore;
|
||||
}
|
||||
status = xlat->fn.list(MMALOMX_PARAM_MAPPING_TO_OMX, xlat, index, mmal_header, pParam, mmal_port);
|
||||
vcos_free(mmal_header);
|
||||
return mmalil_error_to_omx(status);
|
||||
}
|
||||
|
||||
if (!xlat->fn.generic && !xlat->fn.simple)
|
||||
{
|
||||
// FIXME
|
||||
return OMX_ErrorNotImplemented;
|
||||
}
|
||||
|
||||
// FIXME: check size of mmal_generic is sufficient
|
||||
if (sizeof(mmal_generic) < xlat->mmal_size)
|
||||
return OMX_ErrorBadParameter;
|
||||
|
||||
mmal_header->size = xlat->mmal_size;
|
||||
mmal_header->id = xlat->mmal_id;
|
||||
|
||||
if (xlat->double_translation)
|
||||
{
|
||||
if (xlat->fn.generic)
|
||||
status = xlat->fn.generic(MMALOMX_PARAM_MAPPING_TO_MMAL, xlat, mmal_header, pParam, mmal_port);
|
||||
else
|
||||
status = xlat->fn.simple(MMALOMX_PARAM_MAPPING_TO_MMAL, mmal_header, pParam);
|
||||
}
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
status = mmal_port_parameter_get(mmal_port, mmal_header);
|
||||
if (status != MMAL_SUCCESS)
|
||||
goto error;
|
||||
|
||||
if (xlat->fn.generic)
|
||||
status = xlat->fn.generic(MMALOMX_PARAM_MAPPING_TO_OMX, xlat, mmal_header, pParam, mmal_port);
|
||||
else
|
||||
status = xlat->fn.simple(MMALOMX_PARAM_MAPPING_TO_OMX, mmal_header, pParam);
|
||||
|
||||
error:
|
||||
return mmalil_error_to_omx(status);
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE mmalomx_parameter_extension_index_get(OMX_STRING cParameterName,
|
||||
OMX_INDEXTYPE *pIndex)
|
||||
{
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat;
|
||||
MMAL_BOOL_T config = MMAL_FALSE;
|
||||
unsigned int i = 0;
|
||||
|
||||
/* Check we're dealing with our extensions */
|
||||
if (!vcos_strncasecmp(cParameterName, MMALOMX_COMPONENT_PREFIX, sizeof(MMALOMX_COMPONENT_PREFIX)-1))
|
||||
return OMX_ErrorNotImplemented;
|
||||
cParameterName += sizeof(MMALOMX_COMPONENT_PREFIX)-1;
|
||||
|
||||
/* Check if we're dealing with a config or param */
|
||||
if (!vcos_strncasecmp(cParameterName, "index.config.", sizeof("index.config.")-1))
|
||||
config = MMAL_TRUE;
|
||||
if (!config && vcos_strncasecmp(cParameterName, "index.param.", sizeof("index.param.")-1))
|
||||
return OMX_ErrorNotImplemented;
|
||||
if (config)
|
||||
cParameterName += sizeof("index.config.")-1;
|
||||
else
|
||||
cParameterName += sizeof("index.param.")-1;
|
||||
|
||||
/* Loop through all the */
|
||||
while ((xlat = mmalomx_find_parameter_enum(i++)) != NULL)
|
||||
{
|
||||
const char *name = xlat->omx_name;
|
||||
|
||||
/* We only report vendor extensions */
|
||||
if (xlat->omx_id < OMX_IndexVendorStartUnused)
|
||||
continue;
|
||||
|
||||
/* Strip out the standard prefix */
|
||||
if (config)
|
||||
{
|
||||
if (!strncmp(name, "OMX_IndexConfigBrcm", sizeof("OMX_IndexConfigBrcm")-1))
|
||||
name += sizeof("OMX_IndexConfigBrcm")-1;
|
||||
else if (!strncmp(name, "OMX_IndexConfig", sizeof("OMX_IndexConfig")-1))
|
||||
name += sizeof("OMX_IndexConfig")-1;
|
||||
else continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strncmp(name, "OMX_IndexParamBrcm", sizeof("OMX_IndexParamBrcm")-1))
|
||||
name += sizeof("OMX_IndexParamBrcm")-1;
|
||||
else if (!strncmp(name, "OMX_IndexParam", sizeof("OMX_IndexParam")-1))
|
||||
name += sizeof("OMX_IndexParam")-1;
|
||||
else continue;
|
||||
}
|
||||
|
||||
/* Compare the last part of the name */
|
||||
if (!vcos_strcasecmp(name, cParameterName))
|
||||
{
|
||||
*pIndex = xlat->omx_id;
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
}
|
||||
|
||||
return OMX_ErrorNotImplemented;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static OMX_ERRORTYPE mmalomx_get_video_param(MMALOMX_PORT_T *port,
|
||||
uint32_t *profile, uint32_t *level, uint32_t *intraperiod)
|
||||
{
|
||||
MMAL_PARAMETER_VIDEO_PROFILE_T mmal_param = {{MMAL_PARAMETER_PROFILE, sizeof(mmal_param)},
|
||||
{{(MMAL_VIDEO_PROFILE_T)0, (MMAL_VIDEO_LEVEL_T)0}}};
|
||||
|
||||
*profile = *level = *intraperiod = 0;
|
||||
|
||||
mmal_port_parameter_get_uint32(port->mmal, MMAL_PARAMETER_INTRAPERIOD, intraperiod);
|
||||
|
||||
if (mmal_port_parameter_get(port->mmal, &mmal_param.hdr) == MMAL_SUCCESS)
|
||||
{
|
||||
*profile = mmalil_video_profile_to_omx(mmal_param.profile[0].profile);
|
||||
*level = mmalil_video_level_to_omx(mmal_param.profile[0].level);
|
||||
}
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_parameter_get(MMALOMX_COMPONENT_T *component,
|
||||
OMX_INDEXTYPE nParamIndex, OMX_PTR pParam)
|
||||
{
|
||||
MMALOMX_PORT_T *port = NULL;
|
||||
|
||||
switch(nParamIndex)
|
||||
{
|
||||
/* All OMX_IndexParamVideo parameters are only partially implemented
|
||||
* and we try and use sensible hard-coded values for the rest. */
|
||||
case OMX_IndexParamVideoAvc:
|
||||
{
|
||||
OMX_VIDEO_PARAM_AVCTYPE *param = (OMX_VIDEO_PARAM_AVCTYPE *)pParam;
|
||||
uint32_t profile, level, intraperiod;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
if (param->nSize < sizeof(*param))
|
||||
return OMX_ErrorBadParameter;
|
||||
memset(¶m->nSliceHeaderSpacing, 0,
|
||||
param->nSize - offsetof(OMX_VIDEO_PARAM_AVCTYPE, nSliceHeaderSpacing));
|
||||
|
||||
mmalomx_get_video_param(port, &profile, &level, &intraperiod);
|
||||
param->eProfile = (OMX_VIDEO_AVCPROFILETYPE)profile;
|
||||
param->eLevel = (OMX_VIDEO_AVCLEVELTYPE)level;
|
||||
param->nPFrames = intraperiod - 1;
|
||||
param->bUseHadamard = OMX_TRUE;
|
||||
param->nRefFrames = 1;
|
||||
param->nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
|
||||
param->bFrameMBsOnly = OMX_TRUE;
|
||||
if (param->eProfile != OMX_VIDEO_AVCProfileBaseline)
|
||||
param->bEntropyCodingCABAC = OMX_TRUE;
|
||||
param->eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
|
||||
}
|
||||
return OMX_ErrorNone;
|
||||
case OMX_IndexParamVideoMpeg4:
|
||||
{
|
||||
OMX_VIDEO_PARAM_MPEG4TYPE *param = (OMX_VIDEO_PARAM_MPEG4TYPE *)pParam;
|
||||
uint32_t profile, level, intraperiod;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
if (param->nSize < sizeof(*param))
|
||||
return OMX_ErrorBadParameter;
|
||||
memset(¶m->nSliceHeaderSpacing, 0,
|
||||
param->nSize - offsetof(OMX_VIDEO_PARAM_MPEG4TYPE, nSliceHeaderSpacing));
|
||||
|
||||
mmalomx_get_video_param(port, &profile, &level, &intraperiod);
|
||||
param->eProfile = (OMX_VIDEO_MPEG4PROFILETYPE)profile;
|
||||
param->eLevel = (OMX_VIDEO_MPEG4LEVELTYPE)level;
|
||||
param->nPFrames = intraperiod - 1;
|
||||
param->bACPred = OMX_TRUE;
|
||||
param->nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
|
||||
}
|
||||
return OMX_ErrorNone;
|
||||
case OMX_IndexParamVideoH263:
|
||||
{
|
||||
OMX_VIDEO_PARAM_H263TYPE *param = (OMX_VIDEO_PARAM_H263TYPE *)pParam;
|
||||
uint32_t profile, level, intraperiod;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
if (param->nSize < sizeof(*param))
|
||||
return OMX_ErrorBadParameter;
|
||||
memset(¶m->nPFrames, 0,
|
||||
param->nSize - offsetof(OMX_VIDEO_PARAM_H263TYPE, nPFrames));
|
||||
|
||||
mmalomx_get_video_param(port, &profile, &level, &intraperiod);
|
||||
param->eProfile = (OMX_VIDEO_H263PROFILETYPE)profile;
|
||||
param->eLevel = (OMX_VIDEO_H263LEVELTYPE)level;
|
||||
param->nPFrames = intraperiod - 1;
|
||||
param->nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
|
||||
}
|
||||
return OMX_ErrorNone;
|
||||
case OMX_IndexParamVideoMpeg2:
|
||||
case OMX_IndexParamVideoWmv:
|
||||
case OMX_IndexParamVideoRv:
|
||||
{
|
||||
OMX_FORMAT_PARAM_TYPE *param = (OMX_FORMAT_PARAM_TYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->common.nPortIndex);
|
||||
OMX_U32 offset = offsetof(OMX_PARAM_U32TYPE, nU32);
|
||||
if (param->common.nSize > sizeof(port->format_param) ||
|
||||
param->common.nSize < offset)
|
||||
return OMX_ErrorBadParameter;
|
||||
memcpy(¶m->common.nU32, &port->format_param.common.nU32,
|
||||
param->common.nSize - offset);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
case OMX_IndexParamAudioPcm:
|
||||
case OMX_IndexParamAudioAac:
|
||||
case OMX_IndexParamAudioMp3:
|
||||
case OMX_IndexParamAudioDdp:
|
||||
{
|
||||
OMX_FORMAT_PARAM_TYPE *param = (OMX_FORMAT_PARAM_TYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->common.nPortIndex);
|
||||
OMX_U32 offset = offsetof(OMX_PARAM_U32TYPE, nU32);
|
||||
if (param->common.nSize > sizeof(port->format_param) ||
|
||||
param->common.nSize < offset)
|
||||
return OMX_ErrorBadParameter;
|
||||
memcpy(¶m->common.nU32, &port->format_param.common.nU32,
|
||||
param->common.nSize - offset);
|
||||
mmalil_format_to_omx_audio_param(param, NULL, port->mmal->format);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
case OMX_IndexParamBrcmPixelAspectRatio:
|
||||
{
|
||||
OMX_CONFIG_POINTTYPE *param = (OMX_CONFIG_POINTTYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
param->nX = port->mmal->format->es->video.par.num;
|
||||
param->nY = port->mmal->format->es->video.par.den;
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
case OMX_IndexParamColorSpace:
|
||||
{
|
||||
OMX_PARAM_COLORSPACETYPE *param = (OMX_PARAM_COLORSPACETYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
param->eColorSpace = mmalil_color_space_to_omx(port->mmal->format->es->video.color_space);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
case OMX_IndexConfigCommonOutputCrop:
|
||||
{
|
||||
OMX_CONFIG_RECTTYPE *param = (OMX_CONFIG_RECTTYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
param->nLeft = port->mmal->format->es->video.crop.x;
|
||||
param->nTop = port->mmal->format->es->video.crop.y;
|
||||
param->nWidth = port->mmal->format->es->video.width;
|
||||
if (port->mmal->format->es->video.crop.width)
|
||||
param->nWidth = port->mmal->format->es->video.crop.width;
|
||||
param->nHeight = port->mmal->format->es->video.height;
|
||||
if (port->mmal->format->es->video.crop.height)
|
||||
param->nHeight = port->mmal->format->es->video.crop.height;
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
case OMX_IndexConfigCommonScale:
|
||||
{
|
||||
OMX_CONFIG_SCALEFACTORTYPE *param = (OMX_CONFIG_SCALEFACTORTYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
param->xWidth = param->xHeight = 1<<16;
|
||||
if (port->mmal->format->es->video.par.num &&
|
||||
port->mmal->format->es->video.par.den)
|
||||
param->xWidth = mmal_rational_to_fixed_16_16(port->mmal->format->es->video.par);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
default:
|
||||
return mmalomx_parameter_get_xlat(component, nParamIndex, pParam);
|
||||
}
|
||||
|
||||
return OMX_ErrorNotImplemented;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static OMX_ERRORTYPE mmalomx_set_video_param(MMALOMX_PORT_T *port,
|
||||
uint32_t profile, uint32_t level, uint32_t intraperiod)
|
||||
{
|
||||
MMAL_PARAMETER_VIDEO_PROFILE_T mmal_param = {{MMAL_PARAMETER_PROFILE, sizeof(mmal_param)},
|
||||
{{(MMAL_VIDEO_PROFILE_T)0, (MMAL_VIDEO_LEVEL_T)0}}};
|
||||
OMX_VIDEO_CODINGTYPE coding =
|
||||
mmalil_encoding_to_omx_video_coding(port->mmal->format->encoding);
|
||||
|
||||
if (mmal_port_parameter_set_uint32(port->mmal, MMAL_PARAMETER_INTRAPERIOD,
|
||||
intraperiod) != MMAL_SUCCESS)
|
||||
return OMX_ErrorBadParameter;
|
||||
|
||||
mmal_param.profile[0].profile = (MMAL_VIDEO_PROFILE_T)
|
||||
mmalil_omx_video_profile_to_mmal(profile, coding);
|
||||
mmal_param.profile[0].level = (MMAL_VIDEO_LEVEL_T)
|
||||
mmalil_omx_video_level_to_mmal(level, coding);
|
||||
if (mmal_port_parameter_set(port->mmal, &mmal_param.hdr) != MMAL_SUCCESS)
|
||||
return OMX_ErrorBadParameter;
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
OMX_ERRORTYPE mmalomx_parameter_set(MMALOMX_COMPONENT_T *component,
|
||||
OMX_INDEXTYPE nParamIndex, OMX_PTR pParam)
|
||||
{
|
||||
MMALOMX_PORT_T *port = NULL;
|
||||
|
||||
switch(nParamIndex)
|
||||
{
|
||||
/* All OMX_IndexParamVideo parameters are only partially implemented */
|
||||
case OMX_IndexParamVideoAvc:
|
||||
{
|
||||
OMX_VIDEO_PARAM_AVCTYPE *param = (OMX_VIDEO_PARAM_AVCTYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
if (param->nSize < sizeof(*param))
|
||||
return OMX_ErrorBadParameter;
|
||||
return mmalomx_set_video_param(port, param->eProfile, param->eLevel,
|
||||
param->nPFrames + 1);
|
||||
}
|
||||
case OMX_IndexParamVideoMpeg4:
|
||||
{
|
||||
OMX_VIDEO_PARAM_MPEG4TYPE *param = (OMX_VIDEO_PARAM_MPEG4TYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
if (param->nSize < sizeof(*param))
|
||||
return OMX_ErrorBadParameter;
|
||||
return mmalomx_set_video_param(port, param->eProfile, param->eLevel,
|
||||
param->nPFrames + 1);
|
||||
}
|
||||
case OMX_IndexParamVideoH263:
|
||||
{
|
||||
OMX_VIDEO_PARAM_H263TYPE *param = (OMX_VIDEO_PARAM_H263TYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
if (param->nSize < sizeof(*param))
|
||||
return OMX_ErrorBadParameter;
|
||||
return mmalomx_set_video_param(port, param->eProfile, param->eLevel,
|
||||
param->nPFrames + 1);
|
||||
}
|
||||
case OMX_IndexParamVideoMpeg2:
|
||||
case OMX_IndexParamVideoWmv:
|
||||
case OMX_IndexParamVideoRv:
|
||||
{
|
||||
OMX_FORMAT_PARAM_TYPE *param = (OMX_FORMAT_PARAM_TYPE *)pParam;
|
||||
OMX_U32 offset = offsetof(OMX_PARAM_U32TYPE, nU32);
|
||||
PARAM_GET_PORT(port, component, param->common.nPortIndex);
|
||||
if (param->common.nSize > sizeof(port->format_param) ||
|
||||
param->common.nSize < offset)
|
||||
return OMX_ErrorBadParameter;
|
||||
memcpy(&port->format_param.common.nU32, ¶m->common.nU32,
|
||||
param->common.nSize - offset);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
case OMX_IndexParamAudioPcm:
|
||||
case OMX_IndexParamAudioAac:
|
||||
case OMX_IndexParamAudioMp3:
|
||||
case OMX_IndexParamAudioDdp:
|
||||
{
|
||||
OMX_FORMAT_PARAM_TYPE *param = (OMX_FORMAT_PARAM_TYPE *)pParam;
|
||||
OMX_U32 offset = offsetof(OMX_PARAM_U32TYPE, nU32);
|
||||
PARAM_GET_PORT(port, component, param->common.nPortIndex);
|
||||
if (param->common.nSize > sizeof(port->format_param) ||
|
||||
param->common.nSize < offset)
|
||||
return OMX_ErrorBadParameter;
|
||||
memcpy(&port->format_param.common.nU32, ¶m->common.nU32,
|
||||
param->common.nSize - offset);
|
||||
mmalil_omx_audio_param_to_format(port->mmal->format,
|
||||
mmalil_omx_audio_param_index_to_coding(nParamIndex), param);
|
||||
mmal_port_format_commit(port->mmal);
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
case OMX_IndexParamBrcmPixelAspectRatio:
|
||||
{
|
||||
OMX_CONFIG_POINTTYPE *param = (OMX_CONFIG_POINTTYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
port->mmal->format->es->video.par.num = param->nX;
|
||||
port->mmal->format->es->video.par.den = param->nY;
|
||||
mmal_rational_simplify(&port->mmal->format->es->video.par);
|
||||
return mmal_port_format_commit(port->mmal);
|
||||
}
|
||||
case OMX_IndexParamColorSpace:
|
||||
{
|
||||
OMX_PARAM_COLORSPACETYPE *param = (OMX_PARAM_COLORSPACETYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
port->mmal->format->es->video.color_space = mmalil_omx_color_space_to_mmal(param->eColorSpace);
|
||||
return mmal_port_format_commit(port->mmal);
|
||||
}
|
||||
case OMX_IndexParamBrcmVideoCroppingDisable:
|
||||
{
|
||||
OMX_CONFIG_PORTBOOLEANTYPE *param = (OMX_CONFIG_PORTBOOLEANTYPE *)pParam;
|
||||
PARAM_GET_PORT(port, component, param->nPortIndex);
|
||||
port->no_cropping = param->bEnabled;
|
||||
return OMX_ErrorNone;
|
||||
}
|
||||
default:
|
||||
return mmalomx_parameter_set_xlat(component, nParamIndex, pParam);
|
||||
}
|
||||
|
||||
return OMX_ErrorNotImplemented;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Parameters related functions
|
||||
*/
|
||||
|
||||
OMX_ERRORTYPE mmalomx_parameter_get(MMALOMX_COMPONENT_T *component,
|
||||
OMX_INDEXTYPE nParamIndex, OMX_PTR pParam);
|
||||
OMX_ERRORTYPE mmalomx_parameter_set(MMALOMX_COMPONENT_T *component,
|
||||
OMX_INDEXTYPE nParamIndex, OMX_PTR pParam);
|
||||
OMX_ERRORTYPE mmalomx_parameter_extension_index_get(OMX_STRING cParameterName,
|
||||
OMX_INDEXTYPE *pIndex);
|
@ -1,159 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_roles.h"
|
||||
#include "mmalomx_registry.h"
|
||||
#include "mmalomx_logging.h"
|
||||
#include <util/mmal_default_components.h>
|
||||
|
||||
#ifndef ENABLE_MMALOMX_AUDIO_HW_DECODER
|
||||
# define ENABLE_MMALOMX_AUDIO_HW_DECODER 0
|
||||
#endif
|
||||
#ifndef ENABLE_MMALOMX_AUDIO_SPDIF
|
||||
# define ENABLE_MMALOMX_AUDIO_SPDIF 1
|
||||
#endif
|
||||
|
||||
static const struct {
|
||||
const char *omx;
|
||||
const char *omx_prefix;
|
||||
const char *mmal;
|
||||
MMALOMX_ROLE_T roles[MMALOMX_ROLE_MAX];
|
||||
} mmalomx_components[] =
|
||||
{
|
||||
{"video.hw.decoder", 0, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER,
|
||||
{MMALOMX_ROLE_VIDEO_DECODER_H263, MMALOMX_ROLE_VIDEO_DECODER_MPEG2,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_MPEG4, MMALOMX_ROLE_VIDEO_DECODER_AVC,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_WMV, MMALOMX_ROLE_VIDEO_DECODER_VPX,
|
||||
MMALOMX_ROLE_UNDEFINED}},
|
||||
{"video.hw.decoder.secure", 0, "drm_alloc.video_decode",
|
||||
{MMALOMX_ROLE_VIDEO_DECODER_H263, MMALOMX_ROLE_VIDEO_DECODER_MPEG2,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_MPEG4, MMALOMX_ROLE_VIDEO_DECODER_AVC,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_WMV, MMALOMX_ROLE_VIDEO_DECODER_VPX,
|
||||
MMALOMX_ROLE_UNDEFINED}},
|
||||
{"video.hw.decoder.divx_drm", 0, "aggregator.pipeline:divx_drm:vc.video_decode",
|
||||
{MMALOMX_ROLE_VIDEO_DECODER_MPEG4, MMALOMX_ROLE_UNDEFINED}},
|
||||
{"video.vpx.decoder", 0, "libvpx",
|
||||
{MMALOMX_ROLE_VIDEO_DECODER_VPX, MMALOMX_ROLE_UNDEFINED}},
|
||||
|
||||
{"video.hw.encoder", 0, MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER,
|
||||
{MMALOMX_ROLE_VIDEO_ENCODER_H263, MMALOMX_ROLE_VIDEO_ENCODER_MPEG4,
|
||||
MMALOMX_ROLE_VIDEO_ENCODER_AVC, MMALOMX_ROLE_UNDEFINED}},
|
||||
|
||||
{"AIV.play", "", "aivplay",
|
||||
{MMALOMX_ROLE_AIV_PLAY_101, MMALOMX_ROLE_AIV_PLAY_AVCDDP, MMALOMX_ROLE_UNDEFINED}},
|
||||
{"AIV.play.avcddp", "", "aivplay.ddp",
|
||||
{MMALOMX_ROLE_AIV_PLAY_AVCDDP, MMALOMX_ROLE_AIV_PLAY_101, MMALOMX_ROLE_UNDEFINED}},
|
||||
|
||||
#if ENABLE_MMALOMX_AUDIO_HW_DECODER
|
||||
{"audio.hw.decoder", 0, "vc.ril.audio_decode",
|
||||
{MMALOMX_ROLE_AUDIO_DECODER_AAC, MMALOMX_ROLE_AUDIO_DECODER_MPGA_L1,
|
||||
MMALOMX_ROLE_AUDIO_DECODER_MPGA_L2, MMALOMX_ROLE_AUDIO_DECODER_MPGA_L3,
|
||||
MMALOMX_ROLE_AUDIO_DECODER_DDP, MMALOMX_ROLE_UNDEFINED}},
|
||||
#endif
|
||||
|
||||
#if ENABLE_MMALOMX_AUDIO_SPDIF
|
||||
{"audio.spdif", 0, "spdif",
|
||||
{MMALOMX_ROLE_AUDIO_DECODER_DDP, MMALOMX_ROLE_UNDEFINED}},
|
||||
#endif
|
||||
|
||||
{0, 0, 0, {MMALOMX_ROLE_UNDEFINED}}
|
||||
};
|
||||
|
||||
int mmalomx_registry_find_component(const char *name)
|
||||
{
|
||||
int i, prefix_size;
|
||||
const char *prefix;
|
||||
|
||||
for (i = 0; mmalomx_components[i].omx; i++)
|
||||
{
|
||||
/* Check the prefix first */
|
||||
prefix = mmalomx_components[i].omx_prefix;
|
||||
if (!prefix)
|
||||
prefix = MMALOMX_COMPONENT_PREFIX;
|
||||
prefix_size = strlen(prefix);
|
||||
if (strncmp(name, prefix, prefix_size))
|
||||
continue;
|
||||
|
||||
/* Check the rest of the name */
|
||||
if (!strcmp(name + prefix_size, mmalomx_components[i].omx))
|
||||
break;
|
||||
}
|
||||
|
||||
return mmalomx_components[i].mmal ? i : -1;
|
||||
}
|
||||
|
||||
const char *mmalomx_registry_component_mmal(int id)
|
||||
{
|
||||
if (id >= (int)MMAL_COUNTOF(mmalomx_components) || id < 0)
|
||||
id = MMAL_COUNTOF(mmalomx_components) - 1;
|
||||
|
||||
return mmalomx_components[id].mmal;
|
||||
}
|
||||
|
||||
MMALOMX_ROLE_T mmalomx_registry_component_roles(int id, unsigned int index)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (id >= (int)MMAL_COUNTOF(mmalomx_components) || id < 0)
|
||||
id = MMAL_COUNTOF(mmalomx_components) - 1;
|
||||
|
||||
for (i = 0; i < index; i++)
|
||||
if (mmalomx_components[id].roles[i] == MMALOMX_ROLE_UNDEFINED)
|
||||
break;
|
||||
|
||||
return mmalomx_components[id].roles[i];
|
||||
}
|
||||
|
||||
MMAL_BOOL_T mmalomx_registry_component_supports_role(int id, MMALOMX_ROLE_T role)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (id >= (int)MMAL_COUNTOF(mmalomx_components) || id < 0)
|
||||
id = MMAL_COUNTOF(mmalomx_components) - 1;
|
||||
|
||||
for (i = 0; mmalomx_components[id].roles[i] != MMALOMX_ROLE_UNDEFINED; i++)
|
||||
if (mmalomx_components[id].roles[i] == role)
|
||||
return MMAL_TRUE;
|
||||
|
||||
return MMAL_FALSE;
|
||||
}
|
||||
|
||||
const char *mmalomx_registry_component_name(int id, const char **prefix)
|
||||
{
|
||||
if (id >= (int)MMAL_COUNTOF(mmalomx_components) || id < 0)
|
||||
id = MMAL_COUNTOF(mmalomx_components) - 1;
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
*prefix = mmalomx_components[id].omx_prefix;
|
||||
if (!*prefix)
|
||||
*prefix = MMALOMX_COMPONENT_PREFIX;
|
||||
}
|
||||
|
||||
return mmalomx_components[id].omx;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Registry of components
|
||||
*/
|
||||
|
||||
#define MMALOMX_COMPONENT_PREFIX "OMX.brcm."
|
||||
|
||||
int mmalomx_registry_find_component(const char *name);
|
||||
|
||||
const char *mmalomx_registry_component_mmal(int id);
|
||||
|
||||
MMALOMX_ROLE_T mmalomx_registry_component_roles(int id, unsigned int index);
|
||||
MMAL_BOOL_T mmalomx_registry_component_supports_role(int id, MMALOMX_ROLE_T role);
|
||||
|
||||
const char *mmalomx_registry_component_name(int index, const char **prefix);
|
@ -1,210 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_roles.h"
|
||||
#include "mmalomx_registry.h"
|
||||
#include "mmalomx_logging.h"
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
MMALOMX_ROLE_T role;
|
||||
} mmalomx_roles[] =
|
||||
{
|
||||
{"video_decoder.h263", MMALOMX_ROLE_VIDEO_DECODER_H263},
|
||||
{"video_decoder.mpeg4", MMALOMX_ROLE_VIDEO_DECODER_MPEG4},
|
||||
{"video_decoder.avc", MMALOMX_ROLE_VIDEO_DECODER_AVC},
|
||||
{"video_decoder.mpeg2", MMALOMX_ROLE_VIDEO_DECODER_MPEG2},
|
||||
{"video_decoder.wmv", MMALOMX_ROLE_VIDEO_DECODER_WMV},
|
||||
{"video_decoder.vpx", MMALOMX_ROLE_VIDEO_DECODER_VPX},
|
||||
|
||||
{"video_encoder.h263", MMALOMX_ROLE_VIDEO_ENCODER_H263},
|
||||
{"video_encoder.mpeg4", MMALOMX_ROLE_VIDEO_ENCODER_MPEG4},
|
||||
{"video_encoder.avc", MMALOMX_ROLE_VIDEO_ENCODER_AVC},
|
||||
|
||||
{"audio_decoder.aac", MMALOMX_ROLE_AUDIO_DECODER_AAC},
|
||||
{"audio_decoder.mp1", MMALOMX_ROLE_AUDIO_DECODER_MPGA_L1},
|
||||
{"audio_decoder.mp2", MMALOMX_ROLE_AUDIO_DECODER_MPGA_L2},
|
||||
{"audio_decoder.mp3", MMALOMX_ROLE_AUDIO_DECODER_MPGA_L3},
|
||||
{"audio_decoder.ddp", MMALOMX_ROLE_AUDIO_DECODER_DDP},
|
||||
|
||||
{"AIV.play.101", MMALOMX_ROLE_AIV_PLAY_101},
|
||||
{"play.avcddp", MMALOMX_ROLE_AIV_PLAY_AVCDDP},
|
||||
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
const char *mmalomx_role_to_name(MMALOMX_ROLE_T role)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; mmalomx_roles[i].name; i++)
|
||||
if (mmalomx_roles[i].role == role)
|
||||
break;
|
||||
return mmalomx_roles[i].name;
|
||||
}
|
||||
|
||||
MMALOMX_ROLE_T mmalomx_role_from_name(const char *name)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; mmalomx_roles[i].name; i++)
|
||||
if (!strcmp(mmalomx_roles[i].name, name))
|
||||
break;
|
||||
return mmalomx_roles[i].role;
|
||||
}
|
||||
|
||||
static void mmalomx_format_encoding_from_role(MMALOMX_ROLE_T role,
|
||||
MMAL_FOURCC_T *encoding, MMAL_ES_TYPE_T *es_type, unsigned int *port)
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_MPEG4:
|
||||
case MMALOMX_ROLE_VIDEO_ENCODER_MPEG4:
|
||||
*encoding = MMAL_ENCODING_MP4V;
|
||||
*es_type = MMAL_ES_TYPE_VIDEO;
|
||||
break;
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_AVC:
|
||||
case MMALOMX_ROLE_VIDEO_ENCODER_AVC:
|
||||
*encoding = MMAL_ENCODING_H264;
|
||||
*es_type = MMAL_ES_TYPE_VIDEO;
|
||||
break;
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_MPEG2:
|
||||
*encoding = MMAL_ENCODING_MP2V;
|
||||
*es_type = MMAL_ES_TYPE_VIDEO;
|
||||
break;
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_WMV:
|
||||
*encoding = MMAL_ENCODING_WMV3;
|
||||
*es_type = MMAL_ES_TYPE_VIDEO;
|
||||
break;
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_VPX:
|
||||
*encoding = MMAL_ENCODING_VP8;
|
||||
*es_type = MMAL_ES_TYPE_VIDEO;
|
||||
break;
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_H263:
|
||||
case MMALOMX_ROLE_VIDEO_ENCODER_H263:
|
||||
*encoding = MMAL_ENCODING_H263;
|
||||
*es_type = MMAL_ES_TYPE_VIDEO;
|
||||
break;
|
||||
case MMALOMX_ROLE_AUDIO_DECODER_AAC:
|
||||
*encoding = MMAL_ENCODING_MP4A;
|
||||
*es_type = MMAL_ES_TYPE_AUDIO;
|
||||
break;
|
||||
case MMALOMX_ROLE_AUDIO_DECODER_MPGA_L1:
|
||||
case MMALOMX_ROLE_AUDIO_DECODER_MPGA_L2:
|
||||
case MMALOMX_ROLE_AUDIO_DECODER_MPGA_L3:
|
||||
*encoding = MMAL_ENCODING_MPGA;
|
||||
*es_type = MMAL_ES_TYPE_AUDIO;
|
||||
break;
|
||||
|
||||
case MMALOMX_ROLE_AUDIO_DECODER_DDP:
|
||||
*encoding = MMAL_ENCODING_AC3;
|
||||
*es_type = MMAL_ES_TYPE_AUDIO;
|
||||
break;
|
||||
|
||||
default:
|
||||
*encoding = MMAL_ENCODING_UNKNOWN;
|
||||
*es_type = MMAL_ES_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case MMALOMX_ROLE_VIDEO_ENCODER_H263:
|
||||
case MMALOMX_ROLE_VIDEO_ENCODER_MPEG4:
|
||||
case MMALOMX_ROLE_VIDEO_ENCODER_AVC:
|
||||
*port = 1;
|
||||
break;
|
||||
default:
|
||||
*port = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OMX_ERRORTYPE mmalomx_role_set(MMALOMX_COMPONENT_T *component, const char *name)
|
||||
{
|
||||
const MMALOMX_ROLE_T role = mmalomx_role_from_name(name);
|
||||
MMAL_FOURCC_T encoding = MMAL_ENCODING_UNKNOWN;
|
||||
MMAL_ES_TYPE_T es_type = MMAL_ES_TYPE_UNKNOWN;
|
||||
unsigned int port;
|
||||
MMAL_ES_FORMAT_T *format;
|
||||
|
||||
if (!role || !mmalomx_registry_component_supports_role(component->registry_id, role))
|
||||
return OMX_ErrorUnsupportedSetting;
|
||||
|
||||
component->role = role;
|
||||
|
||||
mmalomx_format_encoding_from_role(role, &encoding, &es_type, &port);
|
||||
if (encoding == MMAL_ENCODING_UNKNOWN)
|
||||
return OMX_ErrorNone;
|
||||
|
||||
format = component->ports[port].mmal->format;
|
||||
format->type = es_type;
|
||||
format->encoding = encoding;
|
||||
format->bitrate = 64000;
|
||||
switch (es_type)
|
||||
{
|
||||
case MMAL_ES_TYPE_VIDEO:
|
||||
format->es->video.width = 176;
|
||||
format->es->video.height = 144;
|
||||
format->es->video.frame_rate.num = 15;
|
||||
format->es->video.frame_rate.den = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_H263:
|
||||
case MMALOMX_ROLE_VIDEO_ENCODER_H263:
|
||||
component->ports[port].format_param.h263.eProfile = OMX_VIDEO_H263ProfileBaseline;
|
||||
component->ports[port].format_param.h263.eLevel = OMX_VIDEO_H263Level10;
|
||||
component->ports[port].format_param.h263.bPLUSPTYPEAllowed = OMX_FALSE;
|
||||
component->ports[port].format_param.h263.bForceRoundingTypeToZero = OMX_TRUE;
|
||||
break;
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_MPEG4:
|
||||
case MMALOMX_ROLE_VIDEO_ENCODER_MPEG4:
|
||||
component->ports[port].format_param.mpeg4.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
|
||||
component->ports[port].format_param.mpeg4.eLevel = OMX_VIDEO_MPEG4Level1;
|
||||
break;
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_AVC:
|
||||
case MMALOMX_ROLE_VIDEO_ENCODER_AVC:
|
||||
component->ports[port].format_param.avc.eProfile = OMX_VIDEO_AVCProfileBaseline;
|
||||
component->ports[port].format_param.avc.eLevel = OMX_VIDEO_AVCLevel1;
|
||||
break;
|
||||
case MMALOMX_ROLE_VIDEO_DECODER_WMV:
|
||||
component->ports[port].format_param.wmv.eFormat = OMX_VIDEO_WMVFormat9;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (mmal_port_format_commit(component->ports[port].mmal) != MMAL_SUCCESS)
|
||||
LOG_ERROR("failed to commit format to %s for role %s",
|
||||
component->ports[port].mmal->name, name);
|
||||
|
||||
return OMX_ErrorNone;
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Role specific functions
|
||||
*/
|
||||
|
||||
#define MMALOMX_MAX_ROLES 16
|
||||
|
||||
typedef enum MMALOMX_ROLE_T {
|
||||
MMALOMX_ROLE_UNDEFINED = 0,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_H263,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_MPEG4,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_AVC,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_MPEG2,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_WMV,
|
||||
MMALOMX_ROLE_VIDEO_DECODER_VPX,
|
||||
|
||||
MMALOMX_ROLE_VIDEO_ENCODER_H263,
|
||||
MMALOMX_ROLE_VIDEO_ENCODER_MPEG4,
|
||||
MMALOMX_ROLE_VIDEO_ENCODER_AVC,
|
||||
|
||||
MMALOMX_ROLE_AUDIO_DECODER_AAC,
|
||||
MMALOMX_ROLE_AUDIO_DECODER_MPGA_L1,
|
||||
MMALOMX_ROLE_AUDIO_DECODER_MPGA_L2,
|
||||
MMALOMX_ROLE_AUDIO_DECODER_MPGA_L3,
|
||||
MMALOMX_ROLE_AUDIO_DECODER_DDP,
|
||||
|
||||
MMALOMX_ROLE_AIV_PLAY_101,
|
||||
MMALOMX_ROLE_AIV_PLAY_AVCDDP,
|
||||
|
||||
MMALOMX_ROLE_MAX
|
||||
} MMALOMX_ROLE_T;
|
||||
|
||||
const char *mmalomx_role_to_name(MMALOMX_ROLE_T role);
|
||||
MMALOMX_ROLE_T mmalomx_role_from_name(const char *name);
|
||||
OMX_ERRORTYPE mmalomx_role_set(struct MMALOMX_COMPONENT_T *component, const char *name);
|
@ -1,193 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Broadcom.h"
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_util_params.h"
|
||||
#include "mmalomx_util_params_common.h"
|
||||
|
||||
static const MMALOMX_PARAM_TRANSLATION_T *mmalomx_param_list[] = {
|
||||
mmalomx_param_xlator_audio, mmalomx_param_xlator_video,
|
||||
mmalomx_param_xlator_camera, mmalomx_param_xlator_misc};
|
||||
|
||||
const MMALOMX_PARAM_TRANSLATION_T *mmalomx_find_parameter_enum(unsigned int index)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < MMAL_COUNTOF(mmalomx_param_list); i++)
|
||||
{
|
||||
for (j = 0; mmalomx_param_list[i][j].mmal_id != MMAL_PARAMETER_UNUSED; j++)
|
||||
{
|
||||
if (!index--)
|
||||
break;
|
||||
}
|
||||
if (mmalomx_param_list[i][j].mmal_id != MMAL_PARAMETER_UNUSED)
|
||||
break;
|
||||
}
|
||||
|
||||
return i < MMAL_COUNTOF(mmalomx_param_list) ? &mmalomx_param_list[i][j] : NULL;
|
||||
}
|
||||
|
||||
const MMALOMX_PARAM_TRANSLATION_T *mmalomx_find_parameter_from_omx_id(uint32_t id)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < MMAL_COUNTOF(mmalomx_param_list); i++)
|
||||
{
|
||||
for (j = 0; mmalomx_param_list[i][j].mmal_id != MMAL_PARAMETER_UNUSED; j++)
|
||||
{
|
||||
if (mmalomx_param_list[i][j].omx_id == id)
|
||||
break;
|
||||
}
|
||||
if (mmalomx_param_list[i][j].mmal_id != MMAL_PARAMETER_UNUSED)
|
||||
break;
|
||||
}
|
||||
|
||||
return i < MMAL_COUNTOF(mmalomx_param_list) ? &mmalomx_param_list[i][j] : NULL;
|
||||
}
|
||||
|
||||
const MMALOMX_PARAM_TRANSLATION_T *mmalomx_find_parameter_from_mmal_id(uint32_t id)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < MMAL_COUNTOF(mmalomx_param_list); i++)
|
||||
{
|
||||
for (j = 0; mmalomx_param_list[i][j].mmal_id != MMAL_PARAMETER_UNUSED; j++)
|
||||
{
|
||||
if (mmalomx_param_list[i][j].mmal_id == id)
|
||||
break;
|
||||
}
|
||||
if (mmalomx_param_list[i][j].mmal_id != MMAL_PARAMETER_UNUSED)
|
||||
break;
|
||||
}
|
||||
|
||||
return i < MMAL_COUNTOF(mmalomx_param_list) ? &mmalomx_param_list[i][j] : NULL;
|
||||
}
|
||||
|
||||
const char *mmalomx_parameter_name_omx(uint32_t id)
|
||||
{
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat = mmalomx_find_parameter_from_omx_id(id);
|
||||
return xlat ? xlat->omx_name : 0;
|
||||
}
|
||||
|
||||
const char *mmalomx_parameter_name_mmal(uint32_t id)
|
||||
{
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat = mmalomx_find_parameter_from_mmal_id(id);
|
||||
return xlat ? xlat->mmal_name : 0;
|
||||
}
|
||||
|
||||
MMAL_STATUS_T mmalomx_param_mapping_generic(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param, MMAL_PORT_T *mmal_port)
|
||||
{
|
||||
MMALOMX_PARAM_OMX_HEADER_T *omx_header = (MMALOMX_PARAM_OMX_HEADER_T *)omx_param;
|
||||
uint8_t *mmal_data = ((uint8_t *)mmal_param) + sizeof(MMAL_PARAMETER_HEADER_T);
|
||||
uint8_t *omx_data = ((uint8_t *)omx_param) + sizeof(MMALOMX_PARAM_OMX_HEADER_T);
|
||||
unsigned int size = mmal_param->size - sizeof(MMAL_PARAMETER_HEADER_T);
|
||||
MMAL_PARAM_UNUSED(mmal_port);
|
||||
|
||||
if (xlat->portless)
|
||||
omx_data -= sizeof(OMX_U32);
|
||||
|
||||
if (((uint8_t *)omx_param) + omx_header->nSize !=
|
||||
omx_data + size)
|
||||
{
|
||||
VCOS_ALERT("mmalomx_param_mapping_generic: mismatch between mmal and omx paramters for (%u)",
|
||||
(unsigned int)mmal_param->id);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
memcpy(mmal_data, omx_data, size);
|
||||
else
|
||||
memcpy(omx_data, mmal_data, size);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
MMAL_STATUS_T mmalomx_param_enum_generic(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param, MMAL_PORT_T *mmal_port)
|
||||
{
|
||||
uint32_t *mmal = (uint32_t *)(((uint8_t *)mmal_param) + sizeof(MMAL_PARAMETER_HEADER_T));
|
||||
uint32_t *omx = (uint32_t *)(((uint8_t *)omx_param) + sizeof(MMALOMX_PARAM_OMX_HEADER_T));
|
||||
unsigned int i = 0;
|
||||
MMAL_PARAM_UNUSED(mmal_port);
|
||||
|
||||
if (xlat->portless)
|
||||
omx -= 1;
|
||||
|
||||
/* Find translation entry in lookup table */
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
for (i = 0; i < xlat->xlat_enum_num && xlat->xlat_enum->omx != *omx; i++);
|
||||
else
|
||||
for (i = 0; i < xlat->xlat_enum_num && xlat->xlat_enum->mmal != *mmal; i++);
|
||||
|
||||
if (i == xlat->xlat_enum_num)
|
||||
{
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
VCOS_ALERT("mmalomx_param_enum_generic: omx enum value %u not supported", (unsigned int)*omx);
|
||||
else
|
||||
VCOS_ALERT("mmalomx_param_enum_generic: mmal enum value %u not supported", (unsigned int)*mmal);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
*mmal = xlat->xlat_enum[i].mmal;
|
||||
else
|
||||
*omx = xlat->xlat_enum[i].omx;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
MMAL_STATUS_T mmalomx_param_rational_generic(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param, MMAL_PORT_T *mmal_port)
|
||||
{
|
||||
MMAL_RATIONAL_T *mmal = (MMAL_RATIONAL_T *)(((uint8_t *)mmal_param) + sizeof(MMAL_PARAMETER_HEADER_T));
|
||||
int32_t *omx = (int32_t *)(((uint8_t *)omx_param) + sizeof(MMALOMX_PARAM_OMX_HEADER_T));
|
||||
MMAL_PARAM_UNUSED(mmal_port);
|
||||
|
||||
if (xlat->portless)
|
||||
omx -= 1;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->num = *omx;
|
||||
mmal->den = xlat->xlat_enum_num;
|
||||
mmal_rational_simplify(mmal);
|
||||
}
|
||||
else
|
||||
{
|
||||
mmal_rational_simplify(mmal);
|
||||
*omx = 0;
|
||||
if (mmal->den)
|
||||
*omx = mmal->num * xlat->xlat_enum_num / mmal->den;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Parameters related functions
|
||||
*/
|
||||
|
||||
#ifndef MMALOMX_UTIL_PARAMS_H
|
||||
#define MMALOMX_UTIL_PARAMS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** The structure that all OMX parameters containing a port start with */
|
||||
typedef struct MMALOMX_PARAM_OMX_HEADER_T
|
||||
{
|
||||
OMX_U32 nSize;
|
||||
OMX_VERSIONTYPE nVersion;
|
||||
OMX_U32 nPortIndex;
|
||||
} MMALOMX_PARAM_OMX_HEADER_T;
|
||||
|
||||
/** The structure that all OMX parameters without a port start with */
|
||||
typedef struct MMALOMX_PARAM_OMX_HEADER_PORTLESS_T
|
||||
{
|
||||
OMX_U32 nSize;
|
||||
OMX_VERSIONTYPE nVersion;
|
||||
} MMALOMX_PARAM_OMX_HEADER_PORTLESS_T;
|
||||
|
||||
typedef enum {
|
||||
MMALOMX_PARAM_MAPPING_TO_MMAL,
|
||||
MMALOMX_PARAM_MAPPING_TO_OMX
|
||||
} MMALOMX_PARAM_MAPPING_DIRECTION;
|
||||
|
||||
typedef struct MMALOMX_PARAM_ENUM_TRANSLATE_T {
|
||||
uint32_t mmal;
|
||||
uint32_t omx;
|
||||
} MMALOMX_PARAM_ENUM_TRANSLATE_T;
|
||||
|
||||
typedef enum MMALOMX_PARAM_TRANSLATION_TYPE_T {
|
||||
MMALOMX_PARAM_TRANSLATION_TYPE_NONE = 0,
|
||||
MMALOMX_PARAM_TRANSLATION_TYPE_SIMPLE,
|
||||
MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM,
|
||||
MMALOMX_PARAM_TRANSLATION_TYPE_DIRECT,
|
||||
} MMALOMX_PARAM_TRANSLATION_TYPE_T;
|
||||
|
||||
/** MMAL <-> OMX parameter translation information */
|
||||
typedef struct MMALOMX_PARAM_TRANSLATION_T
|
||||
{
|
||||
uint32_t mmal_id; /**< MMAL parameter id */
|
||||
uint32_t omx_id; /**< OpenMAX IL parameter index */
|
||||
unsigned int mmal_size:16;
|
||||
unsigned int omx_size:16;
|
||||
unsigned int portless:1;
|
||||
unsigned int double_translation:1;
|
||||
MMALOMX_PARAM_TRANSLATION_TYPE_T type:4;
|
||||
|
||||
struct {
|
||||
MMAL_STATUS_T (*simple)(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param);
|
||||
MMAL_STATUS_T (*generic)(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const struct MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param, MMAL_PORT_T *mmal_port);
|
||||
MMAL_STATUS_T (*list)(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const struct MMALOMX_PARAM_TRANSLATION_T *xlat, unsigned int index,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param, MMAL_PORT_T *mmal_port);
|
||||
MMAL_STATUS_T (*custom)(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const struct MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param, MMAL_PORT_T *mmal_port);
|
||||
} fn;
|
||||
|
||||
const struct MMALOMX_PARAM_ENUM_TRANSLATE_T *xlat_enum;
|
||||
unsigned int xlat_enum_num;
|
||||
|
||||
const char *mmal_name; /**< MMAL parameter name */
|
||||
const char *omx_name; /**< OMX parameter name */
|
||||
|
||||
} MMALOMX_PARAM_TRANSLATION_T;
|
||||
|
||||
const char *mmalomx_parameter_name_omx(uint32_t id);
|
||||
const char *mmalomx_parameter_name_mmal(uint32_t id);
|
||||
const MMALOMX_PARAM_TRANSLATION_T *mmalomx_find_parameter_from_omx_id(uint32_t id);
|
||||
const MMALOMX_PARAM_TRANSLATION_T *mmalomx_find_parameter_from_mmal_id(uint32_t id);
|
||||
const MMALOMX_PARAM_TRANSLATION_T *mmalomx_find_parameter_enum(unsigned int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MMALOMX_UTIL_PARAMS_H */
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_util_params_common.h"
|
||||
#include "mmalomx_logging.h"
|
||||
|
||||
const MMALOMX_PARAM_TRANSLATION_T mmalomx_param_xlator_audio[] = {
|
||||
MMALOMX_PARAM_TERMINATE()
|
||||
};
|
@ -1,556 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_util_params_common.h"
|
||||
#include "mmalomx_logging.h"
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_awb_mode[] = {
|
||||
{MMAL_PARAM_AWBMODE_OFF, OMX_WhiteBalControlOff},
|
||||
{MMAL_PARAM_AWBMODE_AUTO, OMX_WhiteBalControlAuto},
|
||||
{MMAL_PARAM_AWBMODE_SUNLIGHT, OMX_WhiteBalControlSunLight},
|
||||
{MMAL_PARAM_AWBMODE_CLOUDY, OMX_WhiteBalControlCloudy},
|
||||
{MMAL_PARAM_AWBMODE_SHADE, OMX_WhiteBalControlShade},
|
||||
{MMAL_PARAM_AWBMODE_TUNGSTEN, OMX_WhiteBalControlTungsten},
|
||||
{MMAL_PARAM_AWBMODE_FLUORESCENT, OMX_WhiteBalControlFluorescent},
|
||||
{MMAL_PARAM_AWBMODE_INCANDESCENT,OMX_WhiteBalControlIncandescent},
|
||||
{MMAL_PARAM_AWBMODE_FLASH, OMX_WhiteBalControlFlash},
|
||||
{MMAL_PARAM_AWBMODE_HORIZON, OMX_WhiteBalControlHorizon},
|
||||
};
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_image_effect[] = {
|
||||
{MMAL_PARAM_IMAGEFX_NONE, OMX_ImageFilterNone},
|
||||
{MMAL_PARAM_IMAGEFX_NEGATIVE, OMX_ImageFilterNegative},
|
||||
{MMAL_PARAM_IMAGEFX_SOLARIZE, OMX_ImageFilterSolarize},
|
||||
{MMAL_PARAM_IMAGEFX_SKETCH, OMX_ImageFilterSketch},
|
||||
{MMAL_PARAM_IMAGEFX_DENOISE, OMX_ImageFilterNoise},
|
||||
{MMAL_PARAM_IMAGEFX_EMBOSS, OMX_ImageFilterEmboss},
|
||||
{MMAL_PARAM_IMAGEFX_OILPAINT, OMX_ImageFilterOilPaint},
|
||||
{MMAL_PARAM_IMAGEFX_HATCH, OMX_ImageFilterHatch},
|
||||
{MMAL_PARAM_IMAGEFX_GPEN, OMX_ImageFilterGpen},
|
||||
{MMAL_PARAM_IMAGEFX_PASTEL, OMX_ImageFilterPastel},
|
||||
{MMAL_PARAM_IMAGEFX_WATERCOLOUR, OMX_ImageFilterWatercolor},
|
||||
{MMAL_PARAM_IMAGEFX_FILM, OMX_ImageFilterFilm},
|
||||
{MMAL_PARAM_IMAGEFX_BLUR, OMX_ImageFilterBlur},
|
||||
{MMAL_PARAM_IMAGEFX_SATURATION, OMX_ImageFilterSaturation},
|
||||
{MMAL_PARAM_IMAGEFX_COLOURSWAP, OMX_ImageFilterColourSwap},
|
||||
{MMAL_PARAM_IMAGEFX_WASHEDOUT, OMX_ImageFilterWashedOut},
|
||||
{MMAL_PARAM_IMAGEFX_POSTERISE, OMX_ImageFilterPosterise},
|
||||
{MMAL_PARAM_IMAGEFX_COLOURPOINT, OMX_ImageFilterColourPoint},
|
||||
{MMAL_PARAM_IMAGEFX_COLOURBALANCE, OMX_ImageFilterColourBalance},
|
||||
{MMAL_PARAM_IMAGEFX_CARTOON, OMX_ImageFilterCartoon},
|
||||
};
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_colour_effect(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_CONFIG_COLORENHANCEMENTTYPE *omx = (OMX_CONFIG_COLORENHANCEMENTTYPE *)omx_param;
|
||||
MMAL_PARAMETER_COLOURFX_T *mmal = (MMAL_PARAMETER_COLOURFX_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->enable = omx->bColorEnhancement;
|
||||
mmal->u = omx->nCustomizedU;
|
||||
mmal->v = omx->nCustomizedV;
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->bColorEnhancement = mmal->enable;
|
||||
omx->nCustomizedU = mmal->u;
|
||||
omx->nCustomizedV = mmal->v;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_flicker_avoid[] = {
|
||||
{MMAL_PARAM_FLICKERAVOID_OFF, OMX_COMMONFLICKERCANCEL_OFF},
|
||||
{MMAL_PARAM_FLICKERAVOID_AUTO, OMX_COMMONFLICKERCANCEL_AUTO},
|
||||
{MMAL_PARAM_FLICKERAVOID_50HZ, OMX_COMMONFLICKERCANCEL_50},
|
||||
{MMAL_PARAM_FLICKERAVOID_60HZ, OMX_COMMONFLICKERCANCEL_60},
|
||||
};
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_flash[] = {
|
||||
{MMAL_PARAM_FLASH_OFF, OMX_IMAGE_FlashControlOff},
|
||||
{MMAL_PARAM_FLASH_AUTO, OMX_IMAGE_FlashControlAuto},
|
||||
{MMAL_PARAM_FLASH_ON, OMX_IMAGE_FlashControlOn},
|
||||
{MMAL_PARAM_FLASH_REDEYE, OMX_IMAGE_FlashControlRedEyeReduction},
|
||||
{MMAL_PARAM_FLASH_FILLIN, OMX_IMAGE_FlashControlFillin},
|
||||
{MMAL_PARAM_FLASH_TORCH, OMX_IMAGE_FlashControlTorch},
|
||||
};
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_redeye[] = {
|
||||
{MMAL_PARAM_REDEYE_OFF, OMX_RedEyeRemovalNone},
|
||||
{MMAL_PARAM_REDEYE_ON, OMX_RedEyeRemovalOn},
|
||||
{MMAL_PARAM_REDEYE_ON, OMX_RedEyeRemovalAuto},
|
||||
{MMAL_PARAM_REDEYE_SIMPLE, OMX_RedEyeRemovalSimple}
|
||||
};
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_focus(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
static const struct MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_focus[] = {
|
||||
{MMAL_PARAM_FOCUS_AUTO, OMX_IMAGE_FocusControlAutoLock},
|
||||
{MMAL_PARAM_FOCUS_CAF, OMX_IMAGE_FocusControlAuto},
|
||||
{MMAL_PARAM_FOCUS_FIXED_INFINITY, OMX_IMAGE_FocusControlInfinityFixed},
|
||||
{MMAL_PARAM_FOCUS_FIXED_HYPERFOCAL, OMX_IMAGE_FocusControlHyperfocal},
|
||||
{MMAL_PARAM_FOCUS_FIXED_NEAR, OMX_IMAGE_FocusControlNearFixed},
|
||||
{MMAL_PARAM_FOCUS_FIXED_MACRO, OMX_IMAGE_FocusControlMacroFixed},
|
||||
{MMAL_PARAM_FOCUS_AUTO_MACRO, OMX_IMAGE_FocusControlAutoLockMacro},
|
||||
{MMAL_PARAM_FOCUS_AUTO_NEAR, OMX_IMAGE_FocusControlAutoLock},
|
||||
{MMAL_PARAM_FOCUS_CAF_NEAR, OMX_IMAGE_FocusControlAutoNear},
|
||||
{MMAL_PARAM_FOCUS_CAF_MACRO, OMX_IMAGE_FocusControlAutoMacro},
|
||||
{MMAL_PARAM_FOCUS_CAF_FAST, OMX_IMAGE_FocusControlAutoFast},
|
||||
{MMAL_PARAM_FOCUS_CAF_MACRO_FAST, OMX_IMAGE_FocusControlAutoMacroFast},
|
||||
{MMAL_PARAM_FOCUS_CAF_NEAR_FAST, OMX_IMAGE_FocusControlAutoNearFast},
|
||||
/* {MMAL_PARAM_FOCUS_EDOF, ???}, */
|
||||
};
|
||||
OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE *omx = (OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE *)omx_param;
|
||||
MMAL_PARAMETER_FOCUS_T *mmal = (MMAL_PARAMETER_FOCUS_T *)mmal_param;
|
||||
MMALOMX_PARAM_ENUM_FIND(struct MMALOMX_PARAM_ENUM_TRANSLATE_T, xlat_enum, mmalomx_param_enum_focus,
|
||||
dir, mmal->value, omx->eFocusControl);
|
||||
|
||||
if (!xlat_enum)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->value = xlat_enum->mmal;
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->eFocusControl = xlat_enum->omx;
|
||||
omx->nFocusStepIndex = -1;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_mirror[] = {
|
||||
{MMAL_PARAM_MIRROR_NONE, OMX_MirrorNone},
|
||||
{MMAL_PARAM_MIRROR_VERTICAL, OMX_MirrorVertical},
|
||||
{MMAL_PARAM_MIRROR_HORIZONTAL, OMX_MirrorHorizontal},
|
||||
{MMAL_PARAM_MIRROR_BOTH, OMX_MirrorBoth}
|
||||
};
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_exposure_mode[] = {
|
||||
{MMAL_PARAM_EXPOSUREMODE_OFF, OMX_ExposureControlOff},
|
||||
{MMAL_PARAM_EXPOSUREMODE_AUTO, OMX_ExposureControlAuto},
|
||||
{MMAL_PARAM_EXPOSUREMODE_NIGHT, OMX_ExposureControlNight},
|
||||
{MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW, OMX_ExposureControlNightWithPreview},
|
||||
{MMAL_PARAM_EXPOSUREMODE_BACKLIGHT, OMX_ExposureControlBackLight},
|
||||
{MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT, OMX_ExposureControlSpotLight},
|
||||
{MMAL_PARAM_EXPOSUREMODE_SPORTS, OMX_ExposureControlSports},
|
||||
{MMAL_PARAM_EXPOSUREMODE_SNOW, OMX_ExposureControlSnow},
|
||||
{MMAL_PARAM_EXPOSUREMODE_BEACH, OMX_ExposureControlBeach},
|
||||
{MMAL_PARAM_EXPOSUREMODE_VERYLONG, OMX_ExposureControlVeryLong},
|
||||
{MMAL_PARAM_EXPOSUREMODE_FIXEDFPS, OMX_ExposureControlFixedFps},
|
||||
{MMAL_PARAM_EXPOSUREMODE_ANTISHAKE, OMX_ExposureControlAntishake},
|
||||
{MMAL_PARAM_EXPOSUREMODE_FIREWORKS, OMX_ExposureControlFireworks},
|
||||
};
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_capture_status[] = {
|
||||
{MMAL_PARAM_CAPTURE_STATUS_NOT_CAPTURING, OMX_NotCapturing},
|
||||
{MMAL_PARAM_CAPTURE_STATUS_CAPTURE_STARTED, OMX_CaptureStarted},
|
||||
{MMAL_PARAM_CAPTURE_STATUS_CAPTURE_ENDED, OMX_CaptureComplete},
|
||||
};
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_face_track(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_face_track[] = {
|
||||
{MMAL_PARAM_FACE_DETECT_NONE, OMX_FaceDetectionControlNone},
|
||||
{MMAL_PARAM_FACE_DETECT_ON, OMX_FaceDetectionControlOn},
|
||||
};
|
||||
OMX_CONFIG_FACEDETECTIONCONTROLTYPE *omx = (OMX_CONFIG_FACEDETECTIONCONTROLTYPE *)omx_param;
|
||||
MMAL_PARAMETER_FACE_TRACK_T *mmal = (MMAL_PARAMETER_FACE_TRACK_T *)mmal_param;
|
||||
MMALOMX_PARAM_ENUM_FIND(MMALOMX_PARAM_ENUM_TRANSLATE_T, xenum, mmalomx_param_enum_face_track,
|
||||
dir, mmal->mode, omx->eMode);
|
||||
|
||||
if (!xenum)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->mode = xenum->mmal;
|
||||
mmal->maxRegions = omx->nMaxRegions;
|
||||
mmal->frames = omx->nFrames;
|
||||
mmal->quality = omx->nQuality;
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->eMode = xenum->omx;
|
||||
omx->nMaxRegions = mmal->maxRegions;
|
||||
omx->nFrames = mmal->frames;
|
||||
omx->nQuality = mmal->quality;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_thumb_cfg(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_PARAM_BRCMTHUMBNAILTYPE *omx = (OMX_PARAM_BRCMTHUMBNAILTYPE *)omx_param;
|
||||
MMAL_PARAMETER_THUMBNAIL_CONFIG_T *mmal = (MMAL_PARAMETER_THUMBNAIL_CONFIG_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->enable = !!omx->bEnable;
|
||||
mmal->width = omx->nWidth;
|
||||
mmal->height = omx->nHeight;
|
||||
mmal->quality = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->bEnable = mmal->enable ? OMX_TRUE : OMX_FALSE;
|
||||
omx->bUsePreview = OMX_FALSE;
|
||||
omx->nWidth = mmal->width;
|
||||
omx->nHeight = mmal->height;
|
||||
/* We don't have an API for setting the thumbnail quality */
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_stc[] = {
|
||||
{MMAL_PARAM_STC_MODE_OFF, OMX_TimestampModeZero},
|
||||
{MMAL_PARAM_STC_MODE_RAW, OMX_TimestampModeRawStc},
|
||||
{MMAL_PARAM_STC_MODE_COOKED, OMX_TimestampModeResetStc},
|
||||
};
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_capture_mode[] = {
|
||||
{MMAL_PARAM_CAPTUREMODE_WAIT_FOR_END, OMX_CameraCaptureModeWaitForCaptureEnd},
|
||||
{MMAL_PARAM_CAPTUREMODE_RESUME_VF_IMMEDIATELY, OMX_CameraCaptureModeResumeViewfinderImmediately},
|
||||
/*{MMAL_PARAM_CAPTUREMODE_WAIT_FOR_END_AND_HOLD, OMX_CameraCaptureModeWaitForCaptureEndAndUsePreviousInputImage}, Don't enable for now as not working */
|
||||
};
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_sensor_info(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_CONFIG_CAMERAINFOTYPE *omx = (OMX_CONFIG_CAMERAINFOTYPE *)omx_param;
|
||||
MMAL_PARAMETER_SENSOR_INFORMATION_T *mmal = (MMAL_PARAMETER_SENSOR_INFORMATION_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->f_number = mmal_rational_from_fixed_16_16(omx->xFNumber);
|
||||
mmal->focal_length = mmal_rational_from_fixed_16_16(omx->xFocalLength);
|
||||
mmal->model_id = omx->nModelId;
|
||||
mmal->manufacturer_id = omx->nManufacturerId;
|
||||
mmal->revision = omx->nRevNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->xFNumber = mmal_rational_to_fixed_16_16(mmal->f_number);
|
||||
omx->xFocalLength = mmal_rational_to_fixed_16_16(mmal->focal_length);
|
||||
omx->nModelId = mmal->model_id;
|
||||
omx->nManufacturerId = mmal->manufacturer_id;
|
||||
omx->nRevNum = mmal->revision;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_flash_select[] = {
|
||||
{MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON, OMX_CameraFlashXenon},
|
||||
{MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED, OMX_CameraFlashLED},
|
||||
{MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER, OMX_CameraFlashNone},
|
||||
};
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_fov(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_CONFIG_BRCMFOVTYPE *omx = (OMX_CONFIG_BRCMFOVTYPE *)omx_param;
|
||||
MMAL_PARAMETER_FIELD_OF_VIEW_T *mmal = (MMAL_PARAMETER_FIELD_OF_VIEW_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->fov_h = mmal_rational_from_fixed_16_16(omx->xFieldOfViewHorizontal);
|
||||
mmal->fov_v = mmal_rational_from_fixed_16_16(omx->xFieldOfViewVertical);
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->xFieldOfViewHorizontal = mmal_rational_to_fixed_16_16(mmal->fov_h);
|
||||
omx->xFieldOfViewVertical = mmal_rational_to_fixed_16_16(mmal->fov_v);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_drc[] = {
|
||||
{MMAL_PARAMETER_DRC_STRENGTH_OFF, OMX_DynRangeExpOff},
|
||||
{MMAL_PARAMETER_DRC_STRENGTH_LOW, OMX_DynRangeExpLow},
|
||||
{MMAL_PARAMETER_DRC_STRENGTH_MEDIUM, OMX_DynRangeExpMedium},
|
||||
{MMAL_PARAMETER_DRC_STRENGTH_HIGH, OMX_DynRangeExpHigh},
|
||||
};
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_algo_ctrl(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_algo_ctrl[] = {
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_FACETRACKING, OMX_CameraDisableAlgorithmFacetracking},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_REDEYE_REDUCTION, OMX_CameraDisableAlgorithmRedEyeReduction},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_VIDEO_STABILISATION, OMX_CameraDisableAlgorithmVideoStabilisation},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_WRITE_RAW, OMX_CameraDisableAlgorithmWriteRaw},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_VIDEO_DENOISE, OMX_CameraDisableAlgorithmVideoDenoise},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_STILLS_DENOISE, OMX_CameraDisableAlgorithmStillsDenoise},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_TEMPORAL_DENOISE, OMX_CameraDisableAlgorithmMax},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_ANTISHAKE, OMX_CameraDisableAlgorithmAntiShake},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_IMAGE_EFFECTS, OMX_CameraDisableAlgorithmImageEffects},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_DYNAMIC_RANGE_COMPRESSION,OMX_CameraDisableAlgorithmDynamicRangeExpansion},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_FACE_RECOGNITION, OMX_CameraDisableAlgorithmFaceRecognition},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_FACE_BEAUTIFICATION, OMX_CameraDisableAlgorithmFaceBeautification},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_SCENE_DETECTION, OMX_CameraDisableAlgorithmSceneDetection},
|
||||
{ MMAL_PARAMETER_ALGORITHM_CONTROL_ALGORITHMS_HIGH_DYNAMIC_RANGE, OMX_CameraDisableAlgorithmHighDynamicRange},
|
||||
};
|
||||
OMX_PARAM_CAMERADISABLEALGORITHMTYPE *omx = (OMX_PARAM_CAMERADISABLEALGORITHMTYPE *)omx_param;
|
||||
MMAL_PARAMETER_ALGORITHM_CONTROL_T *mmal = (MMAL_PARAMETER_ALGORITHM_CONTROL_T *)mmal_param;
|
||||
MMALOMX_PARAM_ENUM_FIND(MMALOMX_PARAM_ENUM_TRANSLATE_T, xenum, mmalomx_param_enum_algo_ctrl,
|
||||
dir, mmal->algorithm, omx->eAlgorithm);
|
||||
|
||||
if (!xenum)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->algorithm = xenum->mmal;
|
||||
mmal->enabled = !omx->bDisabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->eAlgorithm = xenum->omx;
|
||||
omx->bDisabled = !mmal->enabled;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_image_effect_params(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_CONFIG_IMAGEFILTERPARAMSTYPE *omx = (OMX_CONFIG_IMAGEFILTERPARAMSTYPE *)omx_param;
|
||||
MMAL_PARAMETER_IMAGEFX_PARAMETERS_T *mmal = (MMAL_PARAMETER_IMAGEFX_PARAMETERS_T *)mmal_param;
|
||||
MMALOMX_PARAM_ENUM_FIND(MMALOMX_PARAM_ENUM_TRANSLATE_T, xenum, mmalomx_param_enum_image_effect,
|
||||
dir, mmal->effect, omx->eImageFilter);
|
||||
|
||||
if (!xenum)
|
||||
return MMAL_EINVAL;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
if (omx->nNumParams > MMAL_COUNTOF(mmal->effect_parameter))
|
||||
return MMAL_EINVAL;
|
||||
mmal->effect = xenum->mmal;
|
||||
mmal->num_effect_params = omx->nNumParams;
|
||||
memcpy(mmal->effect_parameter, omx->nParams, sizeof(uint32_t) * omx->nNumParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mmal->num_effect_params > MMAL_COUNTOF(omx->nParams))
|
||||
return MMAL_EINVAL;
|
||||
omx->eImageFilter = xenum->omx;
|
||||
omx->nNumParams = mmal->num_effect_params;
|
||||
memcpy(omx->nParams, mmal->effect_parameter, sizeof(uint32_t) * omx->nNumParams);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_use_case[] = {
|
||||
{MMAL_PARAM_CAMERA_USE_CASE_UNKNOWN, OMX_CameraUseCaseAuto},
|
||||
{MMAL_PARAM_CAMERA_USE_CASE_STILLS_CAPTURE, OMX_CameraUseCaseStills},
|
||||
{MMAL_PARAM_CAMERA_USE_CASE_VIDEO_CAPTURE, OMX_CameraUseCaseVideo},
|
||||
};
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_fps_range(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_PARAM_BRCMFRAMERATERANGETYPE *omx = (OMX_PARAM_BRCMFRAMERATERANGETYPE *)omx_param;
|
||||
MMAL_PARAMETER_FPS_RANGE_T *mmal = (MMAL_PARAMETER_FPS_RANGE_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->fps_low = mmal_rational_from_fixed_16_16(omx->xFramerateLow);
|
||||
mmal->fps_high = mmal_rational_from_fixed_16_16(omx->xFramerateLow);
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->xFramerateLow = mmal_rational_to_fixed_16_16(mmal->fps_low);
|
||||
omx->xFramerateLow = mmal_rational_to_fixed_16_16(mmal->fps_high);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_ev_comp(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_PARAM_S32TYPE *omx = (OMX_PARAM_S32TYPE *)omx_param;
|
||||
MMAL_PARAMETER_INT32_T *mmal = (MMAL_PARAMETER_INT32_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
mmal->value = (omx->nS32 * 6) >> 16;
|
||||
else
|
||||
omx->nS32 = (mmal->value << 16) / 6;
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
const MMALOMX_PARAM_TRANSLATION_T mmalomx_param_xlator_camera[] = {
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_ROTATION, MMAL_PARAMETER_INT32_T,
|
||||
OMX_IndexConfigCommonRotate, OMX_CONFIG_ROTATIONTYPE),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_AWB_MODE, MMAL_PARAM_AWBMODE_T,
|
||||
OMX_IndexConfigCommonWhiteBalance, OMX_CONFIG_WHITEBALCONTROLTYPE, mmalomx_param_enum_awb_mode),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_IMAGE_EFFECT, MMAL_PARAMETER_IMAGEFX_T,
|
||||
OMX_IndexConfigCommonImageFilter, OMX_CONFIG_IMAGEFILTERTYPE, mmalomx_param_enum_image_effect),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_COLOUR_EFFECT, MMAL_PARAMETER_COLOURFX_T,
|
||||
OMX_IndexConfigCommonColorEnhancement, OMX_CONFIG_COLORENHANCEMENTTYPE, mmalomx_param_mapping_colour_effect),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_FLICKER_AVOID, MMAL_PARAMETER_FLICKERAVOID_T,
|
||||
OMX_IndexConfigCommonFlickerCancellation, OMX_CONFIG_FLICKERCANCELTYPE, mmalomx_param_enum_flicker_avoid),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_FLASH, MMAL_PARAMETER_FLASH_T,
|
||||
OMX_IndexParamFlashControl, OMX_IMAGE_PARAM_FLASHCONTROLTYPE, mmalomx_param_enum_flash),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_REDEYE, MMAL_PARAMETER_REDEYE_T,
|
||||
OMX_IndexConfigCommonRedEyeRemoval, OMX_CONFIG_REDEYEREMOVALTYPE, mmalomx_param_enum_redeye),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_FOCUS, MMAL_PARAMETER_FOCUS_T,
|
||||
OMX_IndexConfigFocusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE, mmalomx_param_mapping_focus),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_REDEYE, MMAL_PARAMETER_REDEYE_T,
|
||||
OMX_IndexConfigCommonRedEyeRemoval, OMX_CONFIG_REDEYEREMOVALTYPE, mmalomx_param_enum_flash),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_ZOOM, MMAL_PARAMETER_SCALEFACTOR_T,
|
||||
OMX_IndexConfigCommonDigitalZoom, OMX_CONFIG_SCALEFACTORTYPE),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_MIRROR, MMAL_PARAMETER_MIRROR_T,
|
||||
OMX_IndexConfigCommonMirror, OMX_CONFIG_MIRRORTYPE, mmalomx_param_enum_mirror),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_CAMERA_NUM, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamCameraDeviceNumber, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_BOOLEAN(MMAL_PARAMETER_CAPTURE,
|
||||
OMX_IndexConfigPortCapturing),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_EXPOSURE_MODE, MMAL_PARAMETER_EXPOSUREMODE_T,
|
||||
OMX_IndexConfigCommonExposure, OMX_CONFIG_EXPOSURECONTROLTYPE, mmalomx_param_enum_exposure_mode),
|
||||
MMALOMX_PARAM_ENUM_PORTLESS(MMAL_PARAMETER_CAPTURE_STATUS, MMAL_PARAMETER_CAPTURE_STATUS_T,
|
||||
OMX_IndexParamCaptureStatus, OMX_PARAM_CAPTURESTATETYPE, mmalomx_param_enum_capture_status),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_FACE_TRACK, MMAL_PARAMETER_FACE_TRACK_T,
|
||||
OMX_IndexConfigCommonFaceDetectionControl, OMX_CONFIG_FACEDETECTIONCONTROLTYPE, mmalomx_param_mapping_face_track),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
|
||||
OMX_IndexConfigDrawBoxAroundFaces),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_JPEG_Q_FACTOR, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamQFactor, OMX_IMAGE_PARAM_QFACTORTYPE),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_EXIF_DISABLE,
|
||||
OMX_IndexParamBrcmDisableEXIF),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING_PORTLESS(MMAL_PARAMETER_THUMBNAIL_CONFIGURATION, MMAL_PARAMETER_THUMBNAIL_CONFIG_T,
|
||||
OMX_IndexParamBrcmThumbnail, OMX_PARAM_BRCMTHUMBNAILTYPE, mmalomx_param_mapping_thumb_cfg),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_USE_STC, MMAL_PARAMETER_CAMERA_STC_MODE_T,
|
||||
OMX_IndexParamCommonUseStcTimestamps, OMX_PARAM_TIMESTAMPMODETYPE, mmalomx_param_enum_stc),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_STABILISATION, MMAL_PARAMETER_BOOLEAN_T,
|
||||
OMX_IndexConfigCommonFrameStabilisation, OMX_CONFIG_FRAMESTABTYPE),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_ENABLE_DPF_FILE,
|
||||
OMX_IndexParamUseDynamicParameterFile),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
|
||||
OMX_IndexParamDynamicParameterFileFailFatal),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_CAPTURE_MODE, MMAL_PARAMETER_CAPTUREMODE_T,
|
||||
OMX_IndexParamCameraCaptureMode, OMX_PARAM_CAMERACAPTUREMODETYPE, mmalomx_param_enum_capture_mode),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_INPUT_CROP, MMAL_PARAMETER_INPUT_CROP_T,
|
||||
OMX_IndexConfigInputCropPercentages, OMX_CONFIG_INPUTCROPTYPE),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING_PORTLESS(MMAL_PARAMETER_SENSOR_INFORMATION, MMAL_PARAMETER_SENSOR_INFORMATION_T,
|
||||
OMX_IndexConfigCameraInfo, OMX_CONFIG_CAMERAINFOTYPE, mmalomx_param_mapping_sensor_info),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_FLASH_SELECT, MMAL_PARAMETER_FLASH_SELECT_T,
|
||||
OMX_IndexParamCameraFlashType, OMX_PARAM_CAMERAFLASHTYPE, mmalomx_param_enum_flash_select),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_FIELD_OF_VIEW, MMAL_PARAMETER_FIELD_OF_VIEW_T,
|
||||
OMX_IndexConfigFieldOfView, OMX_CONFIG_BRCMFOVTYPE, mmalomx_param_mapping_fov),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
|
||||
OMX_IndexConfigBrcmHighDynamicRange),
|
||||
MMALOMX_PARAM_ENUM_PORTLESS(MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, MMAL_PARAMETER_DRC_T,
|
||||
OMX_IndexConfigDynamicRangeExpansion, OMX_CONFIG_DYNAMICRANGEEXPANSIONTYPE, mmalomx_param_enum_drc),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING_PORTLESS(MMAL_PARAMETER_ALGORITHM_CONTROL, MMAL_PARAMETER_ALGORITHM_CONTROL_T,
|
||||
OMX_IndexParamCameraDisableAlgorithm, OMX_PARAM_CAMERADISABLEALGORITHMTYPE, mmalomx_param_mapping_algo_ctrl),
|
||||
MMALOMX_PARAM_RATIONAL(MMAL_PARAMETER_SHARPNESS, MMAL_PARAMETER_RATIONAL_T,
|
||||
OMX_IndexConfigCommonSharpness, OMX_CONFIG_SHARPNESSTYPE, 100),
|
||||
MMALOMX_PARAM_RATIONAL(MMAL_PARAMETER_CONTRAST, MMAL_PARAMETER_RATIONAL_T,
|
||||
OMX_IndexConfigCommonContrast, OMX_CONFIG_CONTRASTTYPE, 100),
|
||||
MMALOMX_PARAM_RATIONAL(MMAL_PARAMETER_BRIGHTNESS, MMAL_PARAMETER_RATIONAL_T,
|
||||
OMX_IndexConfigCommonContrast, OMX_CONFIG_CONTRASTTYPE, 100),
|
||||
MMALOMX_PARAM_RATIONAL(MMAL_PARAMETER_SATURATION, MMAL_PARAMETER_RATIONAL_T,
|
||||
OMX_IndexConfigCommonSaturation, OMX_CONFIG_SATURATIONTYPE, 100),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_ANTISHAKE,
|
||||
OMX_IndexConfigStillsAntiShakeEnable),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, MMAL_PARAMETER_IMAGEFX_PARAMETERS_T,
|
||||
OMX_IndexConfigCommonImageFilterParameters, OMX_CONFIG_IMAGEFILTERPARAMSTYPE, mmalomx_param_mapping_image_effect_params),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
|
||||
OMX_IndexConfigBurstCapture),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_CAMERA_MIN_ISO, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexConfigCameraIsoReferenceValue, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_ENUM_PORTLESS(MMAL_PARAMETER_CAMERA_USE_CASE, MMAL_PARAMETER_CAMERA_USE_CASE_T,
|
||||
OMX_IndexConfigCameraUseCase, OMX_CONFIG_CAMERAUSECASETYPE, mmalomx_param_enum_use_case),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_CAPTURE_STATS_PASS,
|
||||
OMX_IndexConfigCameraEnableStatsPass),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamCameraCustomSensorConfig, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_ENABLE_REGISTER_FILE,
|
||||
OMX_IndexConfigBrcmUseRegisterFile),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
|
||||
OMX_IndexConfigBrcmRegisterFileFailFatal),
|
||||
MMALOMX_PARAM_PASSTHROUGH_PORTLESS(MMAL_PARAMETER_CONFIGFILE_REGISTERS, MMAL_PARAMETER_CONFIGFILE_T,
|
||||
OMX_IndexParamBrcmConfigFileRegisters, OMX_PARAM_BRCMCONFIGFILETYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH_PORTLESS(MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS, MMAL_PARAMETER_CONFIGFILE_CHUNK_T,
|
||||
OMX_IndexParamBrcmConfigFileChunkRegisters, OMX_PARAM_BRCMCONFIGFILECHUNKTYPE),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_JPEG_ATTACH_LOG,
|
||||
OMX_IndexParamBrcmAttachLog),
|
||||
MMALOMX_PARAM_PASSTHROUGH_PORTLESS(MMAL_PARAMETER_ZERO_SHUTTER_LAG, MMAL_PARAMETER_ZEROSHUTTERLAG_T,
|
||||
OMX_IndexParamCameraZeroShutterLag, OMX_CONFIG_ZEROSHUTTERLAGTYPE),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_FPS_RANGE, MMAL_PARAMETER_FPS_RANGE_T,
|
||||
OMX_IndexParamBrcmFpsRange, OMX_PARAM_BRCMFRAMERATERANGETYPE, mmalomx_param_mapping_fps_range),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP, MMAL_PARAMETER_INT32_T,
|
||||
OMX_IndexParamCaptureExposureCompensation, OMX_PARAM_S32TYPE, mmalomx_param_mapping_ev_comp),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_SW_SHARPEN_DISABLE,
|
||||
OMX_IndexParamSWSharpenDisable),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_FLASH_REQUIRED,
|
||||
OMX_IndexConfigBrcmFlashRequired),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_SW_SATURATION_DISABLE,
|
||||
OMX_IndexParamSWSaturationDisable),
|
||||
MMALOMX_PARAM_TERMINATE()
|
||||
};
|
||||
|
||||
#if 0 /* Conversions which are still left to implement */
|
||||
MMALOMX_PARAM_CUSTOM(MMAL_PARAMETER_CAMERA_CONFIG, MMAL_PARAMETER_CAMERA_CONFIG_T,
|
||||
0, 0, mmal_ril_param_set_cam_config),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_EXPOSURE_COMP, MMAL_PARAMETER_INT32_T,
|
||||
OMX_IndexConfigCommonExposureValue, OMX_CONFIG_EXPOSUREVALUETYPE, 0),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_EXP_METERING_MODE, MMAL_PARAMETER_EXPOSUREMETERINGMODE_T,
|
||||
OMX_IndexConfigCommonExposureValue, OMX_CONFIG_EXPOSUREVALUETYPE, 0),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_ISO, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexConfigCommonExposureValue, OMX_CONFIG_EXPOSUREVALUETYPE, 0),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_FOCUS_STATUS, MMAL_PARAMETER_FOCUS_STATUS_T,
|
||||
OMX_IndexConfigCommonFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE, mmalomx_param_mapping_focus_status),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_EXIF, MMAL_PARAMETER_EXIF_T,
|
||||
OMX_IndexConfigMetadataItem, OMX_CONFIG_METADATAITEMTYPE, 0),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_FACE_TRACK_RESULTS, MMAL_PARAMETER_FACE_TRACK_RESULTS_T,
|
||||
OMX_IndexConfigCommonFaceDetectionRegion, OMX_CONFIG_FACEDETECTIONREGIONTYPE, 0),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_ENABLE_RAW_CAPTURE, MMAL_PARAMETER_BOOLEAN_T,
|
||||
OMX_IndexConfigCaptureRawImageURI, OMX_PARAM_CONTENTURITYPE, 0),
|
||||
MMALOMX_PARAM_PASSTHROUGH_PORTLESS(MMAL_PARAMETER_DPF_FILE, MMAL_PARAMETER_URI_T,
|
||||
OMX_IndexParamDynamicParameterFile, OMX_PARAM_CONTENTURITYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH_PORTLESS(MMAL_PARAMETER_FOCUS_REGIONS, ,
|
||||
OMX_IndexConfigCommonFocusRegionXY, ),
|
||||
#endif
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* OpenMAX IL adaptation layer for MMAL - Parameters related functions
|
||||
*/
|
||||
|
||||
#include "interface/vmcs_host/khronos/IL/OMX_Broadcom.h"
|
||||
#include "mmalomx_util_params.h"
|
||||
#include "util/mmal_util_rational.h"
|
||||
|
||||
/* Sanity check that OMX is defining the right int32 types */
|
||||
vcos_static_assert(sizeof(OMX_U32) == 4);
|
||||
|
||||
MMAL_STATUS_T mmalomx_param_enum_generic(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const struct MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal, OMX_PTR omx, MMAL_PORT_T *mmal_port);
|
||||
MMAL_STATUS_T mmalomx_param_rational_generic(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const struct MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal, OMX_PTR omx, MMAL_PORT_T *mmal_port);
|
||||
MMAL_STATUS_T mmalomx_param_mapping_generic(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const struct MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal, OMX_PTR omx, MMAL_PORT_T *mmal_port);
|
||||
|
||||
extern const MMALOMX_PARAM_TRANSLATION_T mmalomx_param_xlator_audio[];
|
||||
extern const MMALOMX_PARAM_TRANSLATION_T mmalomx_param_xlator_video[];
|
||||
extern const MMALOMX_PARAM_TRANSLATION_T mmalomx_param_xlator_camera[];
|
||||
extern const MMALOMX_PARAM_TRANSLATION_T mmalomx_param_xlator_misc[];
|
||||
|
||||
#define MMALOMX_PARAM_ENUM_FIND(TYPE, VAR, TABLE, DIR, MMAL, OMX) \
|
||||
const TYPE *VAR = TABLE; \
|
||||
const TYPE *VAR##_end = VAR + MMAL_COUNTOF(TABLE); \
|
||||
if (DIR == MMALOMX_PARAM_MAPPING_TO_MMAL) \
|
||||
while (VAR < VAR##_end && VAR->omx != OMX) VAR++; \
|
||||
else \
|
||||
while (VAR < VAR##_end && VAR->mmal != MMAL) VAR++; \
|
||||
do { if (VAR == VAR##_end) { \
|
||||
VAR = 0; \
|
||||
if (DIR == MMALOMX_PARAM_MAPPING_TO_MMAL) \
|
||||
VCOS_ALERT("omx enum value %u not supported", (unsigned int)OMX); \
|
||||
else \
|
||||
VCOS_ALERT("mmal enum value %u not supported", (unsigned int)MMAL); \
|
||||
} } while(0)
|
||||
|
||||
#define mmalomx_ct_assert(e) (sizeof(char[1 - 2*!(e)]))
|
||||
|
||||
/** List of macros used to define parameters mapping */
|
||||
#define MMALOMX_PARAM_PASSTHROUGH(a,b,c,d) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), \
|
||||
!(offsetof(d, nPortIndex) | mmalomx_ct_assert(sizeof(b)+4==sizeof(d))), \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM, {0, mmalomx_param_mapping_generic, 0, 0}, 0, 0, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_BOOLEAN(a, b) \
|
||||
MMALOMX_PARAM_PASSTHROUGH(a, MMAL_PARAMETER_BOOLEAN_T, b, OMX_CONFIG_PORTBOOLEANTYPE)
|
||||
#define MMALOMX_PARAM_PASSTHROUGH_PORTLESS(a,b,c,d) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), \
|
||||
!!(mmalomx_ct_assert(sizeof(b)==sizeof(d))), \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM, {0, mmalomx_param_mapping_generic, 0, 0}, 0, 0, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_BOOLEAN_PORTLESS(a, b) \
|
||||
MMALOMX_PARAM_PASSTHROUGH_PORTLESS(a, MMAL_PARAMETER_BOOLEAN_T, b, OMX_CONFIG_BOOLEANTYPE)
|
||||
#define MMALOMX_PARAM_PASSTHROUGH_PORTLESS_DOUBLE_TRANSLATION(a,b,c,d) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), \
|
||||
!!(mmalomx_ct_assert(sizeof(b)==sizeof(d))), \
|
||||
1, MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM, {0, mmalomx_param_mapping_generic, 0, 0}, 0, 0, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_DIRECT_PORTLESS(a,b,c,d) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), 1, \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_DIRECT, {0, 0, 0, 0}, 0, 0, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_STRAIGHT_MAPPING(a,b,c,d,e) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), \
|
||||
!offsetof(d, nPortIndex), \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_SIMPLE, {e, 0, 0, 0}, 0, 0, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_STRAIGHT_MAPPING_PORTLESS(a,b,c,d,e) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), 1, \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_SIMPLE, {e, 0, 0, 0}, 0, 0, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_STRAIGHT_MAPPING_DOUBLE_TRANSLATION(a,b,c,d,e) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), 0, \
|
||||
1, MMALOMX_PARAM_TRANSLATION_TYPE_SIMPLE, {e, 0, 0, 0}, 0, 0, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_ENUM(a,b,c,d,e) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), 0, \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM, {0, mmalomx_param_enum_generic, 0, 0}, e, MMAL_COUNTOF(e), \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_ENUM_PORTLESS(a,b,c,d,e) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), 1, \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM, {0, mmalomx_param_enum_generic, 0, 0}, e, MMAL_COUNTOF(e), \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_RATIONAL(a,b,c,d,e) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), 0, \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM, {0, mmalomx_param_rational_generic, 0, 0}, 0, e, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_RATIONAL_PORTLESS(a,b,c,d,e) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), 1, \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM, {0, mmalomx_param_rational_generic, 0, 0}, 0, e, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_CUSTOM(a,b,c,d,e) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), 0, \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM, {0, e, 0, 0}, 0, 0, \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_LIST(a,b,c,d,e,f) \
|
||||
{a, (uint32_t)c, sizeof(b), sizeof(d), 0, \
|
||||
0, MMALOMX_PARAM_TRANSLATION_TYPE_CUSTOM, {0, 0, f, 0}, 0, offsetof(d,e), \
|
||||
MMAL_TO_STRING(a), MMAL_TO_STRING(c)}
|
||||
#define MMALOMX_PARAM_TERMINATE() \
|
||||
{MMAL_PARAMETER_UNUSED, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, 0, 0, 0, 0}
|
@ -1,157 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_util_params_common.h"
|
||||
#include "mmalomx_logging.h"
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_event_request(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_CONFIG_REQUESTCALLBACKTYPE *omx = (OMX_CONFIG_REQUESTCALLBACKTYPE *)omx_param;
|
||||
MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T *mmal = (MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T *)mmal_param;
|
||||
const MMALOMX_PARAM_TRANSLATION_T *change_xlat;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
change_xlat = mmalomx_find_parameter_from_omx_id(omx->nIndex);
|
||||
if (!change_xlat)
|
||||
{
|
||||
VCOS_ALERT("ommalomx_param_mapping_event_request: omx parameter "
|
||||
"0x%08x not recognised", omx->nIndex);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
mmal->change_id = change_xlat->mmal_id;
|
||||
mmal->enable = omx->bEnable;
|
||||
}
|
||||
else
|
||||
{
|
||||
change_xlat = mmalomx_find_parameter_from_mmal_id(mmal->change_id);
|
||||
if (!change_xlat)
|
||||
{
|
||||
VCOS_ALERT("mmalomx_param_mapping_event_request: mmal parameter "
|
||||
"0x%08x not recognised", mmal->change_id);
|
||||
return MMAL_EINVAL;
|
||||
}
|
||||
|
||||
omx->nIndex = change_xlat->omx_id;
|
||||
omx->bEnable = mmal->enable;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_statistics(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_CONFIG_BRCMPORTSTATSTYPE *omx = (OMX_CONFIG_BRCMPORTSTATSTYPE *)omx_param;
|
||||
MMAL_PARAMETER_STATISTICS_T *mmal = (MMAL_PARAMETER_STATISTICS_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->buffer_count = omx->nBufferCount;
|
||||
mmal->frame_count = omx->nImageCount + omx->nFrameCount;
|
||||
mmal->frames_skipped = omx->nFrameSkips;
|
||||
mmal->frames_discarded = omx->nDiscards;
|
||||
mmal->eos_seen = omx->nEOS;
|
||||
mmal->maximum_frame_bytes = omx->nMaxFrameSize;
|
||||
mmal->total_bytes = omx_ticks_to_s64(omx->nByteCount);
|
||||
mmal->corrupt_macroblocks = omx->nCorruptMBs;
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->nBufferCount = mmal->buffer_count;
|
||||
omx->nFrameCount = mmal->frame_count;
|
||||
omx->nImageCount = 0;
|
||||
omx->nFrameSkips = mmal->frames_skipped;
|
||||
omx->nDiscards = mmal->frames_discarded;
|
||||
omx->nEOS = mmal->eos_seen;
|
||||
omx->nMaxFrameSize = mmal->maximum_frame_bytes;
|
||||
omx->nByteCount = omx_ticks_from_s64(mmal->total_bytes);
|
||||
omx->nCorruptMBs = mmal->corrupt_macroblocks;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_buffer_flags(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_PARAM_U32TYPE *omx = (OMX_PARAM_U32TYPE *)omx_param;
|
||||
MMAL_PARAMETER_UINT32_T *mmal = (MMAL_PARAMETER_UINT32_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
mmal->value = mmalil_buffer_flags_to_mmal(omx->nU32);
|
||||
else
|
||||
omx->nU32 = mmalil_buffer_flags_to_omx(mmal->value);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_time(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_TIME_CONFIG_TIMESTAMPTYPE *omx = (OMX_TIME_CONFIG_TIMESTAMPTYPE *)omx_param;
|
||||
MMAL_PARAMETER_INT64_T *mmal = (MMAL_PARAMETER_INT64_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
mmal->value = omx_ticks_to_s64(omx->nTimestamp);
|
||||
else
|
||||
omx->nTimestamp = omx_ticks_from_s64(mmal->value);
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
const MMALOMX_PARAM_TRANSLATION_T mmalomx_param_xlator_misc[] = {
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING_DOUBLE_TRANSLATION(MMAL_PARAMETER_CHANGE_EVENT_REQUEST, MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T,
|
||||
OMX_IndexConfigRequestCallback, OMX_CONFIG_REQUESTCALLBACKTYPE,
|
||||
mmalomx_param_mapping_event_request),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_STATISTICS, MMAL_PARAMETER_STATISTICS_T,
|
||||
OMX_IndexConfigBrcmPortStats, OMX_CONFIG_BRCMPORTSTATSTYPE,
|
||||
mmalomx_param_mapping_statistics),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_MEM_USAGE, MMAL_PARAMETER_MEM_USAGE_T,
|
||||
OMX_IndexConfigBrcmPoolMemAllocSize, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_BUFFER_FLAG_FILTER, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexConfigBrcmBufferFlagFilter, OMX_PARAM_U32TYPE,
|
||||
mmalomx_param_mapping_buffer_flags),
|
||||
MMALOMX_PARAM_BOOLEAN(MMAL_PARAMETER_ZERO_COPY,
|
||||
OMX_IndexParamBrcmZeroCopy),
|
||||
MMALOMX_PARAM_BOOLEAN(MMAL_PARAMETER_LOCKSTEP_ENABLE,
|
||||
OMX_IndexParamBrcmLockStepEnable),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_POWERMON_ENABLE,
|
||||
OMX_IndexConfigBrcmPowerMonitor),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_CLOCK_TIME, MMAL_PARAMETER_INT64_T,
|
||||
OMX_IndexConfigTimeCurrentMediaTime, OMX_TIME_CONFIG_TIMESTAMPTYPE,
|
||||
mmalomx_param_mapping_time),
|
||||
MMALOMX_PARAM_TERMINATE()
|
||||
};
|
||||
|
||||
#if 0
|
||||
/* Conversions which are not done here. Should part of the core. */
|
||||
MMAL_PARAMETER_SUPPORTED_ENCODINGS
|
||||
#endif
|
@ -1,277 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmalomx.h"
|
||||
#include "mmalomx_util_params_common.h"
|
||||
#include "mmalomx_logging.h"
|
||||
|
||||
static void rect_to_omx(OMX_DISPLAYRECTTYPE *dst, const MMAL_RECT_T *src)
|
||||
{
|
||||
dst->x_offset = src->x;
|
||||
dst->y_offset = src->y;
|
||||
dst->width = src->width;
|
||||
dst->height = src->height;
|
||||
}
|
||||
|
||||
static void rect_to_mmal(MMAL_RECT_T *dst, const OMX_DISPLAYRECTTYPE *src)
|
||||
{
|
||||
dst->x = src->x_offset;
|
||||
dst->y = src->y_offset;
|
||||
dst->width = src->width;
|
||||
dst->height = src->height;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_displayregion(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_CONFIG_DISPLAYREGIONTYPE *omx = (OMX_CONFIG_DISPLAYREGIONTYPE *)omx_param;
|
||||
MMAL_DISPLAYREGION_T *mmal = (MMAL_DISPLAYREGION_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->set = omx->set;
|
||||
mmal->display_num = omx->num;
|
||||
mmal->fullscreen = omx->fullscreen;
|
||||
mmal->transform = omx->transform;
|
||||
rect_to_mmal(&mmal->dest_rect, &omx->dest_rect);
|
||||
rect_to_mmal(&mmal->src_rect, &omx->src_rect);
|
||||
mmal->noaspect = omx->noaspect;
|
||||
mmal->mode = omx->mode;
|
||||
mmal->pixel_x = omx->pixel_x;
|
||||
mmal->pixel_y = omx->pixel_y;
|
||||
mmal->layer = omx->layer;
|
||||
mmal->copyprotect_required = omx->copyprotect_required;
|
||||
mmal->alpha = omx->alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->set = mmal->set;
|
||||
omx->num = mmal->display_num;
|
||||
omx->fullscreen = mmal->fullscreen;
|
||||
omx->transform = mmal->transform;
|
||||
rect_to_omx(&omx->dest_rect, &mmal->dest_rect);
|
||||
rect_to_omx(&omx->src_rect, &mmal->src_rect);
|
||||
omx->noaspect = mmal->noaspect;
|
||||
omx->mode = mmal->mode;
|
||||
omx->pixel_x = mmal->pixel_x;
|
||||
omx->pixel_y = mmal->pixel_y;
|
||||
omx->layer = mmal->layer;
|
||||
omx->copyprotect_required = mmal->copyprotect_required;
|
||||
omx->alpha = mmal->alpha;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_list_supported_profiles(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat, unsigned int index,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param, MMAL_PORT_T *mmal_port)
|
||||
{
|
||||
OMX_VIDEO_PARAM_PROFILELEVELTYPE *omx = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)omx_param;
|
||||
MMAL_PARAMETER_VIDEO_PROFILE_T *mmal = (MMAL_PARAMETER_VIDEO_PROFILE_T *)mmal_param;
|
||||
MMAL_PARAM_UNUSED(xlat);
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
OMX_VIDEO_CODINGTYPE coding = mmalil_encoding_to_omx_video_coding(mmal_port->format->encoding);
|
||||
mmal->profile[index].profile = mmalil_omx_video_profile_to_mmal(omx->eProfile, coding);
|
||||
mmal->profile[index].level = mmalil_omx_video_level_to_mmal(omx->eLevel, coding);
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->eProfile = mmalil_video_profile_to_omx(mmal->profile[index].profile);
|
||||
omx->eLevel = mmalil_video_level_to_omx(mmal->profile[index].level);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_custom_profile(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param, MMAL_PORT_T *mmal_port)
|
||||
{
|
||||
OMX_VIDEO_PARAM_PROFILELEVELTYPE *omx = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)omx_param;
|
||||
MMAL_PARAMETER_VIDEO_PROFILE_T *mmal = (MMAL_PARAMETER_VIDEO_PROFILE_T *)mmal_param;
|
||||
MMAL_PARAM_UNUSED(xlat);
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
OMX_VIDEO_CODINGTYPE coding = mmalil_encoding_to_omx_video_coding(mmal_port->format->encoding);
|
||||
mmal->profile[0].profile = mmalil_omx_video_profile_to_mmal(omx->eProfile, coding);
|
||||
mmal->profile[0].level = mmalil_omx_video_level_to_mmal(omx->eLevel, coding);
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->eProfile = mmalil_video_profile_to_omx(mmal->profile[0].profile);
|
||||
omx->eLevel = mmalil_video_level_to_omx(mmal->profile[0].level);
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_custom_ratecontrol(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
const MMALOMX_PARAM_TRANSLATION_T *xlat,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param, MMAL_PORT_T *mmal_port)
|
||||
{
|
||||
OMX_VIDEO_PARAM_BITRATETYPE *omx = (OMX_VIDEO_PARAM_BITRATETYPE *)omx_param;
|
||||
MMAL_PARAMETER_VIDEO_RATECONTROL_T *mmal = (MMAL_PARAMETER_VIDEO_RATECONTROL_T *)mmal_param;
|
||||
MMAL_PARAM_UNUSED(xlat);
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->control = mmalil_omx_video_ratecontrol_to_mmal(omx->eControlRate);
|
||||
/* This does not apply nTargetBitrate but should not be necessary */
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->eControlRate = mmalil_video_ratecontrol_to_omx(mmal->control);
|
||||
omx->nTargetBitrate = mmal_port->format->bitrate; /* Should not really be necessary */
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
static const MMALOMX_PARAM_ENUM_TRANSLATE_T mmalomx_param_enum_nalunitformat[] = {
|
||||
{MMAL_VIDEO_NALUNITFORMAT_STARTCODES, OMX_NaluFormatStartCodes},
|
||||
{MMAL_VIDEO_NALUNITFORMAT_NALUNITPERBUFFER, OMX_NaluFormatOneNaluPerBuffer},
|
||||
{MMAL_VIDEO_NALUNITFORMAT_ONEBYTEINTERLEAVELENGTH, OMX_NaluFormatOneByteInterleaveLength},
|
||||
{MMAL_VIDEO_NALUNITFORMAT_TWOBYTEINTERLEAVELENGTH, OMX_NaluFormatTwoByteInterleaveLength},
|
||||
{MMAL_VIDEO_NALUNITFORMAT_FOURBYTEINTERLEAVELENGTH, OMX_NaluFormatFourByteInterleaveLength},
|
||||
};
|
||||
|
||||
static MMAL_STATUS_T mmalomx_param_mapping_frame_rate(MMALOMX_PARAM_MAPPING_DIRECTION dir,
|
||||
MMAL_PARAMETER_HEADER_T *mmal_param, OMX_PTR omx_param)
|
||||
{
|
||||
OMX_CONFIG_FRAMERATETYPE *omx = (OMX_CONFIG_FRAMERATETYPE *)omx_param;
|
||||
MMAL_PARAMETER_FRAME_RATE_T *mmal = (MMAL_PARAMETER_FRAME_RATE_T *)mmal_param;
|
||||
|
||||
if (dir == MMALOMX_PARAM_MAPPING_TO_MMAL)
|
||||
{
|
||||
mmal->frame_rate.num = omx->xEncodeFramerate;
|
||||
mmal->frame_rate.den = (1<<16);
|
||||
}
|
||||
else
|
||||
{
|
||||
omx->xEncodeFramerate = 0;
|
||||
if (mmal->frame_rate.den)
|
||||
omx->xEncodeFramerate = (((int64_t)mmal->frame_rate.num)<<16)/mmal->frame_rate.den;
|
||||
}
|
||||
|
||||
return MMAL_SUCCESS;
|
||||
}
|
||||
|
||||
const MMALOMX_PARAM_TRANSLATION_T mmalomx_param_xlator_video[] = {
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_DISPLAYREGION, MMAL_DISPLAYREGION_T,
|
||||
OMX_IndexConfigDisplayRegion, OMX_CONFIG_DISPLAYREGIONTYPE,
|
||||
mmalomx_param_mapping_displayregion),
|
||||
MMALOMX_PARAM_LIST(MMAL_PARAMETER_SUPPORTED_PROFILES, MMAL_PARAMETER_VIDEO_PROFILE_T,
|
||||
OMX_IndexParamVideoProfileLevelQuerySupported, OMX_VIDEO_PARAM_PROFILELEVELTYPE,
|
||||
nProfileIndex, mmalomx_param_list_supported_profiles),
|
||||
MMALOMX_PARAM_CUSTOM(MMAL_PARAMETER_PROFILE, MMAL_PARAMETER_VIDEO_PROFILE_T,
|
||||
OMX_IndexParamVideoProfileLevelCurrent, OMX_VIDEO_PARAM_PROFILELEVELTYPE,
|
||||
mmalomx_param_custom_profile),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_INTRAPERIOD, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexConfigBrcmVideoIntraPeriod, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_CUSTOM(MMAL_PARAMETER_RATECONTROL, MMAL_PARAMETER_VIDEO_RATECONTROL_T,
|
||||
OMX_IndexParamVideoBitrate, OMX_VIDEO_PARAM_BITRATETYPE,
|
||||
mmalomx_param_custom_ratecontrol),
|
||||
MMALOMX_PARAM_ENUM(MMAL_PARAMETER_NALUNITFORMAT, MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T,
|
||||
OMX_IndexParamNalStreamFormatSelect, OMX_NALSTREAMFORMATTYPE, mmalomx_param_enum_nalunitformat),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
|
||||
OMX_IndexConfigMinimiseFragmentation),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_MB_ROWS_PER_SLICE, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexConfigBrcmVideoEncoderMBRowsPerSlice, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION, MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T,
|
||||
OMX_IndexConfigEncLevelExtension, OMX_VIDEO_CONFIG_LEVEL_EXTEND),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_INTRA_REFRESH, MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T,
|
||||
OMX_IndexConfigBrcmVideoIntraRefresh, OMX_VIDEO_PARAM_INTRAREFRESHTYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_INTRA_REFRESH, MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T,
|
||||
OMX_IndexParamVideoIntraRefresh, OMX_VIDEO_PARAM_INTRAREFRESHTYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_EEDE_ENABLE, MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T,
|
||||
OMX_IndexParamBrcmEEDEEnable, OMX_VIDEO_EEDE_ENABLE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE, MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T,
|
||||
OMX_IndexParamBrcmEEDELossRate, OMX_VIDEO_EEDE_LOSSRATE),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
|
||||
OMX_IndexConfigBrcmVideoRequestIFrame),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
|
||||
OMX_IndexParamBrcmImmutableInput),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_BIT_RATE, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexConfigVideoBitrate, OMX_VIDEO_CONFIG_BITRATETYPE),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_VIDEO_FRAME_RATE, MMAL_PARAMETER_FRAME_RATE_T,
|
||||
OMX_IndexConfigVideoFramerate, OMX_CONFIG_FRAMERATETYPE, mmalomx_param_mapping_frame_rate),
|
||||
MMALOMX_PARAM_STRAIGHT_MAPPING(MMAL_PARAMETER_FRAME_RATE, MMAL_PARAMETER_FRAME_RATE_T,
|
||||
OMX_IndexConfigVideoFramerate, OMX_CONFIG_FRAMERATETYPE, mmalomx_param_mapping_frame_rate),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmVideoEncodeMinQuant, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmVideoEncodeMaxQuant, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL, MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T,
|
||||
OMX_IndexParamRateControlModel, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_EXTRA_BUFFERS, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmExtraBuffers, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ALIGN_HORIZ, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmAlignHoriz, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ALIGN_VERT, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmAlignVert, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
|
||||
OMX_IndexParamBrcmDroppablePFrames),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmVideoInitialQuant, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_QP_P, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmVideoInitialQuant, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmVideoRCSliceDQuant, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmVideoFrameLimitBits, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexParamBrcmVideoPeakRate, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
|
||||
OMX_IndexConfigBrcmVideoH264DisableCABAC),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
|
||||
OMX_IndexConfigBrcmVideoH264LowLatency),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
|
||||
OMX_IndexConfigBrcmVideoH264AUDelimiters),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC, MMAL_PARAMETER_UINT32_T,
|
||||
OMX_IndexConfigBrcmVideoH264DeblockIDC, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH(MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE, MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T,
|
||||
OMX_IndexConfigBrcmVideoH264IntraMBMode, OMX_PARAM_U32TYPE),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
|
||||
OMX_IndexParamBrcmHeaderOnOpen),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
|
||||
OMX_IndexParamBrcmVideoPrecodeForQP),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
|
||||
OMX_IndexParamBrcmVideoTimestampFifo),
|
||||
MMALOMX_PARAM_BOOLEAN_PORTLESS(MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
|
||||
OMX_IndexParamBrcmVideoDecodeErrorConcealment),
|
||||
MMALOMX_PARAM_PASSTHROUGH_PORTLESS_DOUBLE_TRANSLATION(MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER, MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T,
|
||||
OMX_IndexParamBrcmVideoDrmProtectBuffer, OMX_PARAM_BRCMVIDEODRMPROTECTBUFFERTYPE),
|
||||
MMALOMX_PARAM_PASSTHROUGH_PORTLESS(MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3, MMAL_PARAMETER_BYTES_T,
|
||||
OMX_IndexParamBrcmVideoDecodeConfigVD3, OMX_PARAM_BRCMVIDEODECODECONFIGVD3TYPE),
|
||||
MMALOMX_PARAM_BOOLEAN(MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
|
||||
OMX_IndexParamBrcmVideoAVCInlineHeaderEnable),
|
||||
MMALOMX_PARAM_TERMINATE()
|
||||
};
|
@ -1,26 +0,0 @@
|
||||
SET( MMAL_TOP ../../.. )
|
||||
SET( MMALPLAY_TOP ${MMAL_TOP}/host_applications/vmcs/test_apps/mmalplay )
|
||||
add_executable(mmalplay ${MMALPLAY_TOP}/playback.c ${MMALPLAY_TOP}/mmalplay.c)
|
||||
target_link_libraries(mmalplay mmal_core mmal_util)
|
||||
target_link_libraries(mmalplay -Wl,--whole-archive mmal_components containers -Wl,--no-whole-archive mmal_core)
|
||||
target_link_libraries(mmalplay vcos)
|
||||
|
||||
SET( MMALCAM_TOP ${MMAL_TOP}/host_applications/vmcs/test_apps/mmalcam )
|
||||
add_executable(mmalcam ${MMALCAM_TOP}/viewfinder.c ${MMALCAM_TOP}/mmalcam.c)
|
||||
target_link_libraries(mmalcam mmal_core mmal_util)
|
||||
target_link_libraries(mmalcam -Wl,--whole-archive mmal_components -Wl,--no-whole-archive mmal_core)
|
||||
target_link_libraries(mmalcam vcos)
|
||||
|
||||
SET( MMALEXAMPLES_TOP ${MMAL_TOP}/interface/mmal/test/examples )
|
||||
add_executable(mmal_example_connections ${MMALEXAMPLES_TOP}/example_connections.c)
|
||||
target_link_libraries(mmal_example_connections mmal_core mmal_util)
|
||||
target_link_libraries(mmal_example_connections -Wl,--whole-archive mmal_components -Wl,--no-whole-archive mmal_core)
|
||||
add_executable(mmal_example_graph ${MMALEXAMPLES_TOP}/example_graph.c)
|
||||
target_link_libraries(mmal_example_graph mmal_core mmal_util)
|
||||
target_link_libraries(mmal_example_graph -Wl,--whole-archive mmal_components -Wl,--no-whole-archive mmal_core)
|
||||
add_executable(mmal_example_basic_1 ${MMALEXAMPLES_TOP}/example_basic_1.c)
|
||||
target_link_libraries(mmal_example_basic_1 mmal_core mmal_util)
|
||||
target_link_libraries(mmal_example_basic_1 -Wl,--whole-archive mmal_components -Wl,--no-whole-archive mmal_core)
|
||||
add_executable(mmal_example_basic_2 ${MMALEXAMPLES_TOP}/example_basic_2.c)
|
||||
target_link_libraries(mmal_example_basic_2 mmal_core mmal_util)
|
||||
target_link_libraries(mmal_example_basic_2 -Wl,--whole-archive mmal_components -Wl,--no-whole-archive mmal_core)
|
@ -1,238 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "util/mmal_default_components.h"
|
||||
#include "interface/vcos/vcos.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define CHECK_STATUS(status, msg) if (status != MMAL_SUCCESS) { fprintf(stderr, msg"\n"); goto error; }
|
||||
|
||||
static uint8_t codec_header_bytes[512];
|
||||
static unsigned int codec_header_bytes_size = sizeof(codec_header_bytes);
|
||||
|
||||
static FILE *source_file;
|
||||
|
||||
/* Macros abstracting the I/O, just to make the example code clearer */
|
||||
#define SOURCE_OPEN(uri) \
|
||||
source_file = fopen(uri, "rb"); if (!source_file) goto error;
|
||||
#define SOURCE_READ_CODEC_CONFIG_DATA(bytes, size) \
|
||||
size = fread(bytes, 1, size, source_file); rewind(source_file)
|
||||
#define SOURCE_READ_DATA_INTO_BUFFER(a) \
|
||||
a->length = fread(a->data, 1, a->alloc_size - 128, source_file); \
|
||||
a->offset = 0; a->pts = a->dts = MMAL_TIME_UNKNOWN
|
||||
#define SOURCE_CLOSE() \
|
||||
if (source_file) fclose(source_file)
|
||||
|
||||
/** Context for our application */
|
||||
static struct CONTEXT_T {
|
||||
VCOS_SEMAPHORE_T semaphore;
|
||||
MMAL_QUEUE_T *queue;
|
||||
} context;
|
||||
|
||||
/** Callback from the input port.
|
||||
* Buffer has been consumed and is available to be used again. */
|
||||
static void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata;
|
||||
|
||||
/* The decoder is done with the data, just recycle the buffer header into its pool */
|
||||
mmal_buffer_header_release(buffer);
|
||||
|
||||
/* Kick the processing thread */
|
||||
vcos_semaphore_post(&ctx->semaphore);
|
||||
}
|
||||
|
||||
/** Callback from the output port.
|
||||
* Buffer has been produced by the port and is available for processing. */
|
||||
static void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata;
|
||||
|
||||
/* Queue the decoded video frame */
|
||||
mmal_queue_put(ctx->queue, buffer);
|
||||
|
||||
/* Kick the processing thread */
|
||||
vcos_semaphore_post(&ctx->semaphore);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_EINVAL;
|
||||
MMAL_COMPONENT_T *decoder = 0;
|
||||
MMAL_POOL_T *pool_in = 0, *pool_out = 0;
|
||||
unsigned int count;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vcos_semaphore_create(&context.semaphore, "example", 1);
|
||||
|
||||
SOURCE_OPEN(argv[1]);
|
||||
|
||||
/* Create the decoder component.
|
||||
* This specific component exposes 2 ports (1 input and 1 output). Like most components
|
||||
* its expects the format of its input port to be set by the client in order for it to
|
||||
* know what kind of data it will be fed. */
|
||||
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &decoder);
|
||||
CHECK_STATUS(status, "failed to create decoder");
|
||||
|
||||
/* Set format of video decoder input port */
|
||||
MMAL_ES_FORMAT_T *format_in = decoder->input[0]->format;
|
||||
format_in->type = MMAL_ES_TYPE_VIDEO;
|
||||
format_in->encoding = MMAL_ENCODING_H264;
|
||||
format_in->es->video.width = 1280;
|
||||
format_in->es->video.height = 720;
|
||||
format_in->es->video.frame_rate.num = 30;
|
||||
format_in->es->video.frame_rate.den = 1;
|
||||
format_in->es->video.par.num = 1;
|
||||
format_in->es->video.par.den = 1;
|
||||
/* If the data is known to be framed then the following flag should be set:
|
||||
* format_in->flags |= MMAL_ES_FORMAT_FLAG_FRAMED; */
|
||||
|
||||
SOURCE_READ_CODEC_CONFIG_DATA(codec_header_bytes, codec_header_bytes_size);
|
||||
status = mmal_format_extradata_alloc(format_in, codec_header_bytes_size);
|
||||
CHECK_STATUS(status, "failed to allocate extradata");
|
||||
format_in->extradata_size = codec_header_bytes_size;
|
||||
if (format_in->extradata_size)
|
||||
memcpy(format_in->extradata, codec_header_bytes, format_in->extradata_size);
|
||||
|
||||
status = mmal_port_format_commit(decoder->input[0]);
|
||||
CHECK_STATUS(status, "failed to commit format");
|
||||
|
||||
/* Display the output port format */
|
||||
MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format;
|
||||
fprintf(stderr, "%s\n", decoder->output[0]->name);
|
||||
fprintf(stderr, " type: %i, fourcc: %4.4s\n", format_out->type, (char *)&format_out->encoding);
|
||||
fprintf(stderr, " bitrate: %i, framed: %i\n", format_out->bitrate,
|
||||
!!(format_out->flags & MMAL_ES_FORMAT_FLAG_FRAMED));
|
||||
fprintf(stderr, " extra data: %i, %p\n", format_out->extradata_size, format_out->extradata);
|
||||
fprintf(stderr, " width: %i, height: %i, (%i,%i,%i,%i)\n",
|
||||
format_out->es->video.width, format_out->es->video.height,
|
||||
format_out->es->video.crop.x, format_out->es->video.crop.y,
|
||||
format_out->es->video.crop.width, format_out->es->video.crop.height);
|
||||
|
||||
/* The format of both ports is now set so we can get their buffer requirements and create
|
||||
* our buffer headers. We use the buffer pool API to create these. */
|
||||
decoder->input[0]->buffer_num = decoder->input[0]->buffer_num_min;
|
||||
decoder->input[0]->buffer_size = decoder->input[0]->buffer_size_min;
|
||||
decoder->output[0]->buffer_num = decoder->output[0]->buffer_num_min;
|
||||
decoder->output[0]->buffer_size = decoder->output[0]->buffer_size_min;
|
||||
pool_in = mmal_pool_create(decoder->input[0]->buffer_num,
|
||||
decoder->input[0]->buffer_size);
|
||||
pool_out = mmal_pool_create(decoder->output[0]->buffer_num,
|
||||
decoder->output[0]->buffer_size);
|
||||
|
||||
/* Create a queue to store our decoded video frames. The callback we will get when
|
||||
* a frame has been decoded will put the frame into this queue. */
|
||||
context.queue = mmal_queue_create();
|
||||
|
||||
/* Store a reference to our context in each port (will be used during callbacks) */
|
||||
decoder->input[0]->userdata = (void *)&context;
|
||||
decoder->output[0]->userdata = (void *)&context;
|
||||
|
||||
/* Enable all the input port and the output port.
|
||||
* The callback specified here is the function which will be called when the buffer header
|
||||
* we sent to the component has been processed. */
|
||||
status = mmal_port_enable(decoder->input[0], input_callback);
|
||||
CHECK_STATUS(status, "failed to enable input port");
|
||||
status = mmal_port_enable(decoder->output[0], output_callback);
|
||||
CHECK_STATUS(status, "failed to enable output port");
|
||||
|
||||
/* Component won't start processing data until it is enabled. */
|
||||
status = mmal_component_enable(decoder);
|
||||
CHECK_STATUS(status, "failed to enable component");
|
||||
|
||||
/* Start decoding */
|
||||
fprintf(stderr, "start decoding\n");
|
||||
|
||||
/* This is the main processing loop */
|
||||
for (count = 0; count < 500; count++)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/* Wait for buffer headers to be available on either of the decoder ports */
|
||||
vcos_semaphore_wait(&context.semaphore);
|
||||
|
||||
/* Send data to decode to the input port of the video decoder */
|
||||
if ((buffer = mmal_queue_get(pool_in->queue)) != NULL)
|
||||
{
|
||||
SOURCE_READ_DATA_INTO_BUFFER(buffer);
|
||||
if (!buffer->length)
|
||||
break;
|
||||
|
||||
fprintf(stderr, "sending %i bytes\n", (int)buffer->length);
|
||||
status = mmal_port_send_buffer(decoder->input[0], buffer);
|
||||
CHECK_STATUS(status, "failed to send buffer");
|
||||
}
|
||||
|
||||
/* Get our decoded frames */
|
||||
while ((buffer = mmal_queue_get(context.queue)) != NULL)
|
||||
{
|
||||
/* We have a frame, do something with it (why not display it for instance?).
|
||||
* Once we're done with it, we release it. It will automatically go back
|
||||
* to its original pool so it can be reused for a new video frame.
|
||||
*/
|
||||
fprintf(stderr, "decoded frame\n");
|
||||
mmal_buffer_header_release(buffer);
|
||||
}
|
||||
|
||||
/* Send empty buffers to the output port of the decoder */
|
||||
while ((buffer = mmal_queue_get(pool_out->queue)) != NULL)
|
||||
{
|
||||
status = mmal_port_send_buffer(decoder->output[0], buffer);
|
||||
CHECK_STATUS(status, "failed to send buffer");
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop decoding */
|
||||
fprintf(stderr, "stop decoding\n");
|
||||
|
||||
/* Stop everything. Not strictly necessary since mmal_component_destroy()
|
||||
* will do that anyway */
|
||||
mmal_port_disable(decoder->input[0]);
|
||||
mmal_port_disable(decoder->output[0]);
|
||||
mmal_component_disable(decoder);
|
||||
|
||||
error:
|
||||
/* Cleanup everything */
|
||||
if (decoder)
|
||||
mmal_component_destroy(decoder);
|
||||
if (pool_in)
|
||||
mmal_pool_destroy(pool_in);
|
||||
if (pool_out)
|
||||
mmal_pool_destroy(pool_out);
|
||||
if (context.queue)
|
||||
mmal_queue_destroy(context.queue);
|
||||
|
||||
SOURCE_CLOSE();
|
||||
vcos_semaphore_delete(&context.semaphore);
|
||||
return status == MMAL_SUCCESS ? 0 : -1;
|
||||
}
|
@ -1,304 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "util/mmal_default_components.h"
|
||||
#include "util/mmal_util_params.h"
|
||||
#include "interface/vcos/vcos.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define CHECK_STATUS(status, msg) if (status != MMAL_SUCCESS) { fprintf(stderr, msg"\n"); goto error; }
|
||||
|
||||
static uint8_t codec_header_bytes[512];
|
||||
static unsigned int codec_header_bytes_size = sizeof(codec_header_bytes);
|
||||
|
||||
static FILE *source_file;
|
||||
|
||||
/* Macros abstracting the I/O, just to make the example code clearer */
|
||||
#define SOURCE_OPEN(uri) \
|
||||
source_file = fopen(uri, "rb"); if (!source_file) goto error;
|
||||
#define SOURCE_READ_CODEC_CONFIG_DATA(bytes, size) \
|
||||
size = fread(bytes, 1, size, source_file); rewind(source_file)
|
||||
#define SOURCE_READ_DATA_INTO_BUFFER(a) \
|
||||
a->length = fread(a->data, 1, a->alloc_size - 128, source_file); \
|
||||
a->offset = 0
|
||||
#define SOURCE_CLOSE() \
|
||||
if (source_file) fclose(source_file)
|
||||
|
||||
/** Context for our application */
|
||||
static struct CONTEXT_T {
|
||||
VCOS_SEMAPHORE_T semaphore;
|
||||
MMAL_QUEUE_T *queue;
|
||||
MMAL_STATUS_T status;
|
||||
} context;
|
||||
|
||||
/** Callback from the control port.
|
||||
* Component is sending us an event. */
|
||||
static void control_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata;
|
||||
|
||||
switch (buffer->cmd)
|
||||
{
|
||||
case MMAL_EVENT_EOS:
|
||||
/* Only sink component generate EOS events */
|
||||
break;
|
||||
case MMAL_EVENT_ERROR:
|
||||
/* Something went wrong. Signal this to the application */
|
||||
ctx->status = *(MMAL_STATUS_T *)buffer->data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Done with the event, recycle it */
|
||||
mmal_buffer_header_release(buffer);
|
||||
|
||||
/* Kick the processing thread */
|
||||
vcos_semaphore_post(&ctx->semaphore);
|
||||
}
|
||||
|
||||
/** Callback from the input port.
|
||||
* Buffer has been consumed and is available to be used again. */
|
||||
static void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata;
|
||||
|
||||
/* The decoder is done with the data, just recycle the buffer header into its pool */
|
||||
mmal_buffer_header_release(buffer);
|
||||
|
||||
/* Kick the processing thread */
|
||||
vcos_semaphore_post(&ctx->semaphore);
|
||||
}
|
||||
|
||||
/** Callback from the output port.
|
||||
* Buffer has been produced by the port and is available for processing. */
|
||||
static void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata;
|
||||
|
||||
/* Queue the decoded video frame */
|
||||
mmal_queue_put(ctx->queue, buffer);
|
||||
|
||||
/* Kick the processing thread */
|
||||
vcos_semaphore_post(&ctx->semaphore);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MMAL_STATUS_T status = MMAL_EINVAL;
|
||||
MMAL_COMPONENT_T *decoder = 0;
|
||||
MMAL_POOL_T *pool_in = 0, *pool_out = 0;
|
||||
MMAL_BOOL_T eos_sent = MMAL_FALSE, eos_received = MMAL_FALSE;
|
||||
unsigned int count;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vcos_semaphore_create(&context.semaphore, "example", 1);
|
||||
|
||||
SOURCE_OPEN(argv[1]);
|
||||
|
||||
/* Create the decoder component.
|
||||
* This specific component exposes 2 ports (1 input and 1 output). Like most components
|
||||
* its expects the format of its input port to be set by the client in order for it to
|
||||
* know what kind of data it will be fed. */
|
||||
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &decoder);
|
||||
CHECK_STATUS(status, "failed to create decoder");
|
||||
|
||||
/* Enable control port so we can receive events from the component */
|
||||
decoder->control->userdata = (void *)&context;
|
||||
status = mmal_port_enable(decoder->control, control_callback);
|
||||
CHECK_STATUS(status, "failed to enable control port");
|
||||
|
||||
/* Get statistics on the input port */
|
||||
MMAL_PARAMETER_CORE_STATISTICS_T stats = {{0}};
|
||||
stats.hdr.id = MMAL_PARAMETER_CORE_STATISTICS;
|
||||
stats.hdr.size = sizeof(MMAL_PARAMETER_CORE_STATISTICS_T);
|
||||
status = mmal_port_parameter_get(decoder->input[0], &stats.hdr);
|
||||
CHECK_STATUS(status, "failed to get stats");
|
||||
fprintf(stderr, "stats: %i, %i", stats.stats.buffer_count, stats.stats.max_delay);
|
||||
|
||||
/* Set the zero-copy parameter on the input port */
|
||||
MMAL_PARAMETER_BOOLEAN_T zc = {{MMAL_PARAMETER_ZERO_COPY, sizeof(zc)}, MMAL_TRUE};
|
||||
status = mmal_port_parameter_set(decoder->input[0], &zc.hdr);
|
||||
fprintf(stderr, "status: %i\n", status);
|
||||
|
||||
/* Set the zero-copy parameter on the output port */
|
||||
status = mmal_port_parameter_set_boolean(decoder->output[0], MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
|
||||
fprintf(stderr, "status: %i\n", status);
|
||||
|
||||
/* Set format of video decoder input port */
|
||||
MMAL_ES_FORMAT_T *format_in = decoder->input[0]->format;
|
||||
format_in->type = MMAL_ES_TYPE_VIDEO;
|
||||
format_in->encoding = MMAL_ENCODING_H264;
|
||||
format_in->es->video.width = 1280;
|
||||
format_in->es->video.height = 720;
|
||||
format_in->es->video.frame_rate.num = 30;
|
||||
format_in->es->video.frame_rate.den = 1;
|
||||
format_in->es->video.par.num = 1;
|
||||
format_in->es->video.par.den = 1;
|
||||
/* If the data is known to be framed then the following flag should be set:
|
||||
* format_in->flags |= MMAL_ES_FORMAT_FLAG_FRAMED; */
|
||||
|
||||
SOURCE_READ_CODEC_CONFIG_DATA(codec_header_bytes, codec_header_bytes_size);
|
||||
status = mmal_format_extradata_alloc(format_in, codec_header_bytes_size);
|
||||
CHECK_STATUS(status, "failed to allocate extradata");
|
||||
format_in->extradata_size = codec_header_bytes_size;
|
||||
if (format_in->extradata_size)
|
||||
memcpy(format_in->extradata, codec_header_bytes, format_in->extradata_size);
|
||||
|
||||
status = mmal_port_format_commit(decoder->input[0]);
|
||||
CHECK_STATUS(status, "failed to commit format");
|
||||
|
||||
/* Our decoder can do internal colour conversion, ask for a conversion to RGB565 */
|
||||
MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format;
|
||||
format_out->encoding = MMAL_ENCODING_RGB16;
|
||||
status = mmal_port_format_commit(decoder->output[0]);
|
||||
CHECK_STATUS(status, "failed to commit format");
|
||||
|
||||
/* Display the output port format */
|
||||
fprintf(stderr, "%s\n", decoder->output[0]->name);
|
||||
fprintf(stderr, " type: %i, fourcc: %4.4s\n", format_out->type, (char *)&format_out->encoding);
|
||||
fprintf(stderr, " bitrate: %i, framed: %i\n", format_out->bitrate,
|
||||
!!(format_out->flags & MMAL_ES_FORMAT_FLAG_FRAMED));
|
||||
fprintf(stderr, " extra data: %i, %p\n", format_out->extradata_size, format_out->extradata);
|
||||
fprintf(stderr, " width: %i, height: %i, (%i,%i,%i,%i)\n",
|
||||
format_out->es->video.width, format_out->es->video.height,
|
||||
format_out->es->video.crop.x, format_out->es->video.crop.y,
|
||||
format_out->es->video.crop.width, format_out->es->video.crop.height);
|
||||
|
||||
/* The format of both ports is now set so we can get their buffer requirements and create
|
||||
* our buffer headers. We use the buffer pool API to create these. */
|
||||
decoder->input[0]->buffer_num = decoder->input[0]->buffer_num_min;
|
||||
decoder->input[0]->buffer_size = decoder->input[0]->buffer_size_min;
|
||||
decoder->output[0]->buffer_num = decoder->output[0]->buffer_num_min;
|
||||
decoder->output[0]->buffer_size = decoder->output[0]->buffer_size_min;
|
||||
pool_in = mmal_pool_create(decoder->input[0]->buffer_num,
|
||||
decoder->input[0]->buffer_size);
|
||||
pool_out = mmal_pool_create(decoder->output[0]->buffer_num,
|
||||
decoder->output[0]->buffer_size);
|
||||
|
||||
/* Create a queue to store our decoded video frames. The callback we will get when
|
||||
* a frame has been decoded will put the frame into this queue. */
|
||||
context.queue = mmal_queue_create();
|
||||
|
||||
/* Store a reference to our context in each port (will be used during callbacks) */
|
||||
decoder->input[0]->userdata = (void *)&context;
|
||||
decoder->output[0]->userdata = (void *)&context;
|
||||
|
||||
/* Enable all the input port and the output port.
|
||||
* The callback specified here is the function which will be called when the buffer header
|
||||
* we sent to the component has been processed. */
|
||||
status = mmal_port_enable(decoder->input[0], input_callback);
|
||||
CHECK_STATUS(status, "failed to enable input port");
|
||||
status = mmal_port_enable(decoder->output[0], output_callback);
|
||||
CHECK_STATUS(status, "failed to enable output port");
|
||||
|
||||
/* Component won't start processing data until it is enabled. */
|
||||
status = mmal_component_enable(decoder);
|
||||
CHECK_STATUS(status, "failed to enable component");
|
||||
|
||||
/* Start decoding */
|
||||
fprintf(stderr, "start decoding\n");
|
||||
|
||||
/* This is the main processing loop */
|
||||
for (count = 0; !eos_received && count < 500; count++)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
|
||||
/* Wait for buffer headers to be available on either of the decoder ports */
|
||||
vcos_semaphore_wait(&context.semaphore);
|
||||
|
||||
/* Check for errors */
|
||||
if (context.status != MMAL_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Send data to decode to the input port of the video decoder */
|
||||
if (!eos_sent && (buffer = mmal_queue_get(pool_in->queue)) != NULL)
|
||||
{
|
||||
SOURCE_READ_DATA_INTO_BUFFER(buffer);
|
||||
if(!buffer->length) eos_sent = MMAL_TRUE;
|
||||
|
||||
buffer->flags = buffer->length ? 0 : MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
buffer->pts = buffer->dts = MMAL_TIME_UNKNOWN;
|
||||
fprintf(stderr, "sending %i bytes\n", (int)buffer->length);
|
||||
status = mmal_port_send_buffer(decoder->input[0], buffer);
|
||||
CHECK_STATUS(status, "failed to send buffer");
|
||||
}
|
||||
|
||||
/* Get our decoded frames */
|
||||
while ((buffer = mmal_queue_get(context.queue)) != NULL)
|
||||
{
|
||||
/* We have a frame, do something with it (why not display it for instance?).
|
||||
* Once we're done with it, we release it. It will automatically go back
|
||||
* to its original pool so it can be reused for a new video frame.
|
||||
*/
|
||||
eos_received = buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS;
|
||||
|
||||
if (buffer->cmd)
|
||||
fprintf(stderr, "received event %4.4s", (char *)&buffer->cmd);
|
||||
else
|
||||
fprintf(stderr, "decoded frame (flags %x)\n", buffer->flags);
|
||||
mmal_buffer_header_release(buffer);
|
||||
}
|
||||
|
||||
/* Send empty buffers to the output port of the decoder */
|
||||
while ((buffer = mmal_queue_get(pool_out->queue)) != NULL)
|
||||
{
|
||||
status = mmal_port_send_buffer(decoder->output[0], buffer);
|
||||
CHECK_STATUS(status, "failed to send buffer");
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop decoding */
|
||||
fprintf(stderr, "stop decoding\n");
|
||||
|
||||
/* Stop everything. Not strictly necessary since mmal_component_destroy()
|
||||
* will do that anyway */
|
||||
mmal_port_disable(decoder->input[0]);
|
||||
mmal_port_disable(decoder->output[0]);
|
||||
mmal_component_disable(decoder);
|
||||
|
||||
error:
|
||||
/* Cleanup everything */
|
||||
if (decoder)
|
||||
mmal_component_destroy(decoder);
|
||||
if (pool_in)
|
||||
mmal_pool_destroy(pool_in);
|
||||
if (pool_out)
|
||||
mmal_pool_destroy(pool_out);
|
||||
if (context.queue)
|
||||
mmal_queue_destroy(context.queue);
|
||||
|
||||
SOURCE_CLOSE();
|
||||
vcos_semaphore_delete(&context.semaphore);
|
||||
return status == MMAL_SUCCESS ? 0 : -1;
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "util/mmal_connection.h"
|
||||
#include "util/mmal_default_components.h"
|
||||
#include "util/mmal_util_params.h"
|
||||
#include "interface/vcos/vcos.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define CHECK_STATUS(status, msg) if (status != MMAL_SUCCESS) { fprintf(stderr, msg"\n"); goto error; }
|
||||
|
||||
/** Context for our application */
|
||||
static struct CONTEXT_T {
|
||||
VCOS_SEMAPHORE_T semaphore;
|
||||
MMAL_STATUS_T status;
|
||||
MMAL_BOOL_T eos;
|
||||
} context;
|
||||
|
||||
/** Callback from a control port. Error and EOS events stop playback. */
|
||||
static void control_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
|
||||
{
|
||||
struct CONTEXT_T *ctx = (struct CONTEXT_T *)port->userdata;
|
||||
|
||||
if (buffer->cmd == MMAL_EVENT_ERROR)
|
||||
ctx->status = *(MMAL_STATUS_T *)buffer->data;
|
||||
else if (buffer->cmd == MMAL_EVENT_EOS)
|
||||
ctx->eos = MMAL_TRUE;
|
||||
|
||||
mmal_buffer_header_release(buffer);
|
||||
|
||||
/* The processing is done in our main thread */
|
||||
vcos_semaphore_post(&ctx->semaphore);
|
||||
}
|
||||
|
||||
/** Callback from the connection. Buffer is available. */
|
||||
static void connection_callback(MMAL_CONNECTION_T *connection)
|
||||
{
|
||||
struct CONTEXT_T *ctx = (struct CONTEXT_T *)connection->user_data;
|
||||
|
||||
/* The processing is done in our main thread */
|
||||
vcos_semaphore_post(&ctx->semaphore);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
MMAL_COMPONENT_T *reader = 0, *decoder = 0, *renderer = 0;
|
||||
MMAL_CONNECTION_T *connection[2] = {0};
|
||||
unsigned int i, count, connection_num = vcos_countof(connection);
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vcos_semaphore_create(&context.semaphore, "example", 1);
|
||||
|
||||
/* Create the components */
|
||||
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CONTAINER_READER, &reader);
|
||||
CHECK_STATUS(status, "failed to create reader");
|
||||
reader->control->userdata = (void *)&context;
|
||||
status = mmal_port_enable(reader->control, control_callback);
|
||||
CHECK_STATUS(status, "failed to enable control port");
|
||||
status = mmal_component_enable(reader);
|
||||
CHECK_STATUS(status, "failed to enable component");
|
||||
|
||||
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &decoder);
|
||||
CHECK_STATUS(status, "failed to create decoder");
|
||||
decoder->control->userdata = (void *)&context;
|
||||
status = mmal_port_enable(decoder->control, control_callback);
|
||||
CHECK_STATUS(status, "failed to enable control port");
|
||||
status = mmal_component_enable(decoder);
|
||||
CHECK_STATUS(status, "failed to enable component");
|
||||
|
||||
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &renderer);
|
||||
CHECK_STATUS(status, "failed to create renderer");
|
||||
renderer->control->userdata = (void *)&context;
|
||||
status = mmal_port_enable(renderer->control, control_callback);
|
||||
CHECK_STATUS(status, "failed to enable control port");
|
||||
status = mmal_component_enable(renderer);
|
||||
CHECK_STATUS(status, "failed to enable component");
|
||||
|
||||
/* Configure the reader using the given URI */
|
||||
status = mmal_util_port_set_uri(reader->control, argv[1]);
|
||||
CHECK_STATUS(status, "failed to set uri");
|
||||
|
||||
/* Create the connections between the components */
|
||||
status = mmal_connection_create(&connection[0], reader->output[0], decoder->input[0], 0);
|
||||
CHECK_STATUS(status, "failed to create connection between reader / decoder");
|
||||
connection[0]->user_data = &context;
|
||||
connection[0]->callback = connection_callback;
|
||||
status = mmal_connection_create(&connection[1], decoder->output[0], renderer->input[0], 0);
|
||||
CHECK_STATUS(status, "failed to create connection between decoder / renderer");
|
||||
connection[1]->user_data = &context;
|
||||
connection[1]->callback = connection_callback;
|
||||
|
||||
/* Enable all our connections */
|
||||
for (i = connection_num; i; i--)
|
||||
{
|
||||
status = mmal_connection_enable(connection[i-1]);
|
||||
CHECK_STATUS(status, "failed to enable connection");
|
||||
}
|
||||
|
||||
/* Start playback */
|
||||
fprintf(stderr, "start playback\n");
|
||||
|
||||
/* This is the main processing loop */
|
||||
for (count = 0; count < 500; count++)
|
||||
{
|
||||
MMAL_BUFFER_HEADER_T *buffer;
|
||||
vcos_semaphore_wait(&context.semaphore);
|
||||
|
||||
/* Check for errors */
|
||||
status = context.status;
|
||||
CHECK_STATUS(status, "error during playback");
|
||||
|
||||
/* Check for end of stream */
|
||||
if (context.eos)
|
||||
break;
|
||||
|
||||
/* Handle buffers for all our connections */
|
||||
for (i = 0; i < connection_num; i++)
|
||||
{
|
||||
if (connection[i]->flags & MMAL_CONNECTION_FLAG_TUNNELLING)
|
||||
continue; /* Nothing else to do in tunnelling mode */
|
||||
|
||||
/* Send empty buffers to the output port of the connection */
|
||||
while ((buffer = mmal_queue_get(connection[i]->pool->queue)) != NULL)
|
||||
{
|
||||
status = mmal_port_send_buffer(connection[i]->out, buffer);
|
||||
CHECK_STATUS(status, "failed to send buffer");
|
||||
}
|
||||
|
||||
/* Send any queued buffer to the next component */
|
||||
while ((buffer = mmal_queue_get(connection[i]->queue)) != NULL)
|
||||
{
|
||||
status = mmal_port_send_buffer(connection[i]->in, buffer);
|
||||
CHECK_STATUS(status, "failed to send buffer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop everything */
|
||||
fprintf(stderr, "stop playback\n");
|
||||
for (i = 0; i < connection_num; i++)
|
||||
{
|
||||
mmal_connection_disable(connection[i]);
|
||||
}
|
||||
|
||||
error:
|
||||
/* Cleanup everything */
|
||||
for (i = 0; i < connection_num; i++)
|
||||
{
|
||||
if (connection[i])
|
||||
mmal_connection_destroy(connection[i]);
|
||||
}
|
||||
if (reader)
|
||||
mmal_component_destroy(reader);
|
||||
if (decoder)
|
||||
mmal_component_destroy(decoder);
|
||||
if (renderer)
|
||||
mmal_component_destroy(renderer);
|
||||
|
||||
vcos_semaphore_delete(&context.semaphore);
|
||||
return status == MMAL_SUCCESS ? 0 : -1;
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mmal.h"
|
||||
#include "util/mmal_graph.h"
|
||||
#include "util/mmal_default_components.h"
|
||||
#include "util/mmal_util_params.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define CHECK_STATUS(status, msg) if (status != MMAL_SUCCESS) { fprintf(stderr, msg"\n"); goto error; }
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MMAL_STATUS_T status;
|
||||
MMAL_GRAPH_T *graph = 0;
|
||||
MMAL_COMPONENT_T *reader = 0, *decoder = 0, *renderer = 0;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "invalid arguments\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create the graph */
|
||||
status = mmal_graph_create(&graph, 0);
|
||||
CHECK_STATUS(status, "failed to create graph");
|
||||
|
||||
/* Add the components */
|
||||
status = mmal_graph_new_component(graph, MMAL_COMPONENT_DEFAULT_CONTAINER_READER, &reader);
|
||||
CHECK_STATUS(status, "failed to create reader");
|
||||
|
||||
status = mmal_graph_new_component(graph, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &decoder);
|
||||
CHECK_STATUS(status, "failed to create decoder");
|
||||
|
||||
status = mmal_graph_new_component(graph, MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &renderer);
|
||||
CHECK_STATUS(status, "failed to create renderer");
|
||||
|
||||
/* Configure the reader using the given URI */
|
||||
status = mmal_util_port_set_uri(reader->control, argv[1]);
|
||||
CHECK_STATUS(status, "failed to set uri");
|
||||
|
||||
/* connect them up - this propagates port settings from outputs to inputs */
|
||||
status = mmal_graph_new_connection(graph, reader->output[0], decoder->input[0], 0, NULL);
|
||||
CHECK_STATUS(status, "failed to connect reader to decoder");
|
||||
status = mmal_graph_new_connection(graph, decoder->output[0], renderer->input[0], 0, NULL);
|
||||
CHECK_STATUS(status, "failed to connect decoder to renderer");
|
||||
|
||||
/* Start playback */
|
||||
fprintf(stderr, "start playback\n");
|
||||
status = mmal_graph_enable(graph, NULL, NULL);
|
||||
CHECK_STATUS(status, "failed to enable graph");
|
||||
|
||||
sleep(5);
|
||||
|
||||
/* Stop everything */
|
||||
fprintf(stderr, "stop playback\n");
|
||||
mmal_graph_disable(graph);
|
||||
|
||||
error:
|
||||
/* Cleanup everything */
|
||||
if (reader)
|
||||
mmal_component_release(reader);
|
||||
if (decoder)
|
||||
mmal_component_release(decoder);
|
||||
if (renderer)
|
||||
mmal_component_release(renderer);
|
||||
if (graph)
|
||||
mmal_graph_destroy(graph);
|
||||
|
||||
return status == MMAL_SUCCESS ? 0 : -1;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
add_library (mmal_util ${LIBRARY_TYPE}
|
||||
mmal_il.c
|
||||
mmal_util.c
|
||||
mmal_connection.c
|
||||
mmal_graph.c
|
||||
mmal_list.c
|
||||
mmal_param_convert.c
|
||||
mmal_util_params.c
|
||||
mmal_component_wrapper.c
|
||||
mmal_util_rational.c
|
||||
)
|
||||
|
||||
target_link_libraries (mmal_util vcos)
|
||||
|
||||
install(TARGETS mmal_util DESTINATION lib)
|
||||
install(FILES
|
||||
mmal_component_wrapper.h
|
||||
mmal_connection.h
|
||||
mmal_default_components.h
|
||||
mmal_graph.h
|
||||
mmal_il.h
|
||||
mmal_list.h
|
||||
mmal_param_convert.h
|
||||
mmal_util.h
|
||||
mmal_util_params.h
|
||||
mmal_util_rational.h
|
||||
DESTINATION include/interface/mmal/util
|
||||
)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user