├── .gitattributes ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── encode.c ├── telepi ├── telepi.c └── telepi.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # ========================= 18 | # Operating System Files 19 | # ========================= 20 | 21 | # OSX 22 | # ========================= 23 | 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must end with two \r 29 | Icon 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Douglas Gore 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. 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. 9 | 10 | 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. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc telepi.c encode.c -DHAVE_LIBBCM_HOST -DUSE_EXTERNAL_LIBBCM_HOST -DUSE_VCHIQ_ARM -Wno-psabi -I /opt/vc/include/ -I /opt/vc/include/interface/vcos/pthreads/ -I /opt/vc/include/interface/vmcs_host/linux/ -I /opt/vc/src/hello_pi/libs/ilclient/ -L /opt/vc/lib -L /opt/vc/src/hello_pi/libs/ilclient -lpthread -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lilclient -o telepi 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TelePi - remote streaming for your Raspberry Pi 2 | 3 | TelePi is an attempt to build a better remote desktop solution for the Raspberry Pi by utilising the features of the platform. Dispmanx is used to capture the exactly what appears on screen and the hardware H.264 encoder to used to compress the video in real-time to allow for a smoother, higher framerate experience compared to traditional solutions such as VNC and remote X windows. It also brings the benefit of being compatible with all Raspberry Pi applications including Minecraft. 4 | 5 | In addition to the streaming feature, TelePi can record the raw H.264 stream to a file making it useful for recording videos for tutorials and demostrations without the need for external hardware. 6 | 7 | Note: This project is currently in a proof of concept phase and isn't very usable for general use, particularly as there are some latency issues to solve for streaming. Please feel free to try the project and contribute towards the development. 8 | 9 | Usage: 10 | Record to file: ./telepi 11 | Output to stdout: ./telepi 12 | 13 | ## Stream to a remote computer using netcat ## 14 | 15 | On the Raspberry Pi: 16 | ./telepi - | netcat 5001 17 | 18 | View on Windows: 19 | ncat.exe -l -p 5001 | mplayer.exe -fps 31 -cache 512 - 20 | 21 | ## Stream as a HTTP server ## 22 | 23 | On the Raspberry Pi: 24 | ./telepi - | cvlc -vvv stream:///dev/stdin --sout '#standard{access=http,mux=ts,dst=:8090}' :demux=h264 25 | 26 | View with VLC: 27 | vlc http://raspberrypi.lan:8089/ -------------------------------------------------------------------------------- /encode.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * TelePi - remote streaming for your Raspberry Pi 3 | ****************************************************************************** 4 | * encode.c 5 | * 6 | * Portions of this code are derived from hello_encode.c: 7 | * Copyright (c) 2012, Broadcom Europe Ltd 8 | * Copyright (c) 2012, Kalle Vahlman 9 | * Tuomas Kulve 10 | */ 11 | 12 | #include 13 | 14 | #include "telepi.h" 15 | #include "ilclient.h" 16 | 17 | OMX_PARAM_PORTDEFINITIONTYPE def; 18 | COMPONENT_T *list[5]; 19 | ILCLIENT_T *client; 20 | 21 | static void 22 | print_def(OMX_PARAM_PORTDEFINITIONTYPE def) 23 | { 24 | fprintf(stderr, "Port %u: %s %u/%u %u %u %s,%s,%s %ux%u %ux%u @%u %u\n", 25 | def.nPortIndex, 26 | def.eDir == OMX_DirInput ? "in" : "out", 27 | def.nBufferCountActual, 28 | def.nBufferCountMin, 29 | def.nBufferSize, 30 | def.nBufferAlignment, 31 | def.bEnabled ? "enabled" : "disabled", 32 | def.bPopulated ? "populated" : "not pop.", 33 | def.bBuffersContiguous ? "contig." : "not cont.", 34 | def.format.video.nFrameWidth, 35 | def.format.video.nFrameHeight, 36 | def.format.video.nStride, 37 | def.format.video.nSliceHeight, 38 | def.format.video.xFramerate, def.format.video.eColorFormat); 39 | } 40 | 41 | bool encode_init(COMPONENT_T **video_encode) 42 | { 43 | OMX_ERRORTYPE omx_return; 44 | 45 | memset(list, 0, sizeof(list)); 46 | 47 | if ((client = ilclient_init()) == NULL) 48 | { 49 | return false; 50 | } 51 | 52 | if (OMX_Init() != OMX_ErrorNone) 53 | { 54 | ilclient_destroy(client); 55 | return false; 56 | } 57 | 58 | // create video_encode 59 | omx_return = ilclient_create_component(client, video_encode, "video_encode", 60 | ILCLIENT_DISABLE_ALL_PORTS | 61 | ILCLIENT_ENABLE_INPUT_BUFFERS | 62 | ILCLIENT_ENABLE_OUTPUT_BUFFERS); 63 | if (omx_return != 0) 64 | { 65 | fprintf(stderr, "ilclient_create_component() for video_encode failed with %x!\n", omx_return); 66 | return false; 67 | } 68 | 69 | list[0] = *video_encode; 70 | 71 | // get current settings of video_encode component from port 200 72 | memset(&def, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); 73 | def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 74 | def.nVersion.nVersion = OMX_VERSION; 75 | def.nPortIndex = 200; 76 | 77 | if (OMX_GetParameter(ILC_GET_HANDLE(*video_encode), OMX_IndexParamPortDefinition, &def) != OMX_ErrorNone) 78 | { 79 | fprintf(stderr, "%s:%d: OMX_GetParameter() for video_encode port 200 failed!\n", __FUNCTION__, __LINE__); 80 | return false; 81 | } 82 | 83 | print_def(def); 84 | 85 | return true; 86 | } 87 | 88 | bool encode_config_format(COMPONENT_T* handle, int32_t width, int32_t height, int32_t framerate) 89 | { 90 | OMX_ERRORTYPE omx_return; 91 | 92 | // Port 200: in 1/1 115200 16 enabled,not pop.,not cont. 320x240 320x240 @1966080 20 93 | def.format.video.nFrameWidth = width; 94 | def.format.video.nFrameHeight = height; 95 | def.format.video.xFramerate = framerate << 16; 96 | def.format.video.nSliceHeight = def.format.video.nFrameHeight; 97 | def.format.video.nStride = def.format.video.nFrameWidth; 98 | def.format.video.eColorFormat = /* OMX_COLOR_FormatYUV420PackedPlanar; */ OMX_COLOR_Format24bitBGR888; 99 | 100 | print_def(def); 101 | 102 | omx_return = OMX_SetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamPortDefinition, &def); 103 | if (omx_return != OMX_ErrorNone) 104 | { 105 | fprintf(stderr, "%s:%d: OMX_SetParameter() for video_encode port 200 failed with %x!\n", __FUNCTION__, __LINE__, omx_return); 106 | return false; 107 | } 108 | } 109 | 110 | bool encode_config_encoding(COMPONENT_T* handle, int32_t codec) 111 | { 112 | OMX_ERRORTYPE omx_return; 113 | OMX_VIDEO_PARAM_PORTFORMATTYPE format; 114 | 115 | memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 116 | format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); 117 | format.nVersion.nVersion = OMX_VERSION; 118 | format.nPortIndex = 201; 119 | format.eCompressionFormat = OMX_VIDEO_CodingAVC; 120 | 121 | fprintf(stderr, "OMX_SetParameter for video_encode:201...\n"); 122 | omx_return = OMX_SetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamVideoPortFormat, &format); 123 | if (omx_return != OMX_ErrorNone) 124 | { 125 | fprintf(stderr, "%s:%d: OMX_SetParameter() for video_encode port 201 failed with %x!\n", __FUNCTION__, __LINE__, omx_return); 126 | return false; 127 | } 128 | 129 | return true; 130 | } 131 | 132 | bool encode_config_bitrate(COMPONENT_T* handle, uint32_t bitrate) 133 | { 134 | OMX_ERRORTYPE omx_return; 135 | OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 136 | 137 | // set current bitrate to 1Mbit 138 | memset(&bitrateType, 0, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); 139 | bitrateType.nSize = sizeof(OMX_VIDEO_PARAM_BITRATETYPE); 140 | bitrateType.nVersion.nVersion = OMX_VERSION; 141 | bitrateType.eControlRate = OMX_Video_ControlRateVariable; 142 | bitrateType.nTargetBitrate = bitrate; 143 | bitrateType.nPortIndex = 201; 144 | 145 | omx_return = OMX_SetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamVideoBitrate, &bitrateType); 146 | if (omx_return != OMX_ErrorNone) 147 | { 148 | fprintf(stderr, "%s:%d: OMX_SetParameter() for bitrate for video_encode port 201 failed with %x!\n", __FUNCTION__, __LINE__, omx_return); 149 | return false; 150 | } 151 | 152 | // get current bitrate 153 | memset(&bitrateType, 0, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); 154 | bitrateType.nSize = sizeof(OMX_VIDEO_PARAM_BITRATETYPE); 155 | bitrateType.nVersion.nVersion = OMX_VERSION; 156 | bitrateType.nPortIndex = 201; 157 | 158 | if (OMX_GetParameter(ILC_GET_HANDLE(handle), OMX_IndexParamVideoBitrate, &bitrateType) != OMX_ErrorNone) 159 | { 160 | fprintf(stderr, "%s:%d: OMX_GetParameter() for video_encode for bitrate port 201 failed!\n", __FUNCTION__, __LINE__); 161 | return false; 162 | } 163 | 164 | fprintf(stderr, "Current Bitrate=%u\n",bitrateType.nTargetBitrate); 165 | 166 | return true; 167 | } 168 | 169 | bool encode_config_low_latency(COMPONENT_T* handle, bool low_latency) 170 | { 171 | OMX_ERRORTYPE omx_return; 172 | OMX_CONFIG_BOOLEANTYPE booleanType; 173 | 174 | // set current bitrate to 1Mbit 175 | memset(&booleanType, 0, sizeof(OMX_CONFIG_BOOLEANTYPE)); 176 | booleanType.nSize = sizeof(OMX_CONFIG_BOOLEANTYPE); 177 | booleanType.nVersion.nVersion = OMX_VERSION; 178 | booleanType.bEnabled = OMX_TRUE; 179 | //booleanType.nPortIndex = 201; 180 | 181 | /* 182 | if((r = OMX_SetParameter(ctx.camera, OMX_IndexConfigPortCapturing, &capture)) != OMX_ErrorNone) { 183 | omx_die(r, "Failed to switch on capture on camera video output port 71"); 184 | } 185 | */ 186 | 187 | omx_return = OMX_SetConfig(ILC_GET_HANDLE(handle), OMX_IndexConfigBrcmVideoH264LowLatency, &booleanType); 188 | if (omx_return != OMX_ErrorNone) 189 | { 190 | fprintf(stderr, "%s:%d: OMX_SetConfig() for low latency for video_encode port 201 failed with %x!\n", __FUNCTION__, __LINE__, omx_return); 191 | return false; 192 | } 193 | 194 | // get current bitrate 195 | memset(&booleanType, 0, sizeof(OMX_CONFIG_BOOLEANTYPE)); 196 | booleanType.nSize = sizeof(OMX_CONFIG_BOOLEANTYPE); 197 | booleanType.nVersion.nVersion = OMX_VERSION; 198 | //booleanType.nPortIndex = 201; 199 | 200 | if (OMX_GetConfig(ILC_GET_HANDLE(handle), OMX_IndexConfigBrcmVideoH264LowLatency, &booleanType) != OMX_ErrorNone) 201 | { 202 | fprintf(stderr, "%s:%d: OMX_GetConfig() for video_encode for bitrate port 201 failed!\n", __FUNCTION__, __LINE__); 203 | return false; 204 | } 205 | 206 | fprintf(stderr, "Low latency=%u\n", booleanType.bEnabled); 207 | 208 | return true; 209 | } 210 | 211 | bool encode_config_activate(COMPONENT_T* handle) 212 | { 213 | fprintf(stderr, "encode to idle...\n"); 214 | 215 | if (ilclient_change_component_state(handle, OMX_StateIdle) == -1) 216 | { 217 | fprintf(stderr, "%s:%d: ilclient_change_component_state(video_encode, OMX_StateIdle) failed", __FUNCTION__, __LINE__); 218 | return false; 219 | } 220 | 221 | fprintf(stderr, "enabling port buffers for 200...\n"); 222 | if (ilclient_enable_port_buffers(handle, 200, NULL, NULL, NULL) != 0) 223 | { 224 | fprintf(stderr, "enabling port buffers for 200 failed!\n"); 225 | return false; 226 | } 227 | 228 | fprintf(stderr, "enabling port buffers for 201...\n"); 229 | if (ilclient_enable_port_buffers(handle, 201, NULL, NULL, NULL) != 0) 230 | { 231 | fprintf(stderr, "enabling port buffers for 201 failed!\n"); 232 | return false; 233 | } 234 | 235 | fprintf(stderr, "encode to executing...\n"); 236 | ilclient_change_component_state(handle, OMX_StateExecuting); 237 | 238 | return true; 239 | } 240 | 241 | void encode_deinit(COMPONENT_T* handle) 242 | { 243 | fprintf(stderr, "disabling port buffers for 200 and 201...\n"); 244 | ilclient_disable_port_buffers(handle, 200, NULL, NULL, NULL); 245 | ilclient_disable_port_buffers(handle, 201, NULL, NULL, NULL); 246 | 247 | ilclient_state_transition(list, OMX_StateIdle); 248 | ilclient_state_transition(list, OMX_StateLoaded); 249 | 250 | ilclient_cleanup_components(list); 251 | 252 | OMX_Deinit(); 253 | 254 | ilclient_destroy(client); 255 | } -------------------------------------------------------------------------------- /telepi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DougGore/telepi/8a2a15dc933fd34e12405437f6efb378629e05b3/telepi -------------------------------------------------------------------------------- /telepi.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * TelePi - remote streaming for your Raspberry Pi 3 | ****************************************************************************** 4 | * Initial preview release 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "bcm_host.h" 13 | #include "ilclient.h" 14 | 15 | #include "telepi.h" 16 | 17 | #define NUMFRAMES 300000 18 | #define WIDTH 640 19 | #define PITCH ((WIDTH+31)&~31) 20 | #define HEIGHT 480 21 | #define HEIGHT16 ((HEIGHT+15)&~15) 22 | #define SIZE ((WIDTH * HEIGHT16 * 3)/2) 23 | 24 | DISPMANX_DISPLAY_HANDLE_T display; 25 | DISPMANX_RESOURCE_HANDLE_T resource; 26 | DISPMANX_MODEINFO_T info; 27 | VC_RECT_T rect; 28 | 29 | 30 | uint32_t screen = 0; 31 | 32 | uint32_t vc_image_ptr; 33 | 34 | COMPONENT_T *video_encode = NULL; 35 | 36 | OMX_BUFFERHEADERTYPE *buf; 37 | OMX_BUFFERHEADERTYPE *out; 38 | 39 | /* 40 | * simulate grabbing a picture from some device 41 | */ 42 | int take_snapshot(void *buffer, OMX_U32 * filledLen) 43 | { 44 | VC_IMAGE_TRANSFORM_T transform = 0; 45 | int ret; 46 | 47 | ret = vc_dispmanx_snapshot(display, resource, transform); 48 | assert(ret == 0); 49 | 50 | ret = vc_dispmanx_resource_read_data(resource, &rect, buffer, info.width * 3); 51 | assert(ret == 0); 52 | 53 | *filledLen = info.width * info.height * 3; 54 | 55 | return 1; 56 | } 57 | 58 | 59 | static int 60 | video_encode_test(char *outputfilename) 61 | { 62 | int status = 0; 63 | int framenumber = 0; 64 | FILE *outf; 65 | 66 | int ret; 67 | 68 | OMX_ERRORTYPE r; 69 | 70 | VC_IMAGE_TYPE_T type = VC_IMAGE_BGR888; 71 | 72 | fprintf(stderr, "Open display[%i]...\n", screen ); 73 | display = vc_dispmanx_display_open( screen ); 74 | 75 | ret = vc_dispmanx_display_get_info(display, &info); 76 | assert(ret == 0); 77 | fprintf(stderr, "Display is %d x %d\n", info.width, info.height ); 78 | 79 | resource = vc_dispmanx_resource_create( type, 80 | info.width, 81 | info.height, 82 | &vc_image_ptr ); 83 | 84 | fprintf(stderr, "VC image ptr: 0x%X\n", vc_image_ptr); 85 | 86 | ret = vc_dispmanx_rect_set(&rect, 0, 0, info.width, info.height); 87 | assert(ret == 0); 88 | 89 | encode_init(&video_encode); 90 | 91 | encode_config_format(video_encode, info.width, info.height, 30); 92 | encode_config_encoding(video_encode, OMX_VIDEO_CodingAVC); 93 | encode_config_bitrate(video_encode, 16000000 /* 8388608 */); 94 | 95 | //encode_config_low_latency(video_encode, true); 96 | 97 | encode_config_activate(video_encode); 98 | 99 | if (outputfilename[0] == '-') 100 | { 101 | outf = stdout; 102 | } 103 | else 104 | { 105 | outf = fopen(outputfilename, "wb"); 106 | } 107 | 108 | if (outf == NULL) 109 | { 110 | fprintf(stderr, "Failed to open '%s' for writing video\n", outputfilename); 111 | exit(1); 112 | } 113 | 114 | fprintf(stderr, "looping for buffers...\n"); 115 | do 116 | { 117 | buf = ilclient_get_input_buffer(video_encode, 200, 1); 118 | 119 | if (buf != NULL) 120 | { 121 | /* fill it */ 122 | take_snapshot(buf->pBuffer, &buf->nFilledLen); 123 | framenumber++; 124 | 125 | if (OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_encode), buf) != OMX_ErrorNone) 126 | { 127 | fprintf(stderr, "Error emptying buffer!\n"); 128 | } 129 | 130 | out = ilclient_get_output_buffer(video_encode, 201, 1); 131 | 132 | r = OMX_FillThisBuffer(ILC_GET_HANDLE(video_encode), out); 133 | if (r != OMX_ErrorNone) 134 | { 135 | fprintf(stderr, "Error filling buffer: %x\n", r); 136 | } 137 | 138 | if (out != NULL) 139 | { 140 | /* 141 | if (out->nFlags & OMX_BUFFERFLAG_CODECCONFIG) 142 | { 143 | int i; 144 | for (i = 0; i < out->nFilledLen; i++) 145 | printf("%x ", out->pBuffer[i]); 146 | printf("\n"); 147 | } 148 | */ 149 | 150 | r = fwrite(out->pBuffer, 1, out->nFilledLen, outf); 151 | if (r != out->nFilledLen) 152 | { 153 | fprintf(stderr, "fwrite: Error emptying buffer: %d!\n", r); 154 | } 155 | else 156 | { 157 | //fprintf(stderr, "Writing frame %d/%d\n", framenumber, NUMFRAMES); 158 | } 159 | 160 | fflush(outf); 161 | 162 | out->nFilledLen = 0; 163 | } 164 | else 165 | { 166 | fprintf(stderr, "Not getting it :(\n"); 167 | } 168 | 169 | } 170 | else 171 | { 172 | fprintf(stderr, "Doh, no buffers for me!\n"); 173 | } 174 | 175 | } while (framenumber < NUMFRAMES); 176 | 177 | fclose(outf); 178 | 179 | fprintf(stderr, "Teardown.\n"); 180 | 181 | encode_deinit(video_encode); 182 | 183 | return status; 184 | } 185 | 186 | int 187 | main(int argc, char **argv) 188 | { 189 | fprintf(stderr, "TelePi - Raspberry Pi remote viewer\n\n"); 190 | 191 | if (argc < 2) { 192 | fprintf(stderr, "Usage:\n"); 193 | fprintf(stderr, "Record to file: %s \n", argv[0]); 194 | fprintf(stderr, "Output to stdout: %s \n", argv[0]); 195 | 196 | fprintf(stderr, "\nStream to a remote computer:\n"); 197 | fprintf(stderr, "%s - | netcat 5001\n\n", argv[0]); 198 | exit(1); 199 | } 200 | 201 | bcm_host_init(); 202 | 203 | return video_encode_test(argv[1]); 204 | } 205 | -------------------------------------------------------------------------------- /telepi.h: -------------------------------------------------------------------------------- 1 | #ifndef TELEPI_H 2 | #define TELEPI_H 3 | 4 | #include 5 | #include 6 | 7 | #include "ilclient.h" 8 | 9 | bool encode_init(COMPONENT_T **video_encode); 10 | bool encode_config_format(COMPONENT_T* handle, int32_t width, int32_t height, int32_t framerate); 11 | bool encode_config_encoding(COMPONENT_T* handle, int32_t codec); 12 | bool encode_config_bitrate(COMPONENT_T* handle, uint32_t bitrate); 13 | bool encode_config_activate(COMPONENT_T* handle); 14 | void encode_deinit(COMPONENT_T* handle); 15 | 16 | bool encode_config_low_latency(COMPONENT_T* handle, bool low_latency); 17 | 18 | #endif // TELEPI_H --------------------------------------------------------------------------------