diff mbox

[FFmpeg-devel,v7,4/4] avformat/rtpdec_rfc4175: handle interlace format

Message ID 1527257791-26839-4-git-send-email-patrick.keroulas@savoirfairelinux.com
State Superseded
Headers show

Commit Message

Patrick Keroulas May 25, 2018, 2:16 p.m. UTC
From: Damien Riegel <damien.riegel@savoirfairelinux.com>

In order to handle the interlaced formats, the demuxer has only a few
things to do:
 - parse the SDP correctly and propagate the information
 - check the field bit in the RFC4175 header, and pass that information
   to the decoder

In interlaced mode, received data only consist of fields, and their
heights are half of the frame size, so some adjustments must be done
here and there to take that into account.

Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
Signed-off-by: Patrick Keroulas <patrick.keroulas@savoirfairelinux.com>
---
 libavformat/rtpdec_rfc4175.c | 57 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 47 insertions(+), 10 deletions(-)
diff mbox

Patch

diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c
index e9c62c1..b9619be 100644
--- a/libavformat/rtpdec_rfc4175.c
+++ b/libavformat/rtpdec_rfc4175.c
@@ -23,6 +23,7 @@ 
 
 #include "avio_internal.h"
 #include "rtpdec_formats.h"
+#include "libavutil/ancillary_data.h"
 #include "libavutil/avstring.h"
 #include "libavutil/pixdesc.h"
 
@@ -31,6 +32,8 @@  struct PayloadContext {
     int depth;
     int width;
     int height;
+    int interlaced;
+    int field;
 
     uint8_t *frame;
     unsigned int frame_size;
@@ -65,10 +68,18 @@  static int rfc4175_parse_format(AVStream *stream, PayloadContext *data)
         return AVERROR_INVALIDDATA;
     }
 
+    if (data->interlaced)
+        stream->codecpar->field_order = AV_FIELD_TT;
+    else
+        stream->codecpar->field_order = AV_FIELD_PROGRESSIVE;
+
     stream->codecpar->format = pixfmt;
     stream->codecpar->codec_tag = tag;
     stream->codecpar->bits_per_coded_sample = bits_per_sample;
-    data->frame_size = data->width * data->height * data->pgroup / data->xinc;
+    if (data->interlaced)
+        data->frame_size = data->width * (data->height / 2) * data->pgroup / data->xinc;
+    else
+        data->frame_size = data->width * data->height * data->pgroup / data->xinc;
 
     return 0;
 }
@@ -85,6 +96,8 @@  static int rfc4175_parse_fmtp(AVFormatContext *s, AVStream *stream,
         data->sampling = av_strdup(value);
     else if (!strncmp(attr, "depth", 5))
         data->depth = atoi(value);
+    else if (!strncmp(attr, "interlace", 9))
+        data->interlaced = 1;
 
     return 0;
 }
@@ -123,17 +136,38 @@  static int rfc4175_parse_sdp_line(AVFormatContext *s, int st_index,
 static int rfc4175_finalize_packet(PayloadContext *data, AVPacket *pkt,
                                    int stream_index)
 {
-   int ret;
+    AVAncillaryData * ancillary;
+    int ret;
+    uint8_t * side_data;
+
+    pkt->stream_index = stream_index;
+    ret = av_packet_from_data(pkt, data->frame, data->frame_size);
+    if (ret < 0) {
+        av_freep(&data->frame);
+    }
 
-   pkt->stream_index = stream_index;
-   ret = av_packet_from_data(pkt, data->frame, data->frame_size);
-   if (ret < 0) {
-       av_freep(&data->frame);
-   }
+    /* In the packet header, the field is set to 0 for top field
+     * and 1 for bottom */
+     if (data->interlaced) {
+         ancillary = av_ancillary_data_alloc();
+         if (!ancillary)
+             return AVERROR(ENOMEM);
 
-   data->frame = NULL;
+         ancillary->field = data->field ? AV_ANCILLARY_DATA_FIELD_BOTTOM_FIELD
+                                         : AV_ANCILLARY_DATA_FIELD_TOP_FIELD;
 
-   return ret;
+         side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_ANCILLARY,
+                                             sizeof(AVAncillaryData));
+         if (!side_data)
+             return AVERROR(ENOMEM);
+
+         memcpy(side_data, ancillary, sizeof(AVAncillaryData));
+    }
+
+    data->frame = NULL;
+    data->field = 0;
+
+    return ret;
 }
 
 static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
@@ -141,7 +175,7 @@  static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
                                  const uint8_t * buf, int len,
                                  uint16_t seq, int flags)
 {
-    int length, line, offset, cont;
+    int length, line, offset, cont, field;
     const uint8_t *headers = buf + 2; /* skip extended seqnum */
     const uint8_t *payload = buf + 2;
     int payload_len = len - 2;
@@ -194,11 +228,14 @@  static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data,
             return AVERROR_INVALIDDATA;
 
         length = (headers[0] << 8) | headers[1];
+        field = (headers[2] & 0x80);
         line = ((headers[2] & 0x7f) << 8) | headers[3];
         offset = ((headers[4] & 0x7f) << 8) | headers[5];
         cont = headers[4] & 0x80;
         headers += 6;
 
+        data->field = field;
+
         if (length % data->pgroup)
             return AVERROR_INVALIDDATA;