[FFmpeg-devel] libavformat/segment.c: Handle custom HTTP headers

Submitted by Artyom V. Poptsov on Oct. 21, 2016, 8:54 p.m.

Details

Message ID 87lgxhjudi.fsf@elephant.savannah
State New
Headers show

Commit Message

Artyom V. Poptsov Oct. 21, 2016, 8:54 p.m.
Hello everybody,

as far as I could see ffmpeg from the 'master' branch doesn't add custom
HTTP headers (specified by means of '-headers' option) to the requests
when 'segment' format is used (checked on August 31st.)

I prepared a patch that allows to use custom headers along with
'segment' format.  The patch is based on commit
a13a81a0dc98a35293f3f2603db9b01bf76b6a05 from the 'master' branch.

The changes were tested on x86 and ARM platforms and it seems that it
works quite well.

I'm hoping that the attached patch could be of some use for others as
it's quite common to use some kind of HTTP authentication mechanism
which requires additional headers.

Please let me know if there any problems with the patch; it's my first
contribution to ffmpeg project and I'd love to get any feedback.

Thanks,

- Artyom

Patch hide | download patch | download mbox

From 9ab977b521ef9221bc44655872a301eb67f85d7a Mon Sep 17 00:00:00 2001
From: "Artyom V. Poptsov" <poptsov.artyom@gmail.com>
Date: Wed, 31 Aug 2016 20:56:11 +0400
Subject: [PATCH] libavformat/segment.c: Handle custom HTTP headers

* libavformat/segment.c: Handle custom HTTP headers.
  (SegmentContext): Add 'headers' field.
  (segment_start): Append the headers; send the headers.
  (segment_list_open): Likewise.
  (seg_init): Likewise.
  (options): Add 'headers' option.
---
 libavformat/segment.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/libavformat/segment.c b/libavformat/segment.c
index bf29ef8..9b1448e 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -1,5 +1,6 @@ 
 /*
  * Copyright (c) 2011, Luca Barbato
+ * Copyright (c) 2016, Artyom V. Poptsov <poptsov.artyom@gmail.com>
  *
  * This file is part of FFmpeg.
  *
@@ -112,6 +113,7 @@  typedef struct SegmentContext {
     int  individual_header_trailer; /**< Set by a private option. */
     int  write_header_trailer; /**< Set by a private option. */
     char *header_filename;  ///< filename to write the output header to
+    char *headers;         ///< HTTP headers
 
     int reset_timestamps;  ///< reset timestamps at the begin of each segment
     int64_t initial_offset;    ///< initial timestamps offset, expressed in microseconds
@@ -247,7 +249,10 @@  static int segment_start(AVFormatContext *s, int write_header)
     if ((err = set_segment_filename(s)) < 0)
         return err;
 
-    if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0) {
+    AVDictionary *d = NULL;
+    av_dict_set(&d, "headers", seg->headers, 0);
+
+    if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &d)) < 0) {
         av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
         return err;
     }
@@ -276,7 +281,9 @@  static int segment_list_open(AVFormatContext *s)
     int ret;
 
     snprintf(seg->temp_list_filename, sizeof(seg->temp_list_filename), seg->use_rename ? "%s.tmp" : "%s", seg->list);
-    ret = s->io_open(s, &seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE, NULL);
+    AVDictionary *d = NULL;
+    av_dict_set(&d, "headers", seg->headers, 0);
+    ret = s->io_open(s, &seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE, &d);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Failed to open segment list '%s'\n", seg->list);
         return ret;
@@ -738,10 +745,13 @@  static int seg_init(AVFormatContext *s)
         goto fail;
     oc = seg->avf;
 
+    AVDictionary *d = NULL;
+    av_dict_set(&d, "headers", seg->headers, 0);
+
     if (seg->write_header_trailer) {
         if ((ret = s->io_open(s, &oc->pb,
                               seg->header_filename ? seg->header_filename : oc->filename,
-                              AVIO_FLAG_WRITE, NULL)) < 0) {
+                              AVIO_FLAG_WRITE, &d)) < 0) {
             av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
             goto fail;
         }
@@ -784,7 +794,7 @@  static int seg_init(AVFormatContext *s)
         } else {
             close_null_ctxp(&oc->pb);
         }
-        if ((ret = oc->io_open(oc, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0)
+        if ((ret = oc->io_open(oc, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &d)) < 0)
             goto fail;
         if (!seg->individual_header_trailer)
             oc->pb->seekable = 0;
@@ -1000,6 +1010,7 @@  static const AVOption options[] = {
     { "reset_timestamps", "reset timestamps at the begin of each segment", OFFSET(reset_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
     { "initial_offset", "set initial timestamp offset", OFFSET(initial_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E },
     { "write_empty_segments", "allow writing empty 'filler' segments", OFFSET(write_empty), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
+    { "headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
     { NULL },
 };
 
-- 
2.7.3