LCOV - code coverage report
Current view: top level - ietf - rtp_pck_mpeg12.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 93 96 96.9 %
Date: 2021-04-29 23:48:07 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / IETF RTP/RTSP/SDP sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/internal/ietf_dev.h>
      27             : 
      28             : #ifndef GPAC_DISABLE_STREAMING
      29             : 
      30             : #include <gpac/constants.h>
      31             : #include <gpac/avparse.h>
      32             : 
      33        7743 : static void mpa12_do_flush(GP_RTPPacketizer *builder, Bool start_new)
      34             : {
      35             :         u8 *tmp;
      36             :         u32 tmp_size;
      37             :         /*flush*/
      38        7743 :         if (builder->pck_hdr) {
      39        3867 :                 gf_bs_get_content(builder->pck_hdr, &tmp, &tmp_size);
      40        3867 :                 builder->OnData(builder->cbk_obj, tmp, tmp_size, GF_TRUE);
      41        3867 :                 gf_free(tmp);
      42             : 
      43        3867 :                 if (gf_bs_get_size(builder->payload)) {
      44        3867 :                         gf_bs_get_content(builder->payload, &tmp, &tmp_size);
      45        3867 :                         builder->OnData(builder->cbk_obj, tmp, tmp_size, GF_FALSE);
      46        3867 :                         gf_free(tmp);
      47             :                 }
      48             : 
      49        3867 :                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
      50        3867 :                 gf_bs_del(builder->pck_hdr);
      51        3867 :                 gf_bs_del(builder->payload);
      52        3867 :                 builder->pck_hdr = NULL;
      53        3867 :                 builder->payload = NULL;
      54        3867 :                 builder->bytesInPacket = 0;
      55             :         }
      56       11619 :         if (!start_new) return;
      57             : 
      58        3867 :         builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
      59        3867 :         builder->pck_hdr = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
      60        3867 :         builder->payload = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
      61             :         /*create new RTP Packet */
      62        3867 :         builder->rtp_header.SequenceNumber += 1;
      63        3867 :         builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
      64        3867 :         builder->first_sl_in_rtp = GF_TRUE;
      65        3867 :         builder->bytesInPacket = 0;
      66             : }
      67             : 
      68        3876 : GF_Err gp_rtp_builder_do_mpeg12_audio(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize)
      69             : {
      70             :         u32 pck_size;
      71             :         u16 offset;
      72             : 
      73             :         /*if no data flush, if nothing start if not enough space restart*/
      74        3876 :         if (!data || !builder->bytesInPacket || (builder->bytesInPacket + data_size > builder->Path_MTU)) {
      75        3876 :                 mpa12_do_flush(builder, data ? GF_TRUE : GF_FALSE);
      76        3876 :                 if (!data) return GF_OK;
      77             :         }
      78             : 
      79             :         offset = 0;
      80        7734 :         while (data_size) {
      81        3867 :                 if (data_size + 4 < builder->Path_MTU) {
      82             :                         pck_size = data_size;
      83             :                 } else {
      84           0 :                         pck_size = builder->Path_MTU - 4;
      85             :                 }
      86        3867 :                 if (builder->first_sl_in_rtp) {
      87        3867 :                         gf_bs_write_u16(builder->pck_hdr, 0);
      88        3867 :                         gf_bs_write_u16(builder->pck_hdr, offset);
      89        3867 :                         builder->first_sl_in_rtp = GF_FALSE;
      90        3867 :                         builder->bytesInPacket = 2;
      91             :                 }
      92             :                 /*add reference*/
      93        3867 :                 if (builder->OnDataReference)
      94        3828 :                         builder->OnDataReference(builder->cbk_obj, pck_size, offset);
      95             :                 else
      96          39 :                         gf_bs_write_data(builder->payload, data + offset, pck_size);
      97             : 
      98        3867 :                 data_size -= pck_size;
      99        3867 :                 builder->bytesInPacket += pck_size;
     100             :                 /*start new packet if fragmenting*/
     101        3867 :                 if (data_size) {
     102           0 :                         offset += (u16) pck_size;
     103           0 :                         mpa12_do_flush(builder, GF_TRUE);
     104             :                 }
     105             :         }
     106             :         /*if offset or no aggregation*/
     107        3867 :         if (offset || !(builder->flags & GP_RTP_PCK_USE_MULTI) ) mpa12_do_flush(builder, GF_FALSE);
     108             : 
     109             :         return GF_OK;
     110             : }
     111             : 
     112             : #ifndef GPAC_DISABLE_AV_PARSERS
     113             : 
     114             : #define MPEG12_PICTURE_START_CODE         0x00000100
     115             : #define MPEG12_SEQUENCE_START_CODE        0x000001b3
     116             : 
     117        2065 : GF_Err gp_rtp_builder_do_mpeg12_video(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize)
     118             : {
     119             :         u32 startcode, pic_type, max_pck_size, offset, prev_slice, next_slice;
     120             :         Bool start_with_slice, slices_done, got_slice, first_slice, have_seq;
     121             :         u8 mpv_hdr[4];
     122             :         u8 *payload, *buffer;
     123             : 
     124             :         /*no flsuh (no aggregation)*/
     125        2065 :         if (!data) return GF_OK;
     126             : 
     127        2061 :         offset = 0;
     128             :         have_seq = GF_FALSE;
     129             : 
     130             :         while (1) {
     131             :                 u32 oldoffset;
     132        2208 :                 oldoffset = offset;
     133        2208 :                 if (gf_mv12_next_start_code((unsigned char *) data + offset, data_size - offset, &offset, &startcode) < 0)
     134             :                         break;
     135             : 
     136        2208 :                 offset += oldoffset;
     137        2208 :                 if (startcode == MPEG12_SEQUENCE_START_CODE) have_seq = GF_TRUE;
     138        2208 :                 offset += 4;
     139             : 
     140        2208 :                 if (startcode == MPEG12_PICTURE_START_CODE) break;
     141             :         }
     142             : 
     143        2061 :         max_pck_size = builder->Path_MTU - 4;
     144             : 
     145        2061 :         payload = data + offset;
     146        2061 :         pic_type = (payload[1] >> 3) & 0x7;
     147             :         /*first 6 bits (MBZ and T bit) not used*/
     148             :         /*temp ref on 10 bits*/
     149        2061 :         mpv_hdr[0] = (payload[0] >> 6) & 0x3;
     150        2061 :         mpv_hdr[1] = (payload[0] << 2) | ((payload[1] >> 6) & 0x3);
     151        2061 :         mpv_hdr[2] = pic_type;
     152        2061 :         mpv_hdr[3] = 0;
     153             : 
     154        2061 :         if ((pic_type==2) || (pic_type== 3)) {
     155             :                 mpv_hdr[3] = (u8) ((((u32)payload[3]) << 5) & 0xf);
     156        1920 :                 if ((payload[4] & 0x80) != 0) mpv_hdr[3] |= 0x10;
     157        1920 :                 if (pic_type == 3) mpv_hdr[3] |= (payload[4] >> 3) & 0xf;
     158             :         }
     159             : 
     160             :         /*start packet*/
     161        2061 :         builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
     162        2061 :         builder->rtp_header.Marker = 1;
     163        2061 :         builder->rtp_header.SequenceNumber += 1;
     164        2061 :         builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     165             : 
     166             :         buffer = data;
     167             :         prev_slice = 0;
     168        2061 :         start_with_slice = (gf_mv12_next_slice_start((unsigned char *)buffer, offset, data_size, &next_slice) >= 0) ? GF_TRUE : GF_FALSE;
     169        2061 :         offset = 0;
     170             :         slices_done = GF_FALSE;
     171             :         got_slice = start_with_slice;
     172             :         first_slice = GF_TRUE;
     173             : 
     174        9001 :         while (data_size > 0) {
     175             :                 Bool last_pck;
     176             :                 u32 len_to_write;
     177             : 
     178        4879 :                 if (data_size <= max_pck_size) {
     179             :                         len_to_write = data_size;
     180             :                         last_pck = GF_TRUE;
     181             : //                      prev_slice = 0;
     182             :                 } else {
     183        2818 :                         got_slice = (!first_slice && !slices_done && (next_slice <= max_pck_size)) ? GF_TRUE : GF_FALSE;
     184             :                         first_slice = GF_FALSE;
     185             :                         last_pck = GF_FALSE;
     186             : 
     187        6549 :                         while (!slices_done && (next_slice <= max_pck_size)) {
     188             :                                 prev_slice = next_slice;
     189         913 :                                 if (gf_mv12_next_slice_start((unsigned char *)buffer, next_slice + 4, data_size, &next_slice) >= 0) {
     190             :                                         got_slice = GF_TRUE;
     191             :                                 } else {
     192             :                                         slices_done = GF_TRUE;
     193             :                                 }
     194             :                         }
     195        2818 :                         if (got_slice) len_to_write = prev_slice;
     196        2818 :                         else len_to_write = MIN(max_pck_size, data_size);
     197             :                 }
     198             : 
     199        4879 :                 mpv_hdr[2] = pic_type;
     200             : 
     201        4879 :                 if (have_seq) {
     202           3 :                         mpv_hdr[2] |= 0x20;
     203             :                         have_seq = GF_FALSE;
     204             :                 }
     205        4879 :                 if (first_slice) mpv_hdr[2] |= 0x10;
     206             : 
     207        4879 :                 if (got_slice || last_pck) {
     208        2061 :                         mpv_hdr[2] |= 0x08;
     209             : //                      start_with_slice = GF_TRUE;
     210             :                 } else {
     211             : //                      start_with_slice = GF_FALSE;
     212             :                 }
     213             : 
     214        4879 :                 builder->OnData(builder->cbk_obj, mpv_hdr, 4, GF_FALSE);
     215        4879 :                 if (builder->OnDataReference) {
     216        4806 :                         builder->OnDataReference(builder->cbk_obj, len_to_write, offset);
     217             :                 } else {
     218          73 :                         builder->OnData(builder->cbk_obj, data + offset, len_to_write, GF_FALSE);
     219             :                 }
     220             : 
     221        4879 :                 builder->rtp_header.Marker = last_pck ? 1 : 0;
     222        4879 :                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     223             : 
     224        4879 :                 offset += len_to_write;
     225        4879 :                 data_size -= len_to_write;
     226             :                 prev_slice = 0;
     227        4879 :                 next_slice -= len_to_write;
     228        4879 :                 buffer += len_to_write;
     229             : 
     230        4879 :                 if (!last_pck) {
     231        2818 :                         builder->rtp_header.Marker = 0;
     232        2818 :                         builder->rtp_header.SequenceNumber += 1;
     233        2818 :                         builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     234             :                 }
     235             :         }
     236             :         return GF_OK;
     237             : }
     238             : 
     239             : #endif
     240             : 
     241             : #endif /*GPAC_DISABLE_STREAMING*/

Generated by: LCOV version 1.13