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

libavformat/rtp_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/bitstream.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 "rtp_h264.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 void 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(NULL, AV_LOG_DEBUG, "H.264/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(stream, AV_LOG_ERROR,
00091                    "H.264/RTP 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(NULL, AV_LOG_DEBUG,
00109                    "H.264/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             uint32_t 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) {
00137                 uint8_t *dest= av_malloc(packet_size+sizeof(start_sequence)+codec->extradata_size);
00138                 if(dest)
00139                 {
00140                     if(codec->extradata_size)
00141                     {
00142                         // av_realloc?
00143                         memcpy(dest, codec->extradata, codec->extradata_size);
00144                         av_free(codec->extradata);
00145                     }
00146 
00147                     memcpy(dest+codec->extradata_size, start_sequence, sizeof(start_sequence));
00148                     memcpy(dest+codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
00149 
00150                     codec->extradata= dest;
00151                     codec->extradata_size+= sizeof(start_sequence)+packet_size;
00152                 } else {
00153                     av_log(NULL, AV_LOG_ERROR, "H.264/RTP Unable to allocate memory for extradata!");
00154                 }
00155             }
00156         }
00157         av_log(NULL, AV_LOG_DEBUG, "H.264/RTP Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size);
00158     }
00159 }
00160 
00161 // return 0 on packet, no more left, 1 on packet, 1 on partial packet...
00162 static int h264_handle_packet(AVFormatContext *ctx,
00163                               PayloadContext *data,
00164                               AVStream *st,
00165                               AVPacket * pkt,
00166                               uint32_t * timestamp,
00167                               const uint8_t * buf,
00168                               int len, int flags)
00169 {
00170     uint8_t nal = buf[0];
00171     uint8_t type = (nal & 0x1f);
00172     int result= 0;
00173     uint8_t start_sequence[]= {0, 0, 1};
00174 
00175 #ifdef DEBUG
00176     assert(data);
00177     assert(data->cookie == MAGIC_COOKIE);
00178 #endif
00179     assert(buf);
00180 
00181     if (type >= 1 && type <= 23)
00182         type = 1;              // simplify the case. (these are all the nal types used internally by the h264 codec)
00183     switch (type) {
00184     case 0:                    // undefined;
00185         result= -1;
00186         break;
00187 
00188     case 1:
00189         av_new_packet(pkt, len+sizeof(start_sequence));
00190         memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00191         memcpy(pkt->data+sizeof(start_sequence), buf, len);
00192 #ifdef DEBUG
00193         data->packet_types_received[nal & 0x1f]++;
00194 #endif
00195         break;
00196 
00197     case 24:                   // STAP-A (one packet, multiple nals)
00198         // consume the STAP-A NAL
00199         buf++;
00200         len--;
00201         // first we are going to figure out the total size....
00202         {
00203             int pass= 0;
00204             int total_length= 0;
00205             uint8_t *dst= NULL;
00206 
00207             for(pass= 0; pass<2; pass++) {
00208                 const uint8_t *src= buf;
00209                 int src_len= len;
00210 
00211                 do {
00212                     uint16_t nal_size = AV_RB16(src); // this going to be a problem if unaligned (can it be?)
00213 
00214                     // consume the length of the aggregate...
00215                     src += 2;
00216                     src_len -= 2;
00217 
00218                     if (nal_size <= src_len) {
00219                         if(pass==0) {
00220                             // counting...
00221                             total_length+= sizeof(start_sequence)+nal_size;
00222                         } else {
00223                             // copying
00224                             assert(dst);
00225                             memcpy(dst, start_sequence, sizeof(start_sequence));
00226                             dst+= sizeof(start_sequence);
00227                             memcpy(dst, src, nal_size);
00228 #ifdef DEBUG
00229                             data->packet_types_received[*src & 0x1f]++;
00230 #endif
00231                             dst+= nal_size;
00232                         }
00233                     } else {
00234                         av_log(NULL, AV_LOG_ERROR,
00235                                "nal size exceeds length: %d %d\n", nal_size, src_len);
00236                     }
00237 
00238                     // eat what we handled...
00239                     src += nal_size;
00240                     src_len -= nal_size;
00241 
00242                     if (src_len < 0)
00243                         av_log(NULL, AV_LOG_ERROR,
00244                                "Consumed more bytes than we got! (%d)\n", src_len);
00245                 } while (src_len > 2);      // because there could be rtp padding..
00246 
00247                 if(pass==0) {
00248                     // now we know the total size of the packet (with the start sequences added)
00249                     av_new_packet(pkt, total_length);
00250                     dst= pkt->data;
00251                 } else {
00252                     assert(dst-pkt->data==total_length);
00253                 }
00254             }
00255         }
00256         break;
00257 
00258     case 25:                   // STAP-B
00259     case 26:                   // MTAP-16
00260     case 27:                   // MTAP-24
00261     case 29:                   // FU-B
00262         av_log(NULL, AV_LOG_ERROR,
00263                "Unhandled type (%d) (See RFC for implementation details\n",
00264                type);
00265         result= -1;
00266         break;
00267 
00268     case 28:                   // FU-A (fragmented nal)
00269         buf++;
00270         len--;                  // skip the fu_indicator
00271         {
00272             // these are the same as above, we just redo them here for clarity...
00273             uint8_t fu_indicator = nal;
00274             uint8_t fu_header = *buf;   // read the fu_header.
00275             uint8_t start_bit = fu_header >> 7;
00276 //            uint8_t end_bit = (fu_header & 0x40) >> 6;
00277             uint8_t nal_type = (fu_header & 0x1f);
00278             uint8_t reconstructed_nal;
00279 
00280             // reconstruct this packet's true nal; only the data follows..
00281             reconstructed_nal = fu_indicator & (0xe0);  // the original nal forbidden bit and NRI are stored in this packet's nal;
00282             reconstructed_nal |= nal_type;
00283 
00284             // skip the fu_header...
00285             buf++;
00286             len--;
00287 
00288 #ifdef DEBUG
00289             if (start_bit)
00290                 data->packet_types_received[nal_type]++;
00291 #endif
00292             if(start_bit) {
00293                 // copy in the start sequence, and the reconstructed nal....
00294                 av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len);
00295                 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00296                 pkt->data[sizeof(start_sequence)]= reconstructed_nal;
00297                 memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len);
00298             } else {
00299                 av_new_packet(pkt, len);
00300                 memcpy(pkt->data, buf, len);
00301             }
00302         }
00303         break;
00304 
00305     case 30:                   // undefined
00306     case 31:                   // undefined
00307     default:
00308         av_log(NULL, AV_LOG_ERROR, "Undefined type (%d)", type);
00309         result= -1;
00310         break;
00311     }
00312 
00313     return result;
00314 }
00315 
00316 /* ---------------- public code */
00317 static PayloadContext *h264_new_extradata(void)
00318 {
00319     PayloadContext *data =
00320         av_mallocz(sizeof(PayloadContext) +
00321                    FF_INPUT_BUFFER_PADDING_SIZE);
00322 
00323     if (data) {
00324         data->cookie = MAGIC_COOKIE;
00325     }
00326 
00327     return data;
00328 }
00329 
00330 static void h264_free_extradata(PayloadContext *data)
00331 {
00332 #ifdef DEBUG
00333     int ii;
00334 
00335     for (ii = 0; ii < 32; ii++) {
00336         if (data->packet_types_received[ii])
00337             av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
00338                    data->packet_types_received[ii], ii);
00339     }
00340 #endif
00341 
00342     assert(data);
00343     assert(data->cookie == MAGIC_COOKIE);
00344 
00345     // avoid stale pointers (assert)
00346     data->cookie = DEAD_COOKIE;
00347 
00348     // and clear out this...
00349     av_free(data);
00350 }
00351 
00352 static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
00353                                PayloadContext *h264_data, const char *line)
00354 {
00355     AVStream *stream = s->streams[st_index];
00356     AVCodecContext *codec = stream->codec;
00357     const char *p = line;
00358 
00359     assert(h264_data->cookie == MAGIC_COOKIE);
00360 
00361     if (av_strstart(p, "framesize:", &p)) {
00362         char buf1[50];
00363         char *dst = buf1;
00364 
00365         // remove the protocol identifier..
00366         while (*p && *p == ' ') p++; // strip spaces.
00367         while (*p && *p != ' ') p++; // eat protocol identifier
00368         while (*p && *p == ' ') p++; // strip trailing spaces.
00369         while (*p && *p != '-' && (buf1 - dst) < sizeof(buf1) - 1) {
00370             *dst++ = *p++;
00371         }
00372         *dst = '\0';
00373 
00374         // a='framesize:96 320-240'
00375         // set our parameters..
00376         codec->width = atoi(buf1);
00377         codec->height = atoi(p + 1); // skip the -
00378         codec->pix_fmt = PIX_FMT_YUV420P;
00379     } else if (av_strstart(p, "fmtp:", &p)) {
00380         char attr[256];
00381         char value[4096];
00382 
00383         // remove the protocol identifier..
00384         while (*p && *p == ' ') p++; // strip spaces.
00385         while (*p && *p != ' ') p++; // eat protocol identifier
00386         while (*p && *p == ' ') p++; // strip trailing spaces.
00387 
00388         /* loop on each attribute */
00389         while (rtsp_next_attr_and_value
00390                (&p, attr, sizeof(attr), value, sizeof(value))) {
00391             /* grab the codec extra_data from the config parameter of the fmtp line */
00392             sdp_parse_fmtp_config_h264(stream, h264_data, attr, value);
00393         }
00394     } else if (av_strstart(p, "cliprect:", &p)) {
00395         // could use this if we wanted.
00396     }
00397 
00398     av_set_pts_info(stream, 33, 1, 90000);      // 33 should be right, because the pts is 64 bit? (done elsewhere; this is a one time thing)
00399 
00400     return 0;                   // keep processing it the normal way...
00401 }
00402 
00406 RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
00407     "H264",
00408     CODEC_TYPE_VIDEO,
00409     CODEC_ID_H264,
00410     parse_h264_sdp_line,
00411     h264_new_extradata,
00412     h264_free_extradata,
00413     h264_handle_packet
00414 };

Generated on Tue Nov 4 2014 12:59:24 for ffmpeg by  doxygen 1.7.1