[FFmpeg-devel,v5,2/2] avformat/rtpdec_rfc4175: handle interlace format

Submitted by Patrick Keroulas on May 14, 2018, 7:29 p.m.

Details

Message ID 1526326150-12360-2-git-send-email-patrick.keroulas@savoirfairelinux.com
State New
Headers show

Commit Message

Patrick Keroulas May 14, 2018, 7:29 p.m.
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 | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c
index e9c62c1..9dc7b29 100644
--- a/libavformat/rtpdec_rfc4175.c
+++ b/libavformat/rtpdec_rfc4175.c
@@ -31,6 +31,8 @@  struct PayloadContext {
     int depth;
     int width;
     int height;
+    int interlaced;
+    int field;
 
     uint8_t *frame;
     unsigned int frame_size;
@@ -65,10 +67,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 +95,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;
 }
@@ -131,7 +143,13 @@  static int rfc4175_finalize_packet(PayloadContext *data, AVPacket *pkt,
        av_freep(&data->frame);
    }
 
+   /* In the packet header, the field is set to 0 for top field
+    * and 1 for bottom */
+    if (data->interlaced)
+        pkt->flags |= data->field ? AV_PKT_FLAG_BOTTOM_FIELD : AV_PKT_FLAG_TOP_FIELD;
+
    data->frame = NULL;
+   data->field = 0;
 
    return ret;
 }
@@ -141,7 +159,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 +212,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;