On Thu, Jul 9, 2015 at 3:47 PM, Nicolas George <geo...@nsup.org> wrote: > Le decadi 20 messidor, an CCXXIII, Stephan Holljes a écrit : >> Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com> >> --- >> doc/examples/Makefile | 1 + >> doc/examples/http_multiclient.c | 120 >> ++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 121 insertions(+) >> create mode 100644 doc/examples/http_multiclient.c >> Changes since first version: >> - Move client handling code in separate function >> - Close filedescriptors earlier >> >> diff --git a/doc/examples/Makefile b/doc/examples/Makefile >> index 9699f11..8c9501b 100644 >> --- a/doc/examples/Makefile >> +++ b/doc/examples/Makefile >> @@ -18,6 +18,7 @@ EXAMPLES= avio_list_dir \ >> extract_mvs \ >> filtering_video \ >> filtering_audio \ >> + http_multiclient \ >> metadata \ >> muxing \ >> remuxing \ >> diff --git a/doc/examples/http_multiclient.c >> b/doc/examples/http_multiclient.c >> new file mode 100644 >> index 0000000..a780321 >> --- /dev/null >> +++ b/doc/examples/http_multiclient.c >> @@ -0,0 +1,120 @@ >> +/* >> + * copyright (c) 2015 Stephan Holljes >> + * >> + * This file is part of FFmpeg. >> + * >> + * FFmpeg is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU Lesser General Public >> + * License as published by the Free Software Foundation; either >> + * version 2.1 of the License, or (at your option) any later version. >> + * >> + * FFmpeg is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + * Lesser General Public License for more details. >> + * >> + * You should have received a copy of the GNU Lesser General Public >> + * License along with FFmpeg; if not, write to the Free Software >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 >> USA >> + */ >> + >> +/** >> + * @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 <unistd.h> >> + >> +void process_client(AVIOContext *client, const char* in_uri) >> +{ > >> + AVIOContext *input =NULL; > > Nit: space. > >> + uint8_t buf[1024]; >> + int ret, n; > >> + avio_handshake(client); > > Check for error. > >> + fprintf(stderr, "Handshake performed.\n"); >> + 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\n", in_uri); >> + return; >> + } > > I just realized this: how would you go about returning 404 to the client > here?
Good question, I haven't thought about that myself. Adding a 404 error to handle_http_errors() and calling it with AVERROR_HTTP_NOT_FOUND could be a solution. I feel like the name "handle_http_errors" is not well chosen then, though. > >> + 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)); >> + ret = n; >> + break; >> + } >> + avio_write(client, buf, n); >> + avio_flush(client); >> + } >> + fprintf(stderr, "Flushing client\n"); >> + avio_flush(client); >> + fprintf(stderr, "Closing client\n"); >> + avio_close(client); >> + fprintf(stderr, "Closing input\n"); >> + avio_close(input); >> +} >> + >> +int main(int argc, char **argv) >> +{ >> + AVDictionary *options = NULL; >> + AVIOContext *client = NULL, *server = NULL; >> + const char *in_uri, *out_uri; >> + int ret, pid; >> + 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]; >> + >> + av_register_all(); >> + avformat_network_init(); >> + >> + if ((ret = av_dict_set(&options, "listen", "2", 0)) < 0) >> + goto end; >> + if ((ret = avio_open2(&server, out_uri, AVIO_FLAG_READ_WRITE, NULL, >> &options)) < 0) >> + goto end; >> + 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) { > >> + fprintf(stderr, "Fork failed.\n"); > > perror() > >> + 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) { > > At this point, I believe yo do not have to worry about EOF. > >> + fprintf(stderr, "Some errors occured: "); >> + fprintf(stderr, "%s\n", av_err2str(ret)); > > Could be a single line. > >> + return 1; >> + } >> + return 0; >> +} > > These are all my remarks for the series for now, I'd say it is almost ready > for inclusion. Great! > > Regards, > > -- > Nicolas George > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > Regards, Stephan _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel