diff --git a/libavcodec/packet.h b/libavcodec/packet.h
old mode 100644
new mode 100755
index 13667ffa36..8cbb1c2a75
--- a/libavcodec/packet.h
+++ b/libavcodec/packet.h
@@ -339,6 +339,13 @@ enum AVPacketSideDataType {
       */
      AV_PKT_DATA_FRAME_CROPPING,
  
+    /**
+     * Attributes found in the SDP, associated with the stream. This is a
+     * list of zero terminated key/value strings. There is no end marker for
+     * the list, so it is required to rely on the side data size to stop.
+     */
+    AV_PKT_DATA_SDP_ATTRIBUTES,
+
      /**
       * The number of side data types.
       * This is not part of the public API/ABI in the sense that it may
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
old mode 100644
new mode 100755
index 19b93df839..10594e501a
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -283,6 +283,91 @@ static int init_satip_stream(AVFormatContext *s)
  }
  #endif
  
+static int sdp_add_attribute_to_stream_side_data(AVFormatContext *s,
+                                                 AVStream *st,
+                                                 const char *p)
+{
+    AVPacketSideData *side_data = NULL;
+    AVDictionary* attributes_dict = NULL;
+    char *key = NULL, *value = NULL;
+    int ret = 0;
+
+    /* Get the stream's attributes dictionary.
+     * If the stream has no attributes dictionary, it will be automatically
+     * created by av_dict_set. */
+    side_data = av_packet_side_data_get(st->codecpar->coded_side_data,
+                                        st->codecpar->nb_coded_side_data,
+                                        AV_PKT_DATA_SDP_ATTRIBUTES);
+    if (side_data) {
+        ret = av_packet_unpack_dictionary(side_data->data, side_data->size,
+                                          &attributes_dict);
+        if (ret) {
+            av_log(s, AV_LOG_WARNING,
+                   "Unable to unpack SDP attributes dictionary.\n");
+            return -1;
+        }
+    }
+
+    /* The attribute can either be a value attribute (key:value) or
+     * property attribute (just the key).
+     * Look for the ':' separator, and create the 'key' and 'value'
+     * appropriately. */
+    const char *separator = strchr(p, ':');
+    if (separator) {
+        /* Make a copy of the key and value. */
+        key = av_strndup(p, separator - p);
+        value = av_strdup(separator + 1);
+    } else {
+        /* Copy the key and create an empty value. */
+        key = av_strdup(p);
+        value = av_mallocz(1);
+    }
+    if (!key || !value) {
+        av_dict_free(&attributes_dict);
+        av_free(value);
+        av_free(key);
+        return -1;
+    }
+
+    /* Add the attribute, then pack the dictionary again. */
+    ret = av_dict_set(&attributes_dict, key, value,
+                      AV_DICT_DONT_STRDUP_KEY |
+                      AV_DICT_DONT_STRDUP_VAL |
+                      AV_DICT_MULTIKEY);
+    if (ret) {
+        av_log(s, AV_LOG_WARNING,
+               "Unable to add SDL attribute to dictionary.\n");
+        av_dict_free(&attributes_dict);
+        return -1;
+    }
+    size_t packed_dict_size = 0u;
+    uint8_t *packed_dict = av_packet_pack_dictionary(attributes_dict,
+                                                     &packed_dict_size);
+
+    /* Free the dictionary, which is not needed any longer. */
+    av_dict_free(&attributes_dict);
+
+    /* Make sure the dictionary was packet successfully, then add it
+     * back to the stream's side data. */
+    if (!packed_dict) {
+        av_log(s, AV_LOG_WARNING,
+               "Unable to pack SDP attributes dictionary.\n");
+        return -1;
+    }
+    side_data = av_packet_side_data_add(&st->codecpar->coded_side_data,
+                                        &st->codecpar->nb_coded_side_data,
+                                        AV_PKT_DATA_SDP_ATTRIBUTES,
+                                        packed_dict, packed_dict_size,
+                                        0);
+    if (!side_data) {
+        av_log(s, AV_LOG_WARNING,
+               "Unable to add SDP attributes side data to stream.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
  /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
  static int sdp_parse_rtpmap(AVFormatContext *s,
                              AVStream *st, RTSPStream *rtsp_st,
@@ -570,6 +655,18 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
                     sizeof(rtsp_st->control_url));
          break;
      case 'a':
+        /* add all SDP attributes to the stream's side data */
+        if (rt->nb_rtsp_streams > 0) {
+            rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
+            if (rtsp_st->stream_index >= 0) {
+                st = s->streams[rtsp_st->stream_index];
+                if (sdp_add_attribute_to_stream_side_data(s, st, p)) {
+                    av_log(s, AV_LOG_WARNING,
+                           "Failed to add SDP attribute to stream");
+                }
+            }
+        }
+        /* now parse the SDP attribute line */
          if (av_strstart(p, "control:", &p)) {
              if (rt->nb_rtsp_streams == 0) {
                  if (!strncmp(p, "rtsp://", 7))
