• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/rtpdec_h264.c

Go to the documentation of this file.
00001 /*
00002  * RTP H264 Protocol (RFC3984)
00003  * Copyright (c) 2006 Ryan Martell
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00039 #include "libavutil/base64.h"
00040 #include "libavutil/avstring.h"
00041 #include "libavcodec/get_bits.h"
00042 #include "avformat.h"
00043 #include "mpegts.h"
00044 
00045 #include <unistd.h>
00046 #include "network.h"
00047 #include <assert.h>
00048 
00049 #include "rtpdec.h"
00050 #include "rtpdec_formats.h"
00051 
00055 struct PayloadContext {
00056     unsigned long cookie;       
00057 
00058     //sdp setup parameters
00059     uint8_t profile_idc;        
00060     uint8_t profile_iop;        
00061     uint8_t level_idc;          
00062     int packetization_mode;     
00063 #ifdef DEBUG
00064     int packet_types_received[32];
00065 #endif
00066 };
00067 
00068 #define MAGIC_COOKIE (0xdeadbeef)       ///< Cookie for the extradata; to verify we are what we think we are, and that we haven't been freed.
00069 #define DEAD_COOKIE (0xdeaddead)        ///< Cookie for the extradata; once it is freed.
00070 
00071 /* ---------------- private code */
00072 static int sdp_parse_fmtp_config_h264(AVStream * stream,
00073                                       PayloadContext * h264_data,
00074                                       char *attr, char *value)
00075 {
00076     AVCodecContext *codec = stream->codec;
00077     assert(codec->codec_id == CODEC_ID_H264);
00078     assert(h264_data != NULL);
00079 
00080     if (!strcmp(attr, "packetization-mode")) {
00081         av_log(codec, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
00082         h264_data->packetization_mode = atoi(value);
00083         /*
00084            Packetization Mode:
00085            0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
00086            1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
00087            2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A), and 29 (FU-B) are allowed.
00088          */
00089         if (h264_data->packetization_mode > 1)
00090             av_log(codec, AV_LOG_ERROR,
00091                    "Interleaved RTP mode is not supported yet.");
00092     } else if (!strcmp(attr, "profile-level-id")) {
00093         if (strlen(value) == 6) {
00094             char buffer[3];
00095             // 6 characters=3 bytes, in hex.
00096             uint8_t profile_idc;
00097             uint8_t profile_iop;
00098             uint8_t level_idc;
00099 
00100             buffer[0] = value[0]; buffer[1] = value[1]; buffer[2] = '\0';
00101             profile_idc = strtol(buffer, NULL, 16);
00102             buffer[0] = value[2]; buffer[1] = value[3];
00103             profile_iop = strtol(buffer, NULL, 16);
00104             buffer[0] = value[4]; buffer[1] = value[5];
00105             level_idc = strtol(buffer, NULL, 16);
00106 
00107             // set the parameters...
00108             av_log(codec, AV_LOG_DEBUG,
00109                    "RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
00110                    profile_idc, profile_iop, level_idc);
00111             h264_data->profile_idc = profile_idc;
00112             h264_data->profile_iop = profile_iop;
00113             h264_data->level_idc = level_idc;
00114         }
00115     } else  if (!strcmp(attr, "sprop-parameter-sets")) {
00116         uint8_t start_sequence[]= { 0, 0, 1 };
00117         codec->extradata_size= 0;
00118         codec->extradata= NULL;
00119 
00120         while (*value) {
00121             char base64packet[1024];
00122             uint8_t decoded_packet[1024];
00123             int packet_size;
00124             char *dst = base64packet;
00125 
00126             while (*value && *value != ','
00127                    && (dst - base64packet) < sizeof(base64packet) - 1) {
00128                 *dst++ = *value++;
00129             }
00130             *dst++ = '\0';
00131 
00132             if (*value == ',')
00133                 value++;
00134 
00135             packet_size= av_base64_decode(decoded_packet, base64packet, sizeof(decoded_packet));
00136             if (packet_size > 0) {
00137                 uint8_t *dest = av_malloc(packet_size + sizeof(start_sequence) +
00138                                          codec->extradata_size +
00139                                          FF_INPUT_BUFFER_PADDING_SIZE);
00140                 if(dest)
00141                 {
00142                     if(codec->extradata_size)
00143                     {
00144                         // av_realloc?
00145                         memcpy(dest, codec->extradata, codec->extradata_size);
00146                         av_free(codec->extradata);
00147                     }
00148 
00149                     memcpy(dest+codec->extradata_size, start_sequence, sizeof(start_sequence));
00150                     memcpy(dest+codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
00151                     memset(dest+codec->extradata_size+sizeof(start_sequence)+
00152                            packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00153 
00154                     codec->extradata= dest;
00155                     codec->extradata_size+= sizeof(start_sequence)+packet_size;
00156                 } else {
00157                     av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
00158                     return AVERROR(ENOMEM);
00159                 }
00160             }
00161         }
00162         av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size);
00163     }
00164     return 0;
00165 }
00166 
00167 // return 0 on packet, no more left, 1 on packet, 1 on partial packet...
00168 static int h264_handle_packet(AVFormatContext *ctx,
00169                               PayloadContext *data,
00170                               AVStream *st,
00171                               AVPacket * pkt,
00172                               uint32_t * timestamp,
00173                               const uint8_t * buf,
00174                               int len, int flags)
00175 {
00176     uint8_t nal = buf[0];
00177     uint8_t type = (nal & 0x1f);
00178     int result= 0;
00179     uint8_t start_sequence[]= {0, 0, 1};
00180 
00181 #ifdef DEBUG
00182     assert(data);
00183     assert(data->cookie == MAGIC_COOKIE);
00184 #endif
00185     assert(buf);
00186 
00187     if (type >= 1 && type <= 23)
00188         type = 1;              // simplify the case. (these are all the nal types used internally by the h264 codec)
00189     switch (type) {
00190     case 0:                    // undefined, but pass them through
00191     case 1:
00192         av_new_packet(pkt, len+sizeof(start_sequence));
00193         memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00194         memcpy(pkt->data+sizeof(start_sequence), buf, len);
00195 #ifdef DEBUG
00196         data->packet_types_received[nal & 0x1f]++;
00197 #endif
00198         break;
00199 
00200     case 24:                   // STAP-A (one packet, multiple nals)
00201         // consume the STAP-A NAL
00202         buf++;
00203         len--;
00204         // first we are going to figure out the total size....
00205         {
00206             int pass= 0;
00207             int total_length= 0;
00208             uint8_t *dst= NULL;
00209 
00210             for(pass= 0; pass<2; pass++) {
00211                 const uint8_t *src= buf;
00212                 int src_len= len;
00213 
00214                 do {
00215                     uint16_t nal_size = AV_RB16(src); // this going to be a problem if unaligned (can it be?)
00216 
00217                     // consume the length of the aggregate...
00218                     src += 2;
00219                     src_len -= 2;
00220 
00221                     if (nal_size <= src_len) {
00222                         if(pass==0) {
00223                             // counting...
00224                             total_length+= sizeof(start_sequence)+nal_size;
00225                         } else {
00226                             // copying
00227                             assert(dst);
00228                             memcpy(dst, start_sequence, sizeof(start_sequence));
00229                             dst+= sizeof(start_sequence);
00230                             memcpy(dst, src, nal_size);
00231 #ifdef DEBUG
00232                             data->packet_types_received[*src & 0x1f]++;
00233 #endif
00234                             dst+= nal_size;
00235                         }
00236                     } else {
00237                         av_log(ctx, AV_LOG_ERROR,
00238                                "nal size exceeds length: %d %d\n", nal_size, src_len);
00239                     }
00240 
00241                     // eat what we handled...
00242                     src += nal_size;
00243                     src_len -= nal_size;
00244 
00245                     if (src_len < 0)
00246                         av_log(ctx, AV_LOG_ERROR,
00247                                "Consumed more bytes than we got! (%d)\n", src_len);
00248                 } while (src_len > 2);      // because there could be rtp padding..
00249 
00250                 if(pass==0) {
00251                     // now we know the total size of the packet (with the start sequences added)
00252                     av_new_packet(pkt, total_length);
00253                     dst= pkt->data;
00254                 } else {
00255                     assert(dst-pkt->data==total_length);
00256                 }
00257             }
00258         }
00259         break;
00260 
00261     case 25:                   // STAP-B
00262     case 26:                   // MTAP-16
00263     case 27:                   // MTAP-24
00264     case 29:                   // FU-B
00265         av_log(ctx, AV_LOG_ERROR,
00266                "Unhandled type (%d) (See RFC for implementation details\n",
00267                type);
00268         result= -1;
00269         break;
00270 
00271     case 28:                   // FU-A (fragmented nal)
00272         buf++;
00273         len--;                  // skip the fu_indicator
00274         {
00275             // these are the same as above, we just redo them here for clarity...
00276             uint8_t fu_indicator = nal;
00277             uint8_t fu_header = *buf;   // read the fu_header.
00278             uint8_t start_bit = fu_header >> 7;
00279 //            uint8_t end_bit = (fu_header & 0x40) >> 6;
00280             uint8_t nal_type = (fu_header & 0x1f);
00281             uint8_t reconstructed_nal;
00282 
00283             // reconstruct this packet's true nal; only the data follows..
00284             reconstructed_nal = fu_indicator & (0xe0);  // the original nal forbidden bit and NRI are stored in this packet's nal;
00285             reconstructed_nal |= nal_type;
00286 
00287             // skip the fu_header...
00288             buf++;
00289             len--;
00290 
00291 #ifdef DEBUG
00292             if (start_bit)
00293                 data->packet_types_received[nal_type]++;
00294 #endif
00295             if(start_bit) {
00296                 // copy in the start sequence, and the reconstructed nal....
00297                 av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len);
00298                 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00299                 pkt->data[sizeof(start_sequence)]= reconstructed_nal;
00300                 memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len);
00301             } else {
00302                 av_new_packet(pkt, len);
00303                 memcpy(pkt->data, buf, len);
00304             }
00305         }
00306         break;
00307 
00308     case 30:                   // undefined
00309     case 31:                   // undefined
00310     default:
00311         av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)", type);
00312         result= -1;
00313         break;
00314     }
00315 
00316     pkt->stream_index = st->index;
00317 
00318     return result;
00319 }
00320 
00321 /* ---------------- public code */
00322 static PayloadContext *h264_new_context(void)
00323 {
00324     PayloadContext *data =
00325         av_mallocz(sizeof(PayloadContext) +
00326                    FF_INPUT_BUFFER_PADDING_SIZE);
00327 
00328     if (data) {
00329         data->cookie = MAGIC_COOKIE;
00330     }
00331 
00332     return data;
00333 }
00334 
00335 static void h264_free_context(PayloadContext *data)
00336 {
00337 #ifdef DEBUG
00338     int ii;
00339 
00340     for (ii = 0; ii < 32; ii++) {
00341         if (data->packet_types_received[ii])
00342             av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
00343                    data->packet_types_received[ii], ii);
00344     }
00345 #endif
00346 
00347     assert(data);
00348     assert(data->cookie == MAGIC_COOKIE);
00349 
00350     // avoid stale pointers (assert)
00351     data->cookie = DEAD_COOKIE;
00352 
00353     // and clear out this...
00354     av_free(data);
00355 }
00356 
00357 static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
00358                                PayloadContext *h264_data, const char *line)
00359 {
00360     AVStream *stream = s->streams[st_index];
00361     AVCodecContext *codec = stream->codec;
00362     const char *p = line;
00363 
00364     assert(h264_data->cookie == MAGIC_COOKIE);
00365 
00366     if (av_strstart(p, "framesize:", &p)) {
00367         char buf1[50];
00368         char *dst = buf1;
00369 
00370         // remove the protocol identifier..
00371         while (*p && *p == ' ') p++; // strip spaces.
00372         while (*p && *p != ' ') p++; // eat protocol identifier
00373         while (*p && *p == ' ') p++; // strip trailing spaces.
00374         while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) {
00375             *dst++ = *p++;
00376         }
00377         *dst = '\0';
00378 
00379         // a='framesize:96 320-240'
00380         // set our parameters..
00381         codec->width = atoi(buf1);
00382         codec->height = atoi(p + 1); // skip the -
00383         codec->pix_fmt = PIX_FMT_YUV420P;
00384     } else if (av_strstart(p, "fmtp:", &p)) {
00385         return ff_parse_fmtp(stream, h264_data, p, sdp_parse_fmtp_config_h264);
00386     } else if (av_strstart(p, "cliprect:", &p)) {
00387         // could use this if we wanted.
00388     }
00389 
00390     return 0;                   // keep processing it the normal way...
00391 }
00392 
00396 RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
00397     .enc_name         = "H264",
00398     .codec_type       = AVMEDIA_TYPE_VIDEO,
00399     .codec_id         = CODEC_ID_H264,
00400     .parse_sdp_a_line = parse_h264_sdp_line,
00401     .alloc            = h264_new_context,
00402     .free             = h264_free_context,
00403     .parse_packet     = h264_handle_packet
00404 };
Generated on Fri Feb 1 2013 14:34:54 for FFmpeg by doxygen 1.7.1