@@ -1,3 +1,7 @@ | |||||
#hello_video | |||||
*.a | |||||
*.bin | |||||
omxplayer-dist.tgz* | omxplayer-dist.tgz* | ||||
# Byte-compiled / optimized / DLL files | # Byte-compiled / optimized / DLL files | ||||
__pycache__/ | __pycache__/ | ||||
@@ -1,2 +1,11 @@ | |||||
# pi_video_looper | # pi_video_looper | ||||
Application to turn your Raspberry Pi into a dedicated looping video playback device, good for art installations, information displays, or just playing cat videos all day. | Application to turn your Raspberry Pi into a dedicated looping video playback device, good for art installations, information displays, or just playing cat videos all day. | ||||
# Raspberry Pi hello video | |||||
Fork of hello_video example from Raspberry Pi sample code that provides seamless looping of a raw H264 video stream. Original code is available at: https://github.com/raspberrypi/userland/tree/master/host_applications/linux/apps/hello_pi | |||||
Build by executing `hv_rebuild.sh`. | |||||
Install by executing `sudo make install` inside hello_video directory. | |||||
Run by executing `hello_video.bin`. With no parameters the usage will be printed. |
@@ -12,13 +12,18 @@ fi | |||||
echo "Installing dependencies..." | echo "Installing dependencies..." | ||||
echo "==========================" | echo "==========================" | ||||
apt-get update | apt-get update | ||||
apt-get -y install build-essential python-dev python-pip python-pygame supervisor git omxplayer | |||||
apt-get -y install build-essential python-dev python-pip python-pygame supervisor git omxplayer samba samba-common-bin | |||||
echo "Installing hello_video..." | echo "Installing hello_video..." | ||||
echo "=========================" | echo "=========================" | ||||
git clone https://github.com/adafruit/pi_hello_video.git | |||||
cd pi_hello_video | cd pi_hello_video | ||||
./rebuild.sh | |||||
make -C libs/ilclient clean | |||||
make -C hello_video clean | |||||
make -C libs/ilclient | |||||
make -C hello_video | |||||
cd hello_video | cd hello_video | ||||
make install | make install | ||||
cd ../.. | cd ../.. | ||||
@@ -0,0 +1,29 @@ | |||||
CFLAGS+=-DSTANDALONE -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS -DTARGET_POSIX -D_LINUX -fPIC -DPIC -D_REENTRANT -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -U_FORTIFY_SOURCE -Wall -g -DHAVE_LIBOPENMAX=2 -DOMX -DOMX_SKIP64BIT -ftree-vectorize -pipe -DUSE_EXTERNAL_OMX -DHAVE_LIBBCM_HOST -DUSE_EXTERNAL_LIBBCM_HOST -DUSE_VCHIQ_ARM -Wno-psabi | |||||
LDFLAGS+=-L$(SDKSTAGE)/opt/vc/lib/ -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt -lm -L../libs/ilclient -L../libs/vgfont | |||||
INCLUDES+=-I$(SDKSTAGE)/opt/vc/include/ -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads -I$(SDKSTAGE)/opt/vc/include/interface/vmcs_host/linux -I./ -I../libs/ilclient -I../libs/vgfont | |||||
all: $(BIN) $(LIB) | |||||
%.o: %.c | |||||
@rm -f $@ | |||||
$(CC) $(CFLAGS) $(INCLUDES) -g -c $< -o $@ -Wno-deprecated-declarations | |||||
%.o: %.cpp | |||||
@rm -f $@ | |||||
$(CXX) $(CFLAGS) $(INCLUDES) -g -c $< -o $@ -Wno-deprecated-declarations | |||||
%.bin: $(OBJS) | |||||
$(CC) -o $@ -Wl,--whole-archive $(OBJS) $(LDFLAGS) -Wl,--no-whole-archive -rdynamic | |||||
%.a: $(OBJS) | |||||
$(AR) r $@ $^ | |||||
clean: | |||||
for i in $(OBJS); do (if test -e "$$i"; then ( rm $$i ); fi ); done | |||||
@rm -f $(BIN) $(LIB) | |||||
install: | |||||
cp $(BIN) /usr/local/bin/ |
@@ -0,0 +1,6 @@ | |||||
OBJS=video.o | |||||
BIN=hello_video.bin | |||||
LDFLAGS+=-lilclient | |||||
include ../Makefile.include | |||||
@@ -0,0 +1 @@ | |||||
The video clip test.h264 is (c) copyright 2008, Blender Foundation / www.bigbuckbunny.org |
@@ -0,0 +1,246 @@ | |||||
/* | |||||
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. | |||||
*/ | |||||
// Video deocode demo using OpenMAX IL though the ilcient helper library | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include "bcm_host.h" | |||||
#include "ilclient.h" | |||||
static int video_decode_test(char *filename, int loop) | |||||
{ | |||||
OMX_VIDEO_PARAM_PORTFORMATTYPE format; | |||||
OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; | |||||
COMPONENT_T *video_decode = NULL, *video_scheduler = NULL, *video_render = NULL, *clock = NULL; | |||||
COMPONENT_T *list[5]; | |||||
TUNNEL_T tunnel[4]; | |||||
ILCLIENT_T *client; | |||||
FILE *in; | |||||
int status = 0; | |||||
unsigned int data_len = 0; | |||||
memset(list, 0, sizeof(list)); | |||||
memset(tunnel, 0, sizeof(tunnel)); | |||||
if((in = fopen(filename, "rb")) == NULL) | |||||
return -2; | |||||
if((client = ilclient_init()) == NULL) | |||||
{ | |||||
fclose(in); | |||||
return -3; | |||||
} | |||||
if(OMX_Init() != OMX_ErrorNone) | |||||
{ | |||||
ilclient_destroy(client); | |||||
fclose(in); | |||||
return -4; | |||||
} | |||||
// create video_decode | |||||
if(ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0) | |||||
status = -14; | |||||
list[0] = video_decode; | |||||
// create video_render | |||||
if(status == 0 && ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS) != 0) | |||||
status = -14; | |||||
list[1] = video_render; | |||||
// create clock | |||||
if(status == 0 && ilclient_create_component(client, &clock, "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0) | |||||
status = -14; | |||||
list[2] = clock; | |||||
memset(&cstate, 0, sizeof(cstate)); | |||||
cstate.nSize = sizeof(cstate); | |||||
cstate.nVersion.nVersion = OMX_VERSION; | |||||
cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; | |||||
cstate.nWaitMask = 1; | |||||
if(clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(clock), OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone) | |||||
status = -13; | |||||
// create video_scheduler | |||||
if(status == 0 && ilclient_create_component(client, &video_scheduler, "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS) != 0) | |||||
status = -14; | |||||
list[3] = video_scheduler; | |||||
set_tunnel(tunnel, video_decode, 131, video_scheduler, 10); | |||||
set_tunnel(tunnel+1, video_scheduler, 11, video_render, 90); | |||||
set_tunnel(tunnel+2, clock, 80, video_scheduler, 12); | |||||
// setup clock tunnel first | |||||
if(status == 0 && ilclient_setup_tunnel(tunnel+2, 0, 0) != 0) | |||||
status = -15; | |||||
else | |||||
ilclient_change_component_state(clock, OMX_StateExecuting); | |||||
if(status == 0) | |||||
ilclient_change_component_state(video_decode, OMX_StateIdle); | |||||
memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); | |||||
format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); | |||||
format.nVersion.nVersion = OMX_VERSION; | |||||
format.nPortIndex = 130; | |||||
format.eCompressionFormat = OMX_VIDEO_CodingAVC; | |||||
if(status == 0 && | |||||
OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format) == OMX_ErrorNone && | |||||
ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0) | |||||
{ | |||||
OMX_BUFFERHEADERTYPE *buf; | |||||
int port_settings_changed = 0; | |||||
int first_packet = 1; | |||||
ilclient_change_component_state(video_decode, OMX_StateExecuting); | |||||
while((buf = ilclient_get_input_buffer(video_decode, 130, 1)) != NULL) | |||||
{ | |||||
// feed data and wait until we get port settings changed | |||||
unsigned char *dest = buf->pBuffer; | |||||
data_len += fread(dest, 1, buf->nAllocLen-data_len, in); | |||||
if(port_settings_changed == 0 && | |||||
((data_len > 0 && ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) || | |||||
(data_len == 0 && ilclient_wait_for_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1, | |||||
ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000) == 0))) | |||||
{ | |||||
port_settings_changed = 1; | |||||
if(ilclient_setup_tunnel(tunnel, 0, 0) != 0) | |||||
{ | |||||
status = -7; | |||||
break; | |||||
} | |||||
ilclient_change_component_state(video_scheduler, OMX_StateExecuting); | |||||
// now setup tunnel to video_render | |||||
if(ilclient_setup_tunnel(tunnel+1, 0, 1000) != 0) | |||||
{ | |||||
status = -12; | |||||
break; | |||||
} | |||||
ilclient_change_component_state(video_render, OMX_StateExecuting); | |||||
} | |||||
if(!data_len) { | |||||
// Finished reading the file, either loop or exit. | |||||
if (loop) { | |||||
fseek(in, 0, SEEK_SET); | |||||
} | |||||
else { | |||||
break; | |||||
} | |||||
} | |||||
buf->nFilledLen = data_len; | |||||
data_len = 0; | |||||
buf->nOffset = 0; | |||||
if(first_packet) | |||||
{ | |||||
buf->nFlags = OMX_BUFFERFLAG_STARTTIME; | |||||
first_packet = 0; | |||||
} | |||||
else | |||||
buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN; | |||||
if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone) | |||||
{ | |||||
status = -6; | |||||
break; | |||||
} | |||||
} | |||||
buf->nFilledLen = 0; | |||||
buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS; | |||||
if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone) | |||||
status = -20; | |||||
// wait for EOS from render | |||||
ilclient_wait_for_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0, | |||||
ILCLIENT_BUFFER_FLAG_EOS, 10000); | |||||
// need to flush the renderer to allow video_decode to disable its input port | |||||
ilclient_flush_tunnels(tunnel, 0); | |||||
ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL); | |||||
} | |||||
fclose(in); | |||||
ilclient_disable_tunnel(tunnel); | |||||
ilclient_disable_tunnel(tunnel+1); | |||||
ilclient_disable_tunnel(tunnel+2); | |||||
ilclient_teardown_tunnels(tunnel); | |||||
ilclient_state_transition(list, OMX_StateIdle); | |||||
ilclient_state_transition(list, OMX_StateLoaded); | |||||
ilclient_cleanup_components(list); | |||||
OMX_Deinit(); | |||||
ilclient_destroy(client); | |||||
return status; | |||||
} | |||||
void error_usage(char* name) { | |||||
printf("Usage: %s [--loop] <filename>\n", name); | |||||
exit(1); | |||||
} | |||||
int main (int argc, char **argv) | |||||
{ | |||||
int loop = 0; | |||||
if (argc < 2 || argc > 3) { | |||||
error_usage(argv[0]); | |||||
} | |||||
// Check optional parameter. | |||||
if (argc == 3) { | |||||
// Check for loop parameter. | |||||
if (strcmp(argv[1], "--loop") == 0) { | |||||
loop = 1; | |||||
} | |||||
// Error unknown parameter. | |||||
else { | |||||
error_usage(argv[0]); | |||||
} | |||||
} | |||||
bcm_host_init(); | |||||
return video_decode_test(argv[argc-1], loop); | |||||
} | |||||
@@ -0,0 +1,5 @@ | |||||
OBJS=ilclient.o ilcore.o | |||||
LIB=libilclient.a | |||||
include ../../Makefile.include | |||||
@@ -0,0 +1,308 @@ | |||||
/* | |||||
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 | |||||
* | |||||
* \brief Host core implementation. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdarg.h> | |||||
//includes | |||||
#include <memory.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include "IL/OMX_Component.h" | |||||
#include "interface/vcos/vcos.h" | |||||
#include "interface/vmcs_host/vcilcs.h" | |||||
#include "interface/vmcs_host/vchost.h" | |||||
#include "interface/vmcs_host/vcilcs_common.h" | |||||
static int coreInit = 0; | |||||
static int nActiveHandles = 0; | |||||
static ILCS_SERVICE_T *ilcs_service = NULL; | |||||
static VCOS_MUTEX_T lock; | |||||
static VCOS_ONCE_T once = VCOS_ONCE_INIT; | |||||
/* Atomic creation of lock protecting shared state */ | |||||
static void initOnce(void) | |||||
{ | |||||
VCOS_STATUS_T status; | |||||
status = vcos_mutex_create(&lock, VCOS_FUNCTION); | |||||
vcos_demand(status == VCOS_SUCCESS); | |||||
} | |||||
/* OMX_Init */ | |||||
OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void) | |||||
{ | |||||
VCOS_STATUS_T status; | |||||
OMX_ERRORTYPE err = OMX_ErrorNone; | |||||
status = vcos_once(&once, initOnce); | |||||
vcos_demand(status == VCOS_SUCCESS); | |||||
vcos_mutex_lock(&lock); | |||||
if(coreInit == 0) | |||||
{ | |||||
// we need to connect via an ILCS connection to VideoCore | |||||
VCHI_INSTANCE_T initialise_instance; | |||||
VCHI_CONNECTION_T *connection; | |||||
ILCS_CONFIG_T config; | |||||
vc_host_get_vchi_state(&initialise_instance, &connection); | |||||
vcilcs_config(&config); | |||||
ilcs_service = ilcs_init((VCHIQ_INSTANCE_T) initialise_instance, (void **) &connection, &config, 0); | |||||
if(ilcs_service == NULL) | |||||
{ | |||||
err = OMX_ErrorHardware; | |||||
goto end; | |||||
} | |||||
coreInit = 1; | |||||
} | |||||
else | |||||
coreInit++; | |||||
end: | |||||
vcos_mutex_unlock(&lock); | |||||
return err; | |||||
} | |||||
/* OMX_Deinit */ | |||||
OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void) | |||||
{ | |||||
if(coreInit == 0) // || (coreInit == 1 && nActiveHandles > 0)) | |||||
return OMX_ErrorNotReady; | |||||
vcos_mutex_lock(&lock); | |||||
coreInit--; | |||||
if(coreInit == 0) | |||||
{ | |||||
// we need to teardown the ILCS connection to VideoCore | |||||
ilcs_deinit(ilcs_service); | |||||
ilcs_service = NULL; | |||||
} | |||||
vcos_mutex_unlock(&lock); | |||||
return OMX_ErrorNone; | |||||
} | |||||
/* OMX_ComponentNameEnum */ | |||||
OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum( | |||||
OMX_OUT OMX_STRING cComponentName, | |||||
OMX_IN OMX_U32 nNameLength, | |||||
OMX_IN OMX_U32 nIndex) | |||||
{ | |||||
if(ilcs_service == NULL) | |||||
return OMX_ErrorBadParameter; | |||||
return vcil_out_component_name_enum(ilcs_get_common(ilcs_service), cComponentName, nNameLength, nIndex); | |||||
} | |||||
/* OMX_GetHandle */ | |||||
OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( | |||||
OMX_OUT OMX_HANDLETYPE* pHandle, | |||||
OMX_IN OMX_STRING cComponentName, | |||||
OMX_IN OMX_PTR pAppData, | |||||
OMX_IN OMX_CALLBACKTYPE* pCallBacks) | |||||
{ | |||||
OMX_ERRORTYPE eError; | |||||
OMX_COMPONENTTYPE *pComp; | |||||
OMX_HANDLETYPE hHandle = 0; | |||||
if (pHandle == NULL || cComponentName == NULL || pCallBacks == NULL || ilcs_service == NULL) | |||||
{ | |||||
if(pHandle) | |||||
*pHandle = NULL; | |||||
return OMX_ErrorBadParameter; | |||||
} | |||||
{ | |||||
pComp = (OMX_COMPONENTTYPE *)malloc(sizeof(OMX_COMPONENTTYPE)); | |||||
if (!pComp) | |||||
{ | |||||
vcos_assert(0); | |||||
return OMX_ErrorInsufficientResources; | |||||
} | |||||
memset(pComp, 0, sizeof(OMX_COMPONENTTYPE)); | |||||
hHandle = (OMX_HANDLETYPE)pComp; | |||||
pComp->nSize = sizeof(OMX_COMPONENTTYPE); | |||||
pComp->nVersion.nVersion = OMX_VERSION; | |||||
eError = vcil_out_create_component(ilcs_get_common(ilcs_service), hHandle, cComponentName); | |||||
if (eError == OMX_ErrorNone) { | |||||
// Check that all function pointers have been filled in. | |||||
// All fields should be non-zero. | |||||
int i; | |||||
uint32_t *p = (uint32_t *) pComp; | |||||
for(i=0; i<sizeof(OMX_COMPONENTTYPE)>>2; i++) | |||||
if(*p++ == 0) | |||||
eError = OMX_ErrorInvalidComponent; | |||||
if(eError != OMX_ErrorNone && pComp->ComponentDeInit) | |||||
pComp->ComponentDeInit(hHandle); | |||||
} | |||||
if (eError == OMX_ErrorNone) { | |||||
eError = pComp->SetCallbacks(hHandle,pCallBacks,pAppData); | |||||
if (eError != OMX_ErrorNone) | |||||
pComp->ComponentDeInit(hHandle); | |||||
} | |||||
if (eError == OMX_ErrorNone) { | |||||
*pHandle = hHandle; | |||||
} | |||||
else { | |||||
*pHandle = NULL; | |||||
free(pComp); | |||||
} | |||||
} | |||||
if (eError == OMX_ErrorNone) { | |||||
vcos_mutex_lock(&lock); | |||||
nActiveHandles++; | |||||
vcos_mutex_unlock(&lock); | |||||
} | |||||
return eError; | |||||
} | |||||
/* OMX_FreeHandle */ | |||||
OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( | |||||
OMX_IN OMX_HANDLETYPE hComponent) | |||||
{ | |||||
OMX_ERRORTYPE eError = OMX_ErrorNone; | |||||
OMX_COMPONENTTYPE *pComp; | |||||
if (hComponent == NULL || ilcs_service == NULL) | |||||
return OMX_ErrorBadParameter; | |||||
pComp = (OMX_COMPONENTTYPE*)hComponent; | |||||
if (ilcs_service == NULL) | |||||
return OMX_ErrorBadParameter; | |||||
eError = (pComp->ComponentDeInit)(hComponent); | |||||
if (eError == OMX_ErrorNone) { | |||||
vcos_mutex_lock(&lock); | |||||
--nActiveHandles; | |||||
vcos_mutex_unlock(&lock); | |||||
free(pComp); | |||||
} | |||||
vcos_assert(nActiveHandles >= 0); | |||||
return eError; | |||||
} | |||||
/* OMX_SetupTunnel */ | |||||
OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel( | |||||
OMX_IN OMX_HANDLETYPE hOutput, | |||||
OMX_IN OMX_U32 nPortOutput, | |||||
OMX_IN OMX_HANDLETYPE hInput, | |||||
OMX_IN OMX_U32 nPortInput) | |||||
{ | |||||
OMX_ERRORTYPE eError = OMX_ErrorNone; | |||||
OMX_COMPONENTTYPE *pCompIn, *pCompOut; | |||||
OMX_TUNNELSETUPTYPE oTunnelSetup; | |||||
if ((hOutput == NULL && hInput == NULL) || ilcs_service == NULL) | |||||
return OMX_ErrorBadParameter; | |||||
oTunnelSetup.nTunnelFlags = 0; | |||||
oTunnelSetup.eSupplier = OMX_BufferSupplyUnspecified; | |||||
pCompOut = (OMX_COMPONENTTYPE*)hOutput; | |||||
if (hOutput){ | |||||
eError = pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, hInput, nPortInput, &oTunnelSetup); | |||||
} | |||||
if (eError == OMX_ErrorNone && hInput) { | |||||
pCompIn = (OMX_COMPONENTTYPE*)hInput; | |||||
eError = pCompIn->ComponentTunnelRequest(hInput, nPortInput, hOutput, nPortOutput, &oTunnelSetup); | |||||
if (eError != OMX_ErrorNone && hOutput) { | |||||
/* cancel tunnel request on output port since input port failed */ | |||||
pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, NULL, 0, NULL); | |||||
} | |||||
} | |||||
return eError; | |||||
} | |||||
/* OMX_GetComponentsOfRole */ | |||||
OMX_ERRORTYPE OMX_GetComponentsOfRole ( | |||||
OMX_IN OMX_STRING role, | |||||
OMX_INOUT OMX_U32 *pNumComps, | |||||
OMX_INOUT OMX_U8 **compNames) | |||||
{ | |||||
OMX_ERRORTYPE eError = OMX_ErrorNone; | |||||
*pNumComps = 0; | |||||
return eError; | |||||
} | |||||
/* OMX_GetRolesOfComponent */ | |||||
OMX_ERRORTYPE OMX_GetRolesOfComponent ( | |||||
OMX_IN OMX_STRING compName, | |||||
OMX_INOUT OMX_U32 *pNumRoles, | |||||
OMX_OUT OMX_U8 **roles) | |||||
{ | |||||
OMX_ERRORTYPE eError = OMX_ErrorNone; | |||||
*pNumRoles = 0; | |||||
return eError; | |||||
} | |||||
/* OMX_GetDebugInformation */ | |||||
OMX_ERRORTYPE OMX_GetDebugInformation ( | |||||
OMX_OUT OMX_STRING debugInfo, | |||||
OMX_INOUT OMX_S32 *pLen) | |||||
{ | |||||
if(ilcs_service == NULL) | |||||
return OMX_ErrorBadParameter; | |||||
return vcil_out_get_debug_information(ilcs_get_common(ilcs_service), debugInfo, pLen); | |||||
} | |||||
/* File EOF */ | |||||
@@ -2,12 +2,12 @@ from ez_setup import use_setuptools | |||||
use_setuptools() | use_setuptools() | ||||
from setuptools import setup, find_packages | from setuptools import setup, find_packages | ||||
setup(name = 'Adafruit_Video_Looper', | |||||
setup(name = 'NURD_Video_Looper', | |||||
version = '1.0.0', | version = '1.0.0', | ||||
author = 'Tony DiCola', | |||||
author_email = 'tdicola@adafruit.com', | |||||
description = 'Application to turn your Raspberry Pi into a dedicated looping video playback device, good for art installations, information displays, or just playing cat videos all day.', | |||||
author = 'Nurds', | |||||
author_email = 'ben@nurd.me', | |||||
description = 'Application to turn your Raspberry Pi Zero into a dedicated looping video playback device', | |||||
license = 'GNU GPLv2', | license = 'GNU GPLv2', | ||||
url = 'https://github.com/adafruit/pi_video_looper', | |||||
url = 'https://github.com/FRCTeam3255/pi_video_looper', | |||||
install_requires = ['pyudev'], | install_requires = ['pyudev'], | ||||
packages = find_packages()) | packages = find_packages()) |
@@ -20,8 +20,8 @@ video_player = omxplayer | |||||
# directory option will search only a specified directory on the SD card for | # directory option will search only a specified directory on the SD card for | ||||
# movie files. Note that you change the directory by modifying the setting in | # movie files. Note that you change the directory by modifying the setting in | ||||
# the [directory] section below. The default is usb_drive. | # the [directory] section below. The default is usb_drive. | ||||
file_reader = usb_drive | |||||
#file_reader = directory | |||||
#file_reader = usb_drive | |||||
file_reader = directory | |||||
# The rest of the configuration for video looper below is optional and can be | # The rest of the configuration for video looper below is optional and can be | ||||
# ignored. | # ignored. | ||||
@@ -54,7 +54,7 @@ console_output = true | |||||
[directory] | [directory] | ||||
# The path to search for movies when using the directory file reader. | # The path to search for movies when using the directory file reader. | ||||
path = /home/pi | |||||
path = /home/pi/video | |||||
# USB drive file reader configuration follows. | # USB drive file reader configuration follows. | ||||
[usb_drive] | [usb_drive] | ||||