LCOV - code coverage report
Current view: top level - media_tools - saf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 136 161 84.5 %
Date: 2021-04-29 23:48:07 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2005-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / LASeR codec 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/media_dev.h>
      27             : #include <gpac/bitstream.h>
      28             : #include <gpac/thread.h>
      29             : #include <gpac/list.h>
      30             : 
      31             : enum
      32             : {
      33             :         SAF_STREAM_HEADER = 1,
      34             :         SAF_STREAM_HEADER_PERMANENT = 2,
      35             :         SAF_END_OF_STREAM = 3,
      36             :         SAF_ACCESS_UNIT = 4,
      37             :         SAF_END_OF_SESSION = 5,
      38             :         SAF_CACHE_UNIT = 6,
      39             :         SAF_REMOTE_STREAM_HEADER = 7,
      40             : };
      41             : 
      42             : 
      43             : typedef struct
      44             : {
      45             :         char *data;
      46             :         u32 data_size;
      47             :         Bool is_rap;
      48             :         u32 ts;
      49             : } GF_SAFSample;
      50             : 
      51             : typedef struct
      52             : {
      53             :         u32 stream_id;
      54             :         u32 ts_resolution;
      55             :         u32 buffersize_db;
      56             :         u8 stream_type, object_type;
      57             :         char *mime_type;
      58             :         char *remote_url;
      59             : 
      60             :         char *dsi;
      61             :         u32 dsi_len;
      62             : 
      63             :         GF_List *aus;
      64             :         /*0: not declared yet; 1: declared; (1<<1) : done but end of stream not sent yet*/
      65             :         u32 state;
      66             :         u32 last_au_sn, last_au_ts;
      67             : } GF_SAFStream;
      68             : 
      69             : struct __saf_muxer
      70             : {
      71             :         GF_List *streams;
      72             :         /*0: nothing to do, 1: should regenerate, (1<<1): end of session has been sent*/
      73             :         u32 state;
      74             :         GF_Mutex *mx;
      75             : };
      76             : 
      77           1 : GF_SAFMuxer *gf_saf_mux_new()
      78             : {
      79             :         GF_SAFMuxer *mux;
      80           1 :         GF_SAFEALLOC(mux, GF_SAFMuxer);
      81           1 :         if (!mux) return NULL;
      82           1 :         mux->mx = gf_mx_new("SAF");
      83           1 :         mux->streams = gf_list_new();
      84           1 :         return mux;
      85             : }
      86             : 
      87           1 : static void saf_stream_del(GF_SAFStream *str)
      88             : {
      89           1 :         if (str->mime_type) gf_free(str->mime_type);
      90           1 :         if (str->remote_url) gf_free(str->remote_url);
      91           1 :         if (str->dsi) gf_free(str->dsi);
      92             : 
      93           1 :         while (gf_list_count(str->aus)) {
      94           0 :                 GF_SAFSample *au = (GF_SAFSample *)gf_list_last(str->aus);
      95           0 :                 gf_list_rem_last(str->aus);
      96           0 :                 if (au->data) gf_free(au->data);
      97           0 :                 gf_free(au);
      98             :         }
      99           1 :         gf_list_del(str->aus);
     100           1 :         gf_free(str);
     101           1 : }
     102             : 
     103           1 : void gf_saf_mux_del(GF_SAFMuxer *mux)
     104             : {
     105           3 :         while (gf_list_count(mux->streams)) {
     106           1 :                 GF_SAFStream *str = (GF_SAFStream *)gf_list_last(mux->streams);
     107           1 :                 gf_list_rem_last(mux->streams);
     108           1 :                 saf_stream_del(str);
     109             :         }
     110           1 :         gf_list_del(mux->streams);
     111           1 :         gf_mx_del(mux->mx);
     112           1 :         gf_free(mux);
     113           1 : }
     114             : 
     115             : static GFINLINE GF_SAFStream *saf_get_stream(GF_SAFMuxer *mux, u32 stream_id)
     116             : {
     117             :         GF_SAFStream *str;
     118           4 :         u32 i=0;
     119           4 :         while ( (str = (GF_SAFStream *)gf_list_enum(mux->streams, &i)) ) {
     120           3 :                 if (str->stream_id==stream_id) return str;
     121             :         }
     122             :         return NULL;
     123             : }
     124             : 
     125           1 : GF_Err gf_saf_mux_stream_add(GF_SAFMuxer *mux, u32 stream_id, u32 ts_res, u32 buffersize_db, u8 stream_type, u8 object_type, char *mime_type, char *dsi, u32 dsi_len, char *remote_url)
     126             : {
     127             :         GF_SAFStream *str = saf_get_stream(mux, stream_id);
     128           1 :         if (str) return GF_BAD_PARAM;
     129             : 
     130           1 :         if (mux->state == 2) return GF_BAD_PARAM;
     131             : 
     132           1 :         gf_mx_p(mux->mx);
     133             : 
     134           1 :         GF_SAFEALLOC(str, GF_SAFStream);
     135           1 :         if (!str) return GF_OUT_OF_MEM;
     136           1 :         str->stream_id = stream_id;
     137           1 :         str->ts_resolution = ts_res;
     138           1 :         str->buffersize_db = buffersize_db;
     139           1 :         str->stream_type = stream_type;
     140           1 :         str->object_type = object_type;
     141           1 :         if (mime_type) {
     142           0 :                 str->mime_type = gf_strdup(mime_type);
     143           0 :                 str->stream_type = str->object_type = 0xFF;
     144             :         }
     145           1 :         str->dsi_len = dsi_len;
     146           1 :         if (dsi_len) {
     147           1 :                 str->dsi = (char *) gf_malloc(sizeof(char)*dsi_len);
     148             :                 memcpy(str->dsi, dsi, sizeof(char)*dsi_len);
     149             :         }
     150           1 :         if (remote_url) str->remote_url = gf_strdup(remote_url);
     151           1 :         str->aus = gf_list_new();
     152           1 :         mux->state = 0;
     153           1 :         gf_list_add(mux->streams, str);
     154           1 :         gf_mx_v(mux->mx);
     155           1 :         return GF_OK;
     156             : }
     157             : 
     158             : #if 0 //unused
     159             : /*!
     160             :  Removes a stream from the SAF multiplex
     161             : \param mux the SAF multiplexer object
     162             : \param stream_id ID of the SAF stream to remove
     163             : \return error if any
     164             :  */
     165             : GF_Err gf_saf_mux_stream_rem(GF_SAFMuxer *mux, u32 stream_id)
     166             : {
     167             :         GF_SAFStream *str = saf_get_stream(mux, stream_id);
     168             :         if (!str) return GF_BAD_PARAM;
     169             :         if (mux->state == 2) return GF_BAD_PARAM;
     170             : 
     171             :         gf_mx_p(mux->mx);
     172             :         str->state |= 2;
     173             :         mux->state = 1;
     174             :         gf_mx_v(mux->mx);
     175             :         return GF_OK;
     176             : }
     177             : #endif
     178             : 
     179             : 
     180           3 : GF_Err gf_saf_mux_add_au(GF_SAFMuxer *mux, u32 stream_id, u32 CTS, char *data, u32 data_len, Bool is_rap)
     181             : {
     182             :         GF_SAFSample *au;
     183             :         GF_SAFStream *str = saf_get_stream(mux, stream_id);
     184           3 :         if (!str) return GF_BAD_PARAM;
     185           3 :         if (mux->state == 2) return GF_BAD_PARAM;
     186             : 
     187           3 :         gf_mx_p(mux->mx);
     188             : 
     189           3 :         GF_SAFEALLOC(au, GF_SAFSample);
     190           3 :         if (!au) return GF_OUT_OF_MEM;
     191           3 :         au->data = data;
     192           3 :         au->data_size = data_len;
     193           3 :         au->is_rap = is_rap;
     194           3 :         au->ts = CTS;
     195           3 :         mux->state = 1;
     196             : 
     197           3 :         gf_list_add(str->aus, au);
     198           3 :         gf_mx_v(mux->mx);
     199           3 :         return GF_OK;
     200             : }
     201             : 
     202             : 
     203           7 : GF_Err gf_saf_mux_for_time(GF_SAFMuxer *mux, u32 time_ms, Bool force_end_of_session, u8 **out_data, u32 *out_size)
     204             : {
     205             :         u32 i, count, dlen;
     206             :         u8 *data;
     207             :         GF_SAFStream *str;
     208             :         GF_SAFSample*au;
     209             :         GF_BitStream *bs, *payload;
     210             : 
     211           7 :         *out_data = NULL;
     212           7 :         *out_size = 0;
     213             : 
     214           7 :         gf_mx_p(mux->mx);
     215           7 :         if (!force_end_of_session && (mux->state!=1)) {
     216           3 :                 gf_mx_v(mux->mx);
     217           3 :                 return GF_OK;
     218             :         }
     219             : 
     220           4 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     221             : 
     222           4 :         count = gf_list_count(mux->streams);
     223             : 
     224             :         /*1: write all stream headers*/
     225           8 :         for (i=0; i<count; i++) {
     226           4 :                 str = (GF_SAFStream *)gf_list_get(mux->streams, i);
     227           4 :                 if (str->state & 1) continue;
     228             : 
     229           1 :                 au = (GF_SAFSample *)gf_list_get(str->aus, 0);
     230             : 
     231             :                 /*write stream declaration*/
     232           1 :                 payload = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     233           1 :                 gf_bs_write_int(payload, str->remote_url ? SAF_REMOTE_STREAM_HEADER : SAF_STREAM_HEADER, 4);
     234           1 :                 gf_bs_write_int(payload, str->stream_id, 12);
     235             : 
     236           1 :                 gf_bs_write_u8(payload, str->object_type);
     237           1 :                 gf_bs_write_u8(payload, str->stream_type);
     238           1 :                 gf_bs_write_int(payload, str->ts_resolution, 24);
     239           1 :                 gf_bs_write_u16(payload, str->buffersize_db);
     240           1 :                 if (str->mime_type) {
     241           0 :                         u32 len = (u32) strlen(str->mime_type);
     242           0 :                         gf_bs_write_u16(payload, len);
     243           0 :                         gf_bs_write_data(payload, str->mime_type, len);
     244             :                 }
     245           1 :                 if (str->remote_url) {
     246           0 :                         u32 len = (u32) strlen(str->remote_url);
     247           0 :                         gf_bs_write_u16(payload, len);
     248           0 :                         gf_bs_write_data(payload, str->remote_url, len);
     249             :                 }
     250           1 :                 if (str->dsi) {
     251           1 :                         gf_bs_write_data(payload, str->dsi, str->dsi_len);
     252             :                 }
     253             : 
     254           1 :                 gf_bs_get_content(payload, &data, &dlen);
     255           1 :                 gf_bs_del(payload);
     256             : 
     257             :                 /*write SAF packet header*/
     258           1 :                 gf_bs_write_int(bs, 1, 1);
     259           1 :                 gf_bs_write_int(bs, 0, 15);
     260           1 :                 gf_bs_write_int(bs, 0, 1);
     261           1 :                 gf_bs_write_int(bs, 1, 1);
     262           1 :                 gf_bs_write_int(bs, au ? au->ts : 0, 30);
     263           1 :                 gf_bs_write_int(bs, dlen, 16);
     264           1 :                 gf_bs_write_data(bs, data, dlen);
     265           1 :                 gf_free(data);
     266             : 
     267             :                 /*mark as signaled*/
     268           1 :                 str->state |= 1;
     269             :         }
     270             : 
     271             :         /*write all pending AUs*/
     272           3 :         while (1) {
     273             :                 GF_SAFStream *src = NULL;
     274             :                 u32 mux_time = time_ms;
     275             : 
     276          14 :                 for (i=0; i<count; i++) {
     277           7 :                         str = (GF_SAFStream*)gf_list_get(mux->streams, i);
     278           7 :                         au = (GF_SAFSample*)gf_list_get(str->aus, 0);
     279           7 :                         if (au && (au->ts*1000 < mux_time*str->ts_resolution)) {
     280           3 :                                 mux_time = 1000*au->ts/str->ts_resolution;
     281             :                                 src = str;
     282             :                         }
     283             :                 }
     284             : 
     285           7 :                 if (!src) break;
     286             : 
     287           3 :                 au = (GF_SAFSample*)gf_list_get(src->aus, 0);
     288           3 :                 gf_list_rem(src->aus, 0);
     289             : 
     290             :                 /*write stream declaration*/
     291           3 :                 gf_bs_write_int(bs, au->is_rap ? 1 : 0, 1);
     292           3 :                 gf_bs_write_int(bs, src->last_au_sn, 15);
     293           3 :                 gf_bs_write_int(bs, 0, 1);
     294           3 :                 gf_bs_write_int(bs, 1, 1);
     295           3 :                 gf_bs_write_int(bs, au->ts, 30);
     296           3 :                 gf_bs_write_u16(bs, 2+au->data_size);
     297           3 :                 gf_bs_write_int(bs, SAF_ACCESS_UNIT, 4);
     298           3 :                 gf_bs_write_int(bs, src->stream_id, 12);
     299           3 :                 gf_bs_write_data(bs, au->data, au->data_size);
     300             : 
     301           3 :                 src->last_au_sn ++;
     302           3 :                 src->last_au_ts = au->ts;
     303           3 :                 gf_free(au->data);
     304           3 :                 gf_free(au);
     305             :         }
     306             : 
     307             :         /*3: write all end of stream*/
     308           4 :         for (i=0; i<count; i++) {
     309           4 :                 str = (GF_SAFStream*)gf_list_get(mux->streams, i);
     310             :                 /*mark as signaled*/
     311           4 :                 if (!(str->state & 2)) continue;
     312           0 :                 if (gf_list_count(str->aus)) continue;
     313             : 
     314             :                 /*write stream declaration*/
     315           0 :                 gf_bs_write_int(bs, 1, 1);
     316           0 :                 gf_bs_write_int(bs, str->last_au_sn, 15);
     317           0 :                 gf_bs_write_int(bs, 0, 1);
     318           0 :                 gf_bs_write_int(bs, 1, 1);
     319           0 :                 gf_bs_write_int(bs, str->last_au_ts, 30);
     320           0 :                 gf_bs_write_int(bs, 2, 16);
     321           0 :                 gf_bs_write_int(bs, SAF_END_OF_STREAM, 4);
     322           0 :                 gf_bs_write_int(bs, str->stream_id, 12);
     323             : 
     324             :                 /*remove stream*/
     325           0 :                 gf_list_rem(mux->streams, i);
     326           0 :                 i--;
     327           0 :                 count--;
     328           0 :                 saf_stream_del(str);
     329             :         }
     330           4 :         mux->state = 0;
     331           4 :         if (force_end_of_session) {
     332           1 :                 gf_bs_write_int(bs, 1, 1);
     333           1 :                 gf_bs_write_int(bs, 0, 15);
     334           1 :                 gf_bs_write_int(bs, 0, 1);
     335           1 :                 gf_bs_write_int(bs, 1, 1);
     336           1 :                 gf_bs_write_int(bs, 0, 30);
     337           1 :                 gf_bs_write_int(bs, 2, 16);
     338           1 :                 gf_bs_write_int(bs, SAF_END_OF_SESSION, 4);
     339           1 :                 gf_bs_write_int(bs, 0, 12);
     340           1 :                 mux->state = 2;
     341             :         }
     342           4 :         gf_bs_get_content(bs, out_data, out_size);
     343           4 :         gf_bs_del(bs);
     344           4 :         gf_mx_v(mux->mx);
     345           4 :         return GF_OK;
     346             : }

Generated by: LCOV version 1.13