/*****************************************************************************
* ts_scte.c: TS Demux SCTE section decoders/handlers
*****************************************************************************
* Copyright (C) 2004-2016 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#ifndef _DVBPSI_DVBPSI_H_
#include
#endif
#include
#include "ts_pid.h"
#include "ts_scte.h"
#include "ts_streams_private.h"
#include "timestamps.h"
#include
/* EAS Handling */
void SCTE18_Section_Callback( dvbpsi_t *p_handle, const dvbpsi_psi_section_t* p_section,
void *p_base_pid )
{
demux_t *p_demux = (demux_t *) p_handle->p_sys;
ts_pid_t *p_pid = (ts_pid_t *) p_base_pid;
ts_psip_t *p_psip = p_pid->u.p_psip;
if( p_pid->type != TYPE_PSIP || !p_psip->p_eas_es )
return;
for( ; p_section; p_section = p_section->p_next )
{
size_t i_payload = p_section->p_payload_end - p_section->p_payload_start;
const int i_priority = scte18_get_EAS_priority( p_section->p_payload_start, i_payload );
msg_Dbg( p_demux, "Received EAS Alert with priority %d", i_priority );
if( i_priority != EAS_PRIORITY_HIGH && i_priority != EAS_PRIORITY_MAX )
continue;
for( ts_es_t *p_es = p_psip->p_eas_es; p_es; p_es = p_es->p_next )
{
if( !p_es->id && !(p_es->id = es_out_Add( p_demux->out, &p_es->fmt )) )
continue;
const ts_pmt_t *p_pmt = p_es->p_program;
const vlc_tick_t i_date = TimeStampWrapAround( p_pmt->pcr.i_first, p_pmt->pcr.i_current );
block_t *p_block = block_Alloc( p_section->p_payload_end - p_section->p_payload_start );
memcpy( p_block->p_buffer, p_section->p_payload_start, i_payload );
p_block->i_dts = p_block->i_pts = FROM_SCALE( i_date );
es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, p_es->id, true );
es_out_Send( p_demux->out, p_es->id, p_block );
}
}
}
void SCTE27_Section_Callback( demux_t *p_demux,
const uint8_t *p_sectiondata, size_t i_sectiondata,
const uint8_t *p_payloaddata, size_t i_payloaddata,
void *p_pes_cb_data )
{
VLC_UNUSED(p_payloaddata); VLC_UNUSED(i_payloaddata);
ts_stream_t *p_pes = (ts_stream_t *) p_pes_cb_data;
assert( p_pes->p_es->fmt.i_codec == VLC_CODEC_SCTE_27 );
ts_pmt_t *p_pmt = p_pes->p_es->p_program;
vlc_tick_t i_date = p_pmt->pcr.i_current;
block_t *p_content = block_Alloc( i_sectiondata );
if( unlikely(!p_content) || unlikely(!p_pes->p_es->id) )
return;
memcpy( p_content->p_buffer, p_sectiondata, i_sectiondata );
/* We need to extract the truncated pts stored inside the payload */
int i_index = 0;
size_t i_offset = 4;
if( p_content->p_buffer[3] & 0x40 )
{
i_index = ((p_content->p_buffer[7] & 0x0f) << 8) | /* segment number */
p_content->p_buffer[8];
i_offset += 5;
}
if( i_index == 0 && p_content->i_buffer > i_offset + 8 ) /* message body */
{
bool is_immediate = p_content->p_buffer[i_offset + 3] & 0x40;
if( !is_immediate )
{
vlc_tick_t i_display_in = GetDWBE( &p_content->p_buffer[i_offset + 4] );
if( i_display_in < i_date )
i_date = i_display_in + (1ll << 32);
else
i_date = i_display_in;
}
}
p_content->i_dts = p_content->i_pts = VLC_TICK_0 + i_date * 100 / 9;
//PCRFixHandle( p_demux, p_pmt, p_content );
if( p_pes->p_es->id )
es_out_Send( p_demux->out, p_pes->p_es->id, p_content );
else
block_Release( p_content );
}