FFmpeg
rtpdec_vc2hq.c
Go to the documentation of this file.
1 /*
2  * RTP parser for VC-2 HQ payload format (draft version 1) - experimental
3  * Copyright (c) 2016 Thomas Volkert <thomas@netzeal.de>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/intreadwrite.h"
23 #include "libavcodec/dirac.h"
24 
25 #include "avio_internal.h"
26 #include "rtpdec_formats.h"
27 
28 #define RTP_VC2HQ_PL_HEADER_SIZE 4
29 
30 #define DIRAC_DATA_UNIT_HEADER_SIZE 13
31 #define DIRAC_PIC_NR_SIZE 4
32 #define DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT 0xEC
33 
34 struct PayloadContext {
36  uint32_t frame_size;
37  uint32_t frame_nr;
38  uint32_t timestamp;
39  uint32_t last_unit_size;
41 };
42 
43 static const uint8_t start_sequence[] = { 'B', 'B', 'C', 'D' };
44 
45 static void fill_parse_info_header(PayloadContext *pl_ctx, uint8_t *buf,
46  uint8_t parse_code, uint32_t data_unit_size)
47 {
48  memcpy(buf, start_sequence, sizeof(start_sequence));
49  buf[4] = parse_code;
50  AV_WB32(&buf[5], data_unit_size);
51  AV_WB32(&buf[9], pl_ctx->last_unit_size);
52 
53  pl_ctx->last_unit_size = data_unit_size;
54 }
55 
57  const uint8_t *buf, int len)
58 {
59  int res;
61 
63  return res;
64 
65  fill_parse_info_header(pl_ctx, pkt->data, 0x00, size);
66  /* payload of seq. header */
67  memcpy(pkt->data + DIRAC_DATA_UNIT_HEADER_SIZE, buf, len);
68  pkt->stream_index = st->index;
69 
70  pl_ctx->seen_sequence_header = 1;
71 
72  return 0;
73 }
74 
76 {
77  int res;
78  uint32_t size = 0;
79 
80  /* create A/V packet */
82  return res;
83 
84  fill_parse_info_header(pl_ctx, pkt->data, 0x10, size);
85  pkt->stream_index = st->index;
86 
87  pl_ctx->seen_sequence_header = 0;
88 
89  return 0;
90 }
91 
93  AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len,
94  int flags)
95 {
96  int res;
97  uint32_t pic_nr;
98  uint16_t frag_len;
99  uint16_t no_slices;
100 
101  /* sanity check for size of input packet: 16 bytes header in any case as minimum */
102  if (len < 16) {
103  av_log(ctx, AV_LOG_ERROR, "Too short RTP/VC2hq packet, got %d bytes\n", len);
104  return AVERROR_INVALIDDATA;
105  }
106 
107  pic_nr = AV_RB32(&buf[4]);
108  frag_len = AV_RB16(&buf[12]);
109  no_slices = AV_RB16(&buf[14]);
110 
111  if (pl_ctx->buf && pl_ctx->frame_nr != pic_nr) {
112  av_log(ctx, AV_LOG_WARNING, "Dropping buffered RTP/VC2hq packet fragments - non-continuous picture numbers\n");
113  ffio_free_dyn_buf(&pl_ctx->buf);
114  }
115 
116  /* transform parameters? */
117  if (no_slices == 0) {
118  if (len < frag_len + 16) {
119  av_log(ctx, AV_LOG_ERROR, "Too short RTP/VC2hq packet, got %d bytes\n", len);
120  return AVERROR_INVALIDDATA;
121  }
122 
123  /* start frame buffering with new dynamic buffer */
124  if (!pl_ctx->buf) {
125 
126  res = avio_open_dyn_buf(&pl_ctx->buf);
127  if (res < 0)
128  return res;
129 
130  /* reserve memory for frame header */
131  res = avio_seek(pl_ctx->buf, DIRAC_DATA_UNIT_HEADER_SIZE + DIRAC_PIC_NR_SIZE, SEEK_SET);
132  if (res < 0)
133  return res;
134 
135  pl_ctx->frame_nr = pic_nr;
136  pl_ctx->timestamp = *timestamp;
138  }
139 
140  avio_write(pl_ctx->buf, buf + 16 /* skip pl header */, frag_len);
141  pl_ctx->frame_size += frag_len;
142 
143  return AVERROR(EAGAIN);
144  } else {
145  if (len < frag_len + 20) {
146  av_log(ctx, AV_LOG_ERROR, "Too short RTP/VC2hq packet, got %d bytes\n", len);
147  return AVERROR_INVALIDDATA;
148  }
149 
150  /* transform parameters were missed, no buffer available */
151  if (!pl_ctx->buf)
152  return AVERROR_INVALIDDATA;
153 
154  avio_write(pl_ctx->buf, buf + 20 /* skip pl header */, frag_len);
155  pl_ctx->frame_size += frag_len;
156 
157  /* RTP marker bit means: last fragment of current frame was received;
158  otherwise, an additional fragment is needed for the current frame */
159  if (!(flags & RTP_FLAG_MARKER))
160  return AVERROR(EAGAIN);
161  }
162 
163  /* close frame buffering and create A/V packet */
164  res = ff_rtp_finalize_packet(pkt, &pl_ctx->buf, st->index);
165  if (res < 0)
166  return res;
167 
169  AV_WB32(&pkt->data[13], pl_ctx->frame_nr);
170 
171  pl_ctx->frame_size = 0;
172 
173  return 0;
174 }
175 
177  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
178  const uint8_t *buf, int len, uint16_t seq,
179  int flags)
180 {
181  uint8_t parse_code = 0;
182  int res = 0;
183 
184  if (pl_ctx->buf && pl_ctx->timestamp != *timestamp) {
185  av_log(ctx, AV_LOG_WARNING, "Dropping buffered RTP/VC2hq packet fragments - non-continuous timestamps\n");
186  ffio_free_dyn_buf(&pl_ctx->buf);
187  pl_ctx->frame_size = 0;
188  }
189 
190  /* sanity check for size of input packet: needed header data as minimum */
192  av_log(ctx, AV_LOG_ERROR, "Too short RTP/VC2hq packet, got %d bytes\n", len);
193  return AVERROR_INVALIDDATA;
194  }
195 
196  parse_code = buf[3];
197 
198  /* wait for next sequence header? */
199  if (pl_ctx->seen_sequence_header || parse_code == DIRAC_PCODE_SEQ_HEADER) {
200  switch(parse_code) {
201  /* sequence header */
204  break;
205  /* end of sequence */
206  case DIRAC_PCODE_END_SEQ:
207  res = vc2hq_mark_end_of_sequence(pl_ctx, st, pkt);
208  break;
209  /* HQ picture fragment */
211  res = vc2hq_handle_frame_fragment(ctx, pl_ctx, st, pkt, timestamp, buf, len, flags);
212  break;
213  }
214  }
215 
216  return res;
217 }
218 
220  .enc_name = "VC2",
221  .codec_type = AVMEDIA_TYPE_VIDEO,
222  .codec_id = AV_CODEC_ID_DIRAC,
223  .priv_data_size = sizeof(PayloadContext),
225 };
DIRAC_PIC_NR_SIZE
#define DIRAC_PIC_NR_SIZE
Definition: rtpdec_vc2hq.c:31
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
rtpdec_formats.h
AV_CODEC_ID_DIRAC
@ AV_CODEC_ID_DIRAC
Definition: codec_id.h:166
PayloadContext::frame_size
uint32_t frame_size
Definition: rtpdec_vc2hq.c:36
RTP_FLAG_MARKER
#define RTP_FLAG_MARKER
RTP marker bit was set for this packet.
Definition: rtpdec.h:94
AVPacket::data
uint8_t * data
Definition: packet.h:373
RTP_VC2HQ_PL_HEADER_SIZE
#define RTP_VC2HQ_PL_HEADER_SIZE
Definition: rtpdec_vc2hq.c:28
ff_rtp_finalize_packet
int ff_rtp_finalize_packet(AVPacket *pkt, AVIOContext **dyn_buf, int stream_idx)
Close the dynamic buffer and make a packet from it.
Definition: rtpdec.c:997
PayloadContext::timestamp
uint32_t timestamp
current frame timestamp
Definition: rtpdec_ac3.c:31
RTPDynamicProtocolHandler::enc_name
const char * enc_name
Definition: rtpdec.h:117
PayloadContext::frame_nr
uint32_t frame_nr
Definition: rtpdec_vc2hq.c:37
PayloadContext::last_unit_size
uint32_t last_unit_size
Definition: rtpdec_vc2hq.c:39
dirac.h
vc2hq_handle_frame_fragment
static int vc2hq_handle_frame_fragment(AVFormatContext *ctx, PayloadContext *pl_ctx, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, int flags)
Definition: rtpdec_vc2hq.c:92
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
avio_open_dyn_buf
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1471
intreadwrite.h
DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT
#define DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT
Definition: rtpdec_vc2hq.c:32
av_new_packet
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:99
vc2hq_handle_packet
static int vc2hq_handle_packet(AVFormatContext *ctx, PayloadContext *pl_ctx, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
Definition: rtpdec_vc2hq.c:176
ctx
AVFormatContext * ctx
Definition: movenc.c:48
fill_parse_info_header
static void fill_parse_info_header(PayloadContext *pl_ctx, uint8_t *buf, uint8_t parse_code, uint32_t data_unit_size)
Definition: rtpdec_vc2hq.c:45
AVFormatContext
Format I/O context.
Definition: avformat.h:1200
PayloadContext::seen_sequence_header
int seen_sequence_header
Definition: rtpdec_vc2hq.c:40
AV_WB32
#define AV_WB32(p, v)
Definition: intreadwrite.h:419
AVIOContext
Bytestream IO Context.
Definition: avio.h:161
start_sequence
static const uint8_t start_sequence[]
Definition: rtpdec_vc2hq.c:43
size
int size
Definition: twinvq_data.h:10344
AV_RB32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:96
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:232
DIRAC_PCODE_SEQ_HEADER
@ DIRAC_PCODE_SEQ_HEADER
Definition: dirac.h:58
avio_internal.h
len
int len
Definition: vorbis_enc_data.h:426
ffio_free_dyn_buf
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1544
AVStream
Stream structure.
Definition: avformat.h:935
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:260
vc2hq_handle_sequence_header
static int vc2hq_handle_sequence_header(PayloadContext *pl_ctx, AVStream *st, AVPacket *pkt, const uint8_t *buf, int len)
Definition: rtpdec_vc2hq.c:56
DIRAC_PCODE_END_SEQ
@ DIRAC_PCODE_END_SEQ
Definition: dirac.h:59
PayloadContext::buf
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:183
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:943
DIRAC_DATA_UNIT_HEADER_SIZE
#define DIRAC_DATA_UNIT_HEADER_SIZE
Definition: rtpdec_vc2hq.c:30
AVPacket::stream_index
int stream_index
Definition: packet.h:375
parse_packet
static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index, int flush)
Parse a packet, add all split parts to parse_queue.
Definition: demux.c:1105
vc2hq_mark_end_of_sequence
static int vc2hq_mark_end_of_sequence(PayloadContext *pl_ctx, AVStream *st, AVPacket *pkt)
Definition: rtpdec_vc2hq.c:75
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
PayloadContext::frame_size
unsigned int frame_size
Definition: rtpdec_rfc4175.c:38
AVPacket
This structure stores compressed data.
Definition: packet.h:350
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
PayloadContext
RTP/JPEG specific private data.
Definition: rdt.c:83
DIRAC_PCODE_PICTURE_HQ
@ DIRAC_PCODE_PICTURE_HQ
Definition: dirac.h:65
ff_vc2hq_dynamic_handler
const RTPDynamicProtocolHandler ff_vc2hq_dynamic_handler
Definition: rtpdec_vc2hq.c:219
RTPDynamicProtocolHandler
Definition: rtpdec.h:116
AV_RB16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:98