.github
CMakeModules
dist
externals
SDL
Vulkan-Headers
cmake-modules
cubeb
discord-rpc
dynarmic
ffmpeg
compat
doc
doxy
examples
.gitignore
Makefile
Makefile.example
README
avio_list_dir.c
avio_reading.c
decode_audio.c
decode_video.c
demuxing_decoding.c
encode_audio.c
encode_video.c
extract_mvs.c
filter_audio.c
filtering_audio.c
filtering_video.c
http_multiclient.c
hw_decode.c
metadata.c
muxing.c
qsvdec.c
remuxing.c
resampling_audio.c
scaling_video.c
transcode_aac.c
transcoding.c
vaapi_encode.c
vaapi_transcode.c
.gitignore
APIchanges
Doxyfile
Makefile
authors.texi
bitstream_filters.texi
bootstrap.min.css
build_system.txt
codecs.texi
decoders.texi
default.css
demuxers.texi
developer.texi
devices.texi
doxy-wrapper.sh
encoders.texi
errno.txt
faq.texi
fate.texi
fate_config.sh.template
ffmpeg-bitstream-filters.texi
ffmpeg-codecs.texi
ffmpeg-devices.texi
ffmpeg-filters.texi
ffmpeg-formats.texi
ffmpeg-protocols.texi
ffmpeg-resampler.texi
ffmpeg-scaler.texi
ffmpeg-utils.texi
ffmpeg.texi
ffmpeg.txt
ffplay.texi
ffprobe.texi
ffprobe.xsd
fftools-common-opts.texi
filter_design.txt
filters.texi
formats.texi
general.texi
git-howto.texi
indevs.texi
issue_tracker.txt
lexicon
libav-merge.txt
libavcodec.texi
libavdevice.texi
libavfilter.texi
libavformat.texi
libavutil.texi
libswresample.texi
libswscale.texi
mailing-list-faq.texi
metadata.texi
mips.txt
multithreading.txt
muxers.texi
nut.texi
optimization.txt
outdevs.texi
patchwork
platform.texi
print_options.c
protocols.texi
rate_distortion.txt
resampler.texi
scaler.texi
snow.txt
style.min.css
swresample.txt
swscale.txt
t2h.init
t2h.pm
tablegen.txt
texi2pod.pl
texidep.pl
undefined.txt
utils.texi
writing_filters.txt
ffbuild
fftools
libavcodec
libavdevice
libavfilter
libavformat
libavresample
libavutil
libpostproc
libswresample
libswscale
presets
tests
tools
.gitattributes
.gitignore
.mailmap
.travis.yml
CONTRIBUTING.md
COPYING.GPLv2
COPYING.GPLv3
COPYING.LGPLv2.1
COPYING.LGPLv3
CREDITS
Changelog
INSTALL.md
LICENSE.md
MAINTAINERS
Makefile
README.md
RELEASE
RELEASE_NOTES
configure
find-modules
getopt
glad
httplib
inih
libressl
libusb
libzip
mbedtls
microprofile
opus
sirit
soundtouch
xbyak
CMakeLists.txt
patches
src
CMakeLists.txt
LICENSE
README.md
license.txt
		
			
				
	
	
		
			157 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*
 | |
|  * Copyright (c) 2015 Stephan Holljes
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
|  * of this software and associated documentation files (the "Software"), to deal
 | |
|  * in the Software without restriction, including without limitation the rights
 | |
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
|  * copies of the Software, and to permit persons to whom the Software is
 | |
|  * furnished to do so, subject to the following conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice shall be included in
 | |
|  * all copies or substantial portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | |
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | |
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | |
|  * THE SOFTWARE.
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * @file
 | |
|  * libavformat multi-client network API usage example.
 | |
|  *
 | |
|  * @example http_multiclient.c
 | |
|  * This example will serve a file without decoding or demuxing it over http.
 | |
|  * Multiple clients can connect and will receive the same file.
 | |
|  */
 | |
| 
 | |
| #include <libavformat/avformat.h>
 | |
| #include <libavutil/opt.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| static void process_client(AVIOContext *client, const char *in_uri)
 | |
| {
 | |
|     AVIOContext *input = NULL;
 | |
|     uint8_t buf[1024];
 | |
|     int ret, n, reply_code;
 | |
|     uint8_t *resource = NULL;
 | |
|     while ((ret = avio_handshake(client)) > 0) {
 | |
|         av_opt_get(client, "resource", AV_OPT_SEARCH_CHILDREN, &resource);
 | |
|         // check for strlen(resource) is necessary, because av_opt_get()
 | |
|         // may return empty string.
 | |
|         if (resource && strlen(resource))
 | |
|             break;
 | |
|         av_freep(&resource);
 | |
|     }
 | |
|     if (ret < 0)
 | |
|         goto end;
 | |
|     av_log(client, AV_LOG_TRACE, "resource=%p\n", resource);
 | |
|     if (resource && resource[0] == '/' && !strcmp((resource + 1), in_uri)) {
 | |
|         reply_code = 200;
 | |
|     } else {
 | |
|         reply_code = AVERROR_HTTP_NOT_FOUND;
 | |
|     }
 | |
|     if ((ret = av_opt_set_int(client, "reply_code", reply_code, AV_OPT_SEARCH_CHILDREN)) < 0) {
 | |
|         av_log(client, AV_LOG_ERROR, "Failed to set reply_code: %s.\n", av_err2str(ret));
 | |
|         goto end;
 | |
|     }
 | |
|     av_log(client, AV_LOG_TRACE, "Set reply code to %d\n", reply_code);
 | |
| 
 | |
|     while ((ret = avio_handshake(client)) > 0);
 | |
| 
 | |
|     if (ret < 0)
 | |
|         goto end;
 | |
| 
 | |
|     fprintf(stderr, "Handshake performed.\n");
 | |
|     if (reply_code != 200)
 | |
|         goto end;
 | |
|     fprintf(stderr, "Opening input file.\n");
 | |
|     if ((ret = avio_open2(&input, in_uri, AVIO_FLAG_READ, NULL, NULL)) < 0) {
 | |
|         av_log(input, AV_LOG_ERROR, "Failed to open input: %s: %s.\n", in_uri,
 | |
|                av_err2str(ret));
 | |
|         goto end;
 | |
|     }
 | |
|     for(;;) {
 | |
|         n = avio_read(input, buf, sizeof(buf));
 | |
|         if (n < 0) {
 | |
|             if (n == AVERROR_EOF)
 | |
|                 break;
 | |
|             av_log(input, AV_LOG_ERROR, "Error reading from input: %s.\n",
 | |
|                    av_err2str(n));
 | |
|             break;
 | |
|         }
 | |
|         avio_write(client, buf, n);
 | |
|         avio_flush(client);
 | |
|     }
 | |
| end:
 | |
|     fprintf(stderr, "Flushing client\n");
 | |
|     avio_flush(client);
 | |
|     fprintf(stderr, "Closing client\n");
 | |
|     avio_close(client);
 | |
|     fprintf(stderr, "Closing input\n");
 | |
|     avio_close(input);
 | |
|     av_freep(&resource);
 | |
| }
 | |
| 
 | |
| int main(int argc, char **argv)
 | |
| {
 | |
|     AVDictionary *options = NULL;
 | |
|     AVIOContext *client = NULL, *server = NULL;
 | |
|     const char *in_uri, *out_uri;
 | |
|     int ret, pid;
 | |
|     av_log_set_level(AV_LOG_TRACE);
 | |
|     if (argc < 3) {
 | |
|         printf("usage: %s input http://hostname[:port]\n"
 | |
|                "API example program to serve http to multiple clients.\n"
 | |
|                "\n", argv[0]);
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     in_uri = argv[1];
 | |
|     out_uri = argv[2];
 | |
| 
 | |
|     avformat_network_init();
 | |
| 
 | |
|     if ((ret = av_dict_set(&options, "listen", "2", 0)) < 0) {
 | |
|         fprintf(stderr, "Failed to set listen mode for server: %s\n", av_err2str(ret));
 | |
|         return ret;
 | |
|     }
 | |
|     if ((ret = avio_open2(&server, out_uri, AVIO_FLAG_WRITE, NULL, &options)) < 0) {
 | |
|         fprintf(stderr, "Failed to open server: %s\n", av_err2str(ret));
 | |
|         return ret;
 | |
|     }
 | |
|     fprintf(stderr, "Entering main loop.\n");
 | |
|     for(;;) {
 | |
|         if ((ret = avio_accept(server, &client)) < 0)
 | |
|             goto end;
 | |
|         fprintf(stderr, "Accepted client, forking process.\n");
 | |
|         // XXX: Since we don't reap our children and don't ignore signals
 | |
|         //      this produces zombie processes.
 | |
|         pid = fork();
 | |
|         if (pid < 0) {
 | |
|             perror("Fork failed");
 | |
|             ret = AVERROR(errno);
 | |
|             goto end;
 | |
|         }
 | |
|         if (pid == 0) {
 | |
|             fprintf(stderr, "In child.\n");
 | |
|             process_client(client, in_uri);
 | |
|             avio_close(server);
 | |
|             exit(0);
 | |
|         }
 | |
|         if (pid > 0)
 | |
|             avio_close(client);
 | |
|     }
 | |
| end:
 | |
|     avio_close(server);
 | |
|     if (ret < 0 && ret != AVERROR_EOF) {
 | |
|         fprintf(stderr, "Some errors occurred: %s\n", av_err2str(ret));
 | |
|         return 1;
 | |
|     }
 | |
|     return 0;
 | |
| }
 |