OpenCores
URL https://opencores.org/ocsvn/bluespec-h264/bluespec-h264/trunk

Subversion Repositories bluespec-h264

[/] [bluespec-h264/] [trunk/] [test/] [decoder/] [ldecod/] [src/] [rtp.c] - Blame information for rev 14

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jamey.hick
 
2
/*!
3
 ************************************************************************
4
 * \file  rtp.c
5
 *
6
 * \brief
7
 *    Network Adaptation layer for RTP packets
8
 *
9
 * \author
10
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
11
 *    - Stephan Wenger   <stewe@cs.tu-berlin.de>
12
 ************************************************************************
13
 */
14
 
15
 
16
/*!
17
 
18
  A quick guide to the basics of the RTP decoder implementation
19
 
20
  This module contains the RTP packetization, de-packetization, and the
21
  handling of Parameter Sets, see VCEG-N52 and accompanying documents.
22
  Note: Compound packets are not yet implemented!
23
 
24
  The interface between every NAL (including the RTP NAL) and the VCL is
25
  based on Slices.  The slice data structure on which the VCL is working
26
  is defined in the type Slice (in defines.h).  This type contains the
27
  various fields of the slice header and a partition array, which itself
28
  contains the data partitions the slice consists of.  When data
29
  partitioning is not used, then the whole slice bit string is stored
30
  in partition #0.  When individual partitions are missing, this is
31
  indicated by the size of the bit strings in the partition array.
32
  A complete missing slice (e.g. if a Full Slice packet was lost) is
33
  indicated in a similar way.
34
 
35
  part of the slice structure is the error indication (ei-flag).  The
36
  Ei-flag is set in such cases in which at least one partition of a slice
37
  is damaged or missing.When data partitioning is used, it can happen that
38
  one partition does not contain any symbols but the ei_flag is cleared,
39
  which indicates the intentional missing of symbols of that partition.
40
  A typical example for this behaviour is the Intra Slice, which does not
41
  have symnbols in its type C partition.
42
 
43
  The VCL requests new data to work on through the call of readSliceRTP().
44
  This function calls the main state machine of this module in ReadRTPpaacket().
45
 
46
  ReadRTPpacket assumes, when called, that in an error free environment
47
  a complete slice, consisting of one Full Slice RTP packet, or three Partition
48
  packets of types A, B, C with consecutive sequence numbers, can be read.
49
  It first interprets any trailing SUPP and Parameter Update (Header) packets.
50
  Then it reads one video data packet.  Two cases have to be distinguished:
51
 
52
  1. Type A, or Full Slice packet
53
  In this case, the PictureID and the macroblock mumbers are used to
54
  identify the potential loss of a slice.  A slice is lost, when the
55
  StartMB of the newly read slice header is not equal to the current
56
  state of the decoder
57
    1.1 Loss detected
58
      In this case the last packet is unread (fseek back), and a dummy slice
59
      containing the missing macroblocks is conveyed to the VCL.  At the next
60
      call of the NAL, the same packet is read again, but this time no packet
61
      loss is detected by the above algorithm,
62
    1.2. No loss
63
      In this case it is checked whether a Full Slice packet or a type A data
64
      partition was read
65
        1.2.1 Full Slice
66
          The Full Slice packet is conveyed to the NAL
67
        1.2.2 Type A Partition
68
          The function RTPReadDataPartitionedSlice() is called, which collects
69
          the remaining type B, C partitions and handles them appropriately.
70
 
71
  Paraneter Update Packets (aka Header packets) are in an SDP-like syntax
72
  and are interpreted by a simple parser in the function
73
  RTPInterpretParameterSetPacket()
74
 
75
  Each Slice header contaions the information on which parameter set to be used.
76
  The function RTPSetImgInp() copies the information of the relevant parameter
77
  set in the VCL's global variables img-> and inp->  IMPORTANT: any changes
78
  in the semantics of the img-> and inp-> structure members must be represented
79
  in this function as well!
80
 
81
  A note to the stream-buffer data structure: The stream buffer always contains
82
  only the contents of the partition in question, and not the slice/partition
83
  header.  Decoding has to start at bitoffset 0 (UVLC) or bytreoffset 0 (CABAC).
84
 
85
  The remaining functions should be self-explanatory.
86
 
87
*/
88
 
89
#include "contributors.h"
90
 
91
#include <assert.h>
92
#include <stdlib.h>
93
#include <math.h>
94
#include <string.h>
95
#include <ctype.h>
96
 
97
#include "global.h"
98
#include "errorconcealment.h"
99
#include "rtp.h"
100
#include "fmo.h"
101
#include "sei.h"
102
#include "memalloc.h"
103
 
104
#ifdef WIN32
105
#include <Winsock2.h>
106
#else
107
#include <netinet/in.h>
108
#endif
109
 
110
FILE *bits;
111
 
112
int RTPReadPacket (RTPpacket_t *p, FILE *bits);
113
 
114
/*!
115
 ************************************************************************
116
 * \brief
117
 *    Opens the bit stream file named fn
118
 * \return
119
 *    none
120
 ************************************************************************
121
 */
122
void OpenRTPFile (char *fn)
123
{
124
  if (NULL == (bits=fopen(fn, "rb")))
125
  {
126
    snprintf (errortext, ET_SIZE, "Cannot open RTP file '%s'", input->infile);
127
    error(errortext,500);
128
  }
129
}
130
 
131
 
132
/*!
133
 ************************************************************************
134
 * \brief
135
 *    Closes the bit stream file
136
 ************************************************************************
137
 */
138
void CloseRTPFile()
139
{
140
  fclose (bits);
141
}
142
 
143
 
144
/*!
145
 ************************************************************************
146
 * \brief
147
 *    Fills nalu->buf and nalu->len with the payload of an RTP packet.
148
 *    Other fields in nalu-> remain uninitialized (will be taken care of
149
 *    by NALUtoRBSP.
150
 *
151
 * \return
152
 *     4 in case of ok (for compatibility with GetAnnexbNALU)
153
 *     0 if there is nothing any more to read (EOF)
154
 *    -1 in case of any error
155
 *
156
 ************************************************************************
157
 */
158
 
159
int GetRTPNALU (NALU_t *nalu)
160
{
161
  RTPpacket_t *p;
162
  int ret;
163
 
164
  if ((p=malloc (sizeof (RTPpacket_t)))== NULL)
165
    no_mem_exit ("GetRTPNALU-1");
166
  if ((p->packet=malloc (MAXRTPPACKETSIZE))== NULL)
167
    no_mem_exit ("GetRTPNALU-2");
168
  if ((p->payload=malloc (MAXRTPPACKETSIZE))== NULL)
169
    no_mem_exit ("GetRTPNALU-3");
170
 
171
  ret = RTPReadPacket (p, bits);
172
  nalu->forbidden_bit = 1;
173
  nalu->len = 0;
174
 
175
  if (ret < 0)
176
    return -1;
177
  if (ret == 0)
178
    return 0;
179
 
180
  assert (p->paylen < nalu->max_size);
181
 
182
  nalu->len = p->paylen;
183
  memcpy (nalu->buf, p->payload, p->paylen);
184
  nalu->forbidden_bit = (nalu->buf[0]>>7) & 1;
185
  nalu->nal_reference_idc = (nalu->buf[0]>>5) & 3;
186
  nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;
187
 
188
  free (p->payload);
189
  free (p->packet);
190
  free (p);
191
//  printf ("Got an RTP NALU, len %d, first byte %x\n", nalu->len, nalu->buf[0]);
192
  return nalu->len;
193
}
194
 
195
 
196
 
197
/*!
198
 *****************************************************************************
199
 *
200
 * \brief
201
 *    DecomposeRTPpacket interprets the RTP packet and writes the various
202
 *    structure members of the RTPpacket_t structure
203
 *
204
 * \return
205
 *    0 in case of success
206
 *    negative error code in case of failure
207
 *
208
 * \param p
209
 *    Caller is responsible to allocate enough memory for the generated payload
210
 *    in parameter->payload. Typically a malloc of paclen-12 bytes is sufficient
211
 *
212
 * \par Side effects
213
 *    none
214
 *
215
 * \date
216
 *    30 Spetember 2001
217
 *
218
 * \author
219
 *    Stephan Wenger   stewe@cs.tu-berlin.de
220
 *****************************************************************************/
221
 
222
int DecomposeRTPpacket (RTPpacket_t *p)
223
 
224
{
225
  // consistency check
226
  assert (p->packlen < 65536 - 28);  // IP, UDP headers
227
  assert (p->packlen >= 12);         // at least a complete RTP header
228
  assert (p->payload != NULL);
229
  assert (p->packet != NULL);
230
 
231
  // Extract header information
232
 
233
  p->v  = (p->packet[0] >> 6) & 0x03;
234
  p->p  = (p->packet[0] >> 5) & 0x01;
235
  p->x  = (p->packet[0] >> 4) & 0x01;
236
  p->cc = (p->packet[0] >> 0) & 0x0F;
237
 
238
  p->m  = (p->packet[1] >> 7) & 0x01;
239
  p->pt = (p->packet[1] >> 0) & 0x7F;
240
 
241
  memcpy (&p->seq, &p->packet[2], 2);
242
  p->seq = ntohs((unsigned short)p->seq);
243
 
244
  memcpy (&p->timestamp, &p->packet[4], 4);// change to shifts for unified byte sex
245
  p->timestamp = ntohl(p->timestamp);
246
  memcpy (&p->ssrc, &p->packet[8], 4);// change to shifts for unified byte sex
247
  p->ssrc = ntohl(p->ssrc);
248
 
249
  // header consistency checks
250
  if (     (p->v != 2)
251
        || (p->p != 0)
252
        || (p->x != 0)
253
        || (p->cc != 0) )
254
  {
255
    printf ("DecomposeRTPpacket, RTP header consistency problem, header follows\n");
256
    DumpRTPHeader (p);
257
    return -1;
258
  }
259
  p->paylen = p->packlen-12;
260
  memcpy (p->payload, &p->packet[12], p->paylen);
261
  return 0;
262
}
263
 
264
/*!
265
 *****************************************************************************
266
 *
267
 * \brief
268
 *    DumpRTPHeader is a debug tool that dumps a human-readable interpretation
269
 *    of the RTP header
270
 *
271
 * \return
272
 *    n.a.
273
 * \param p
274
 *    the RTP packet to be dumped, after DecompositeRTPpacket()
275
 *
276
 * \par Side effects
277
 *    Debug output to stdout
278
 *
279
 * \date
280
 *    30 Spetember 2001
281
 *
282
 * \author
283
 *    Stephan Wenger   stewe@cs.tu-berlin.de
284
 *****************************************************************************/
285
 
286
void DumpRTPHeader (RTPpacket_t *p)
287
 
288
{
289
  int i;
290
  for (i=0; i< 30; i++)
291
    printf ("%02x ", p->packet[i]);
292
  printf ("Version (V): %d\n", p->v);
293
  printf ("Padding (P): %d\n", p->p);
294
  printf ("Extension (X): %d\n", p->x);
295
  printf ("CSRC count (CC): %d\n", p->cc);
296
  printf ("Marker bit (M): %d\n", p->m);
297
  printf ("Payload Type (PT): %d\n", p->pt);
298
  printf ("Sequence Number: %d\n", p->seq);
299
  printf ("Timestamp: %d\n", p->timestamp);
300
  printf ("SSRC: %d\n", p->ssrc);
301
}
302
 
303
 
304
/*!
305
 *****************************************************************************
306
 *
307
 * \brief
308
 *    RTPReadPacket reads one packet from file
309
 *
310
 * \return
311
 *    0: EOF
312
 *    negative: error
313
 *    positive: size of RTP packet in bytes
314
 *
315
 * \param p
316
 *    packet data structure, with memory for p->packet allocated
317
 *
318
 * \param bits
319
 *    target file
320
 *
321
 * \par Side effects:
322
 *   - File pointer in bits moved
323
 *   - p->xxx filled by reading and Decomposepacket()
324
 *
325
 * \date
326
 *    04 November, 2001
327
 *
328
 * \author
329
 *    Stephan Wenger, stewe@cs.tu-berlin.de
330
 *****************************************************************************/
331
 
332
int RTPReadPacket (RTPpacket_t *p, FILE *bits)
333
{
334
  int Filepos, intime;
335
 
336
  assert (p != NULL);
337
  assert (p->packet != NULL);
338
  assert (p->payload != NULL);
339
 
340
  Filepos = ftell (bits);
341
  if (4 != fread (&p->packlen,1, 4, bits))
342
    {
343
      return 0;
344
    }
345
 
346
  if (4 != fread (&intime, 1, 4, bits))
347
    {
348
      fseek (bits, Filepos, SEEK_SET);
349
      printf ("RTPReadPacket: File corruption, could not read Timestamp, exit\n");
350
      exit (-1);
351
    }
352
 
353
  assert (p->packlen < MAXRTPPACKETSIZE);
354
 
355
  if (p->packlen != fread (p->packet, 1, p->packlen, bits))
356
    {
357
      printf ("RTPReadPacket: File corruption, could not read %d bytes\n", p->packlen);
358
      exit (-1);    // EOF inidication
359
    }
360
 
361
  if (DecomposeRTPpacket (p) < 0)
362
    {
363
      // this should never happen, hence exit() is ok.  We probably do not want to attempt
364
      // to decode a packet that obviously wasn't generated by RTP
365
      printf ("Errors reported by DecomposePacket(), exit\n");
366
      exit (-700);
367
    }
368
    assert (p->pt == H264PAYLOADTYPE);
369
    assert (p->ssrc == H264SSRC);
370
  return p->packlen;
371
}
372
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.