Beispiel #1
0
static char *encode_avc1_header(uint8_t *p, unsigned int len, int packet_mode)
{
    int i, cnt, nalsize;
    uint8_t *q = p;
    char *sprop = NULL;
    cnt = *(p+5) & 0x1f; // Number of sps
    p += 6;

    for (i = 0; i < cnt; i++) {
        if (p > q + len)
            goto err_alloc;
        nalsize = RB16(p); //buf_size
        p += 2;
        fnc_log(FNC_LOG_VERBOSE, "[h264] nalsize %d", nalsize);
        if (i == 0) {
            gchar *out = g_strdup_printf("profile-level-id=%02x%02x%02x; "
                                  "packetization-mode=%d; ",
                                  p[0], p[1], p[2], packet_mode);
	    gchar *buf = g_base64_encode(p, nalsize);
            sprop = g_strdup_printf("%ssprop-parameter-sets=%s", out, buf);
	    g_free(buf);
            g_free(out);
        } else {
            gchar *buf = g_base64_encode(p, nalsize);
            gchar *out = g_strdup_printf("%s,%s", sprop, buf);
            g_free(sprop);
	    g_free(buf);
            sprop = out;
        }
        p += nalsize;
    }
    // Decode pps from avcC
    cnt = *(p++); // Number of pps
    fnc_log(FNC_LOG_VERBOSE, "[h264] pps %d", cnt);

    for (i = 0; i < cnt; i++) {
        gchar *out, *buf;

        if (p > q + len)
            goto err_alloc;
        nalsize = RB16(p);
        p += 2;
        fnc_log(FNC_LOG_VERBOSE, "[h264] nalsize %d", nalsize);
	buf = g_base64_encode(p, nalsize);
        out = g_strdup_printf("%s,%s",sprop, buf);
        g_free(sprop);
	g_free(buf);
        sprop = out;
        p += nalsize;
    }

    return sprop;

    err_alloc:
        if (sprop) g_free(sprop);
    return NULL;
}
Beispiel #2
0
SR_PRIV int maynuo_m97_get_model_version(struct sr_modbus_dev_inst *modbus,
		uint16_t *model, uint16_t *version)
{
	uint16_t registers[2];
	int ret;
	ret = sr_modbus_read_holding_registers(modbus, MODEL, 2, registers);
	*model   = RB16(registers+0);
	*version = RB16(registers+1);
	return ret;
}
Beispiel #3
0
int write_section(struct lib_ccx_ctx *ctx, struct ts_payload *payload, unsigned char*buf, int size, int pos)
{
	if (payload->pesstart)
	{
		memcpy(payload->section_buf, buf, size);
		payload->section_index = size;
		payload->section_size = -1;
	}
	else
	{
		memcpy(payload->section_buf + payload->section_index, buf, size);
		payload->section_index += size;

	}
	if(payload->section_size == -1 && payload->section_index >= 3)
		payload->section_size = (RB16(payload->section_buf + 1) & 0xfff) + 3 ;

	if(payload->section_index >= (unsigned)payload->section_size)
	{
		if(parse_PMT(ctx, payload->section_buf,payload->section_size,pos))
			return 1;
	}
	return 0;

}
Beispiel #4
0
SR_PRIV int maynuo_m97_get_mode(struct sr_modbus_dev_inst *modbus,
		enum maynuo_m97_mode *mode)
{
	uint16_t registers[1];
	int ret;
	ret = sr_modbus_read_holding_registers(modbus, SETMODE, 1, registers);
	*mode = RB16(registers) & 0xFF;
	return ret;
}
static __inline unsigned int bytestream_get_be16(const uint8_t **b)
{
	(*b) += 2;
	return RB16(*b - 2);
}
Beispiel #6
0
SR_PRIV int gwinstek_gds_800_receive_data(int fd, int revents, void *cb_data)
{
	struct sr_dev_inst *sdi;
	struct sr_scpi_dev_inst *scpi;
	struct dev_context *devc;
	struct sr_datafeed_packet packet;
	struct sr_datafeed_analog_old analog;
	char command[32];
	char *response;
	float volts_per_division;
	int num_samples, i;
	float samples[MAX_SAMPLES];
	uint32_t sample_rate;
	char *end_ptr;

	(void)fd;

	if (!(sdi = cb_data))
		return TRUE;

	if (!(devc = sdi->priv))
		return TRUE;

	scpi = sdi->conn;

	if (!(revents == G_IO_IN || revents == 0))
		return TRUE;

	switch (devc->state) {
	case START_ACQUISITION:
		if (sr_scpi_send(scpi, ":TRIG:MOD 3") != SR_OK) {
			sr_err("Failed to set trigger mode to SINGLE.");
			sdi->driver->dev_acquisition_stop(sdi);
			return TRUE;
		}
		if (sr_scpi_send(scpi, ":STOP") != SR_OK) {
			sr_err("Failed to put the trigger system into STOP state.");
			sdi->driver->dev_acquisition_stop(sdi);
			return TRUE;
		}
		if (sr_scpi_send(scpi, ":RUN") != SR_OK) {
			sr_err("Failed to put the trigger system into RUN state.");
			sdi->driver->dev_acquisition_stop(sdi);
			return TRUE;
		}

		devc->cur_acq_channel = 0;
		devc->state = START_TRANSFER_OF_CHANNEL_DATA;
		break;
	case START_TRANSFER_OF_CHANNEL_DATA:
		if (((struct sr_channel *)g_slist_nth_data(sdi->channels, devc->cur_acq_channel))->enabled) {
			if (sr_scpi_send(scpi, ":ACQ%d:MEM?", devc->cur_acq_channel+1) != SR_OK) {
				sr_err("Failed to acquire memory.");
				sdi->driver->dev_acquisition_stop(sdi);
				return TRUE;
			}
			if (sr_scpi_read_begin(scpi) != SR_OK) {
				sr_err("Could not begin reading SCPI response.");
				sdi->driver->dev_acquisition_stop(sdi);
				return TRUE;
			}
			devc->state = WAIT_FOR_TRANSFER_OF_BEGIN_TRANSMISSION_COMPLETE;
			devc->cur_rcv_buffer_position = 0;
		} else {
			/* All channels acquired. */
			if (devc->cur_acq_channel == ANALOG_CHANNELS - 1) {
				sr_spew("All channels acquired.");

				if (devc->cur_acq_frame == devc->frame_limit - 1) {
					/* All frames accquired. */
					sr_spew("All frames acquired.");
					
					sdi->driver->dev_acquisition_stop(sdi);
					return TRUE;
				} else {
					/* Start acquiring next frame. */
					if (devc->df_started) {
						packet.type = SR_DF_FRAME_END;
						sr_session_send(sdi, &packet);
						
						packet.type = SR_DF_FRAME_BEGIN;
						sr_session_send(sdi, &packet);
					}

					devc->cur_acq_frame++;
					devc->state = START_ACQUISITION;
				}
			} else {
				/* Start acquiring next channel. */
				devc->cur_acq_channel++;
			}
		}
		break;
	case WAIT_FOR_TRANSFER_OF_BEGIN_TRANSMISSION_COMPLETE:
		if (read_data(sdi, scpi, devc, 1) == SR_OK) {
			if (devc->rcv_buffer[0] == '#')
				devc->state = WAIT_FOR_TRANSFER_OF_DATA_SIZE_DIGIT_COMPLETE;
		}
		break;
	case WAIT_FOR_TRANSFER_OF_DATA_SIZE_DIGIT_COMPLETE:
		if (read_data(sdi, scpi, devc, 1) == SR_OK) {
			if (devc->rcv_buffer[0] != '4' &&
				devc->rcv_buffer[0] != '5' &&
				devc->rcv_buffer[0] != '6') {
				sr_err("Data size digits is not 4, 5 or 6 but "
				       "'%c'.", devc->rcv_buffer[0]);
				sdi->driver->dev_acquisition_stop(sdi);
				return TRUE;
			} else {
				devc->data_size_digits = devc->rcv_buffer[0] - '0';
				devc->state = WAIT_FOR_TRANSFER_OF_DATA_SIZE_COMPLETE;
			}
		}
		break;
	case WAIT_FOR_TRANSFER_OF_DATA_SIZE_COMPLETE:
		if (read_data(sdi, scpi, devc, devc->data_size_digits) == SR_OK) {
			devc->rcv_buffer[devc->data_size_digits] = 0;
			if (sr_atoi(devc->rcv_buffer, &devc->data_size) != SR_OK) {
				sr_err("Could not parse data size '%s'", devc->rcv_buffer);
				sdi->driver->dev_acquisition_stop(sdi);
				return TRUE;
			} else
				devc->state = WAIT_FOR_TRANSFER_OF_SAMPLE_RATE_COMPLETE;
		}
		break;
	case WAIT_FOR_TRANSFER_OF_SAMPLE_RATE_COMPLETE:
		if (read_data(sdi, scpi, devc, sizeof(float)) == SR_OK) {
			/*
			 * Contrary to the documentation, this field is
			 * transfered with most significant byte first!
			 */
			sample_rate = RB32(devc->rcv_buffer);
			memcpy(&devc->sample_rate, &sample_rate, sizeof(float));
			devc->state = WAIT_FOR_TRANSFER_OF_CHANNEL_INDICATOR_COMPLETE;

			if (!devc->df_started) {
				std_session_send_df_header(sdi);

				packet.type = SR_DF_FRAME_BEGIN;
				sr_session_send(sdi, &packet);

				devc->df_started = TRUE;
			}
		}
		break;
	case WAIT_FOR_TRANSFER_OF_CHANNEL_INDICATOR_COMPLETE:
		if (read_data(sdi, scpi, devc, 1) == SR_OK)
			devc->state = WAIT_FOR_TRANSFER_OF_RESERVED_DATA_COMPLETE;
		break;
	case WAIT_FOR_TRANSFER_OF_RESERVED_DATA_COMPLETE:
		if (read_data(sdi, scpi, devc, 3) == SR_OK)
			devc->state = WAIT_FOR_TRANSFER_OF_CHANNEL_DATA_COMPLETE;
		break;
	case WAIT_FOR_TRANSFER_OF_CHANNEL_DATA_COMPLETE:
		if (read_data(sdi, scpi, devc, devc->data_size - 8) == SR_OK) {
			/* Fetch data needed for conversion from device. */
			snprintf(command, sizeof(command), ":CHAN%d:SCAL?",
					devc->cur_acq_channel + 1);
			if (sr_scpi_get_string(scpi, command, &response) != SR_OK) {
				sr_err("Failed to get volts per division.");
				sdi->driver->dev_acquisition_stop(sdi);
				return TRUE;
			}
			volts_per_division = g_ascii_strtod(response, &end_ptr);
			if (!strcmp(end_ptr, "mV"))
				volts_per_division *= 1.e-3;
			g_free(response);

			num_samples = (devc->data_size - 8) / 2;
			sr_spew("Received %d number of samples from channel "
				"%d.", num_samples, devc->cur_acq_channel + 1);

			/* Convert data. */
			for (i = 0; i < num_samples; i++)
				samples[i] = ((float) ((int16_t) (RB16(&devc->rcv_buffer[i*2])))) / 256. * VERTICAL_DIVISIONS * volts_per_division;

			/* Fill frame. */
			analog.channels = g_slist_append(NULL, g_slist_nth_data(sdi->channels, devc->cur_acq_channel));
			analog.num_samples = num_samples;
			analog.data = samples;
			analog.mq = SR_MQ_VOLTAGE;
			analog.unit = SR_UNIT_VOLT;
			analog.mqflags = 0;
			packet.type = SR_DF_ANALOG_OLD;
			packet.payload = &analog;
			sr_session_send(sdi, &packet);
			g_slist_free(analog.channels);

			/* All channels acquired. */
			if (devc->cur_acq_channel == ANALOG_CHANNELS - 1) {
				sr_spew("All channels acquired.");

				if (devc->cur_acq_frame == devc->frame_limit - 1) {
					/* All frames acquired. */
					sr_spew("All frames acquired.");
					sdi->driver->dev_acquisition_stop(sdi);
					return TRUE;
				} else {
					/* Start acquiring next frame. */
					if (devc->df_started) {
						packet.type = SR_DF_FRAME_END;
						sr_session_send(sdi, &packet);
						
						packet.type = SR_DF_FRAME_BEGIN;
						sr_session_send(sdi, &packet);
					}
					devc->cur_acq_frame++;
					devc->state = START_ACQUISITION;
				}
			} else {
				/* Start acquiring next channel. */
				devc->state = START_TRANSFER_OF_CHANNEL_DATA;
				devc->cur_acq_channel++;
				return TRUE;
			}
		}
		break;
	}

	return TRUE;
}
int parse_PMT (struct ccx_demuxer *ctx, unsigned char *buf, int len,  struct program_info *pinfo)
{
	int must_flush = 0;
	int ret = 0;
	unsigned char desc_len = 0;
	unsigned char *sbuf = buf;
	unsigned int olen = len;
	uint32_t crc;

	uint8_t table_id;
	uint16_t section_length;
	uint16_t program_number;
	uint8_t version_number;
	uint8_t current_next_indicator;
	uint8_t section_number;
	uint8_t last_section_number;

	uint16_t pi_length;

	crc = (*(int32_t*)(sbuf+olen-4));
	table_id = buf[0];

	/* TO-DO: We're currently parsing the PMT making assumptions that there's only one section with table_id=2,
	but that doesn't have to be the case. There's a sample (friends_tbs.ts) that shows a previous section with
	table_id = 0xc0. I can't find any place that says that 0xc0 (Program Information Table) must come before
	table_id = 2, so we should process sections in any order.
	Check https://github.com/CCExtractor/ccextractor/issues/385 for more info
	*/
	if (table_id == 0xC0)
	{
		/*
		 * Acc to System Information for Satellite Distribution
		 * of Digital Television for Cable and MMDS (ANSI/SCTE 57 2003 )
		 * PROGRAM INFORMATION Table found in PMT
		 */
		dbg_print(CCX_DMT_PARSE, "PMT: PROGRAM INFORMATION Table need implementation");
		// For now, just parse its length and remove it from the buffer
		unsigned c0length = (buf[1] << 8 | buf[2]) & 0xFFF; // 12 bytes
		dbg_print(CCX_DMT_PARSE, "Program information table length: %u", c0length);
		memmove(buf, buf + c0length + 3, len - c0length -3); // First 3 bytes are for the table_id and the length, don't count
		table_id = buf[0];
		// return 0;
	}
	else if (table_id == 0xC1)
	{
                //SCTE 57 2003
		dbg_print(CCX_DMT_PARSE, "PMT: PROGRAM NAME Table need implementation");
		unsigned c0length = (buf[1] << 8 | buf[2]) & 0xFFF; // 12 bytes
		dbg_print(CCX_DMT_PARSE, "Program name message length: %u", c0length);
		memmove(buf, buf + c0length + 3, len - c0length - 3); // First 3 bytes are for the table_id and the length, don't count
		table_id = buf[0];
		//return 0;
	}
	else if(table_id != 0x2)
	{
		mprint("Please Report: Unknown table id in PMT expected 0x02 found 0x%X\n", table_id);
		return 0;
	}

	section_length = (((buf[1] & 0x0F) << 8)| buf[2]);
	if(section_length > (len - 3))
	{
		return 0; //We don't have the full section yet. We will parse again when we have it.
	}

	program_number = ((buf[3] << 8)	| buf[4]);
	version_number = (buf[5] & 0x3E) >> 1;

	current_next_indicator = buf[5] & 0x01;
	// This table is not active, no need to evaluate
	if (!current_next_indicator)
		return 0;

	memcpy (pinfo->saved_section, buf, len);

	if (pinfo->analysed_PMT_once == CCX_TRUE && pinfo->version == version_number)
	{
		if (pinfo->version == version_number)
		{
			/* Same Version number and there was valid or similar CRC last time */
			if ( pinfo->valid_crc == CCX_TRUE || pinfo->crc == crc )
				return 0;

		}
		else if ( (pinfo->version+1)%32 != version_number)
			mprint("TS PMT:Glitch in version number incremnt");
	}
	pinfo->version = version_number;


	section_number = buf[6];
	last_section_number = buf[7];
	if ( last_section_number > 0 )
	{
		mprint("Long PMTs are not supported - skipped.\n");
		return 0;
	}

	pinfo->pcr_pid = (((buf[8] & 0x1F) << 8)
			| buf[9]);
	pi_length = (((buf[10] & 0x0F) << 8)
			| buf[11]);

	if( 12 + pi_length >  len )
	{
		// If we would support long PMTs, this would be wrong.
		mprint("program_info_length cannot be longer than the payload_length - skipped\n");
		return 0;
	}
	buf += 12 + pi_length;
	len -= (12 + pi_length);


	unsigned stream_data = section_length - 9 - pi_length - 4; // prev. bytes and CRC

	dbg_print(CCX_DMT_PARSE, "Read PMT packet  (id: %u) program number: %u\n",
			table_id, program_number);
	dbg_print(CCX_DMT_PARSE, "  section length: %u  number: %u  last: %u\n",
			section_length, section_number, last_section_number);
	dbg_print(CCX_DMT_PARSE, "  version_number: %u  current_next_indicator: %u\n",
			version_number, current_next_indicator);
	dbg_print(CCX_DMT_PARSE, "  PCR_PID: %u  data length: %u  payload_length: %u\n",
			pinfo->pcr_pid, stream_data, len);

	if (!pmt_warning_shown && stream_data+4 > len )
	{
		dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Probably parsing incomplete PMT, expected data longer than available payload.\n");
		pmt_warning_shown=1;
	}
	// Make a note of the program number for all PIDs, so we can report it later
	for( unsigned i=0; i < stream_data && (i+4)<len; i+=5)
	{
		enum ccx_stream_type stream_type = buf[i];
		unsigned elementary_PID = (((buf[i+1] & 0x1F) << 8)
				| buf[i+2]);
		unsigned ES_info_length = (((buf[i+3] & 0x0F) << 8)
				| buf[i+4]);
		if (ctx->PIDs_programs[elementary_PID]==NULL)
		{
			ctx->PIDs_programs[elementary_PID]=(struct PMT_entry *) malloc (sizeof (struct PMT_entry));
			if (ctx->PIDs_programs[elementary_PID]==NULL)
				fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory to process PMT.");
		}
		ctx->PIDs_programs[elementary_PID]->elementary_PID=elementary_PID;
		ctx->PIDs_programs[elementary_PID]->stream_type = stream_type;
		ctx->PIDs_programs[elementary_PID]->program_number=program_number;
		ctx->PIDs_programs[elementary_PID]->printable_stream_type=get_printable_stream_type (stream_type);
		dbg_print(CCX_DMT_PMT, "%6u | %3X (%3u) | %s\n",elementary_PID,stream_type,stream_type,
				desc[ctx->PIDs_programs[elementary_PID]->printable_stream_type]);
		process_ccx_mpeg_descriptor (buf+i+5,ES_info_length);
		i += ES_info_length;
	}
	dbg_print(CCX_DMT_PMT, "---\n");

	dbg_print(CCX_DMT_VERBOSE, "\nProgram map section (PMT)\n");

	for (unsigned i=0; i < stream_data && (i+4)<len; i+=5)
	{
		enum ccx_stream_type stream_type = buf[i];
		unsigned elementary_PID = (((buf[i+1] & 0x1F) << 8)
				| buf[i+2]);
		unsigned ES_info_length = (((buf[i+3] & 0x0F) << 8)
				| buf[i+4]);

		if (!ccx_options.print_file_reports ||
				stream_type != CCX_STREAM_TYPE_PRIVATE_MPEG2 ||
				!ES_info_length)
		{
			i += ES_info_length;
			continue;
		}

		unsigned char *es_info = buf + i + 5;
		for (desc_len = 0;(buf + i + 5 + ES_info_length) > es_info; es_info += desc_len)
		{
			enum ccx_mpeg_descriptor descriptor_tag = (enum ccx_mpeg_descriptor)(*es_info++);
			desc_len = (*es_info++);

			if(descriptor_tag == CCX_MPEG_DSC_DVB_SUBTITLE)
			{
				int k = 0;
				for (int j = 0; j < SUB_STREAMS_CNT; j++) {
					if (ctx->freport.dvb_sub_pid[j] == 0)
						k = j;
					if (ctx->freport.dvb_sub_pid[j] == elementary_PID)
					{
						k = j;
						break;
					}
				}
				ctx->freport.dvb_sub_pid[k] = elementary_PID;
			}
			if(IS_VALID_TELETEXT_DESC(descriptor_tag))
			{
				int k = 0;
				for (int j = 0; j < SUB_STREAMS_CNT; j++) {
					if (ctx->freport.tlt_sub_pid[j] == 0)
						k = j;
					if (ctx->freport.tlt_sub_pid[j] == elementary_PID)
					{
						k = j;
						break;
					}
				}
				ctx->freport.tlt_sub_pid[k] = elementary_PID;
			}
		}
		i += ES_info_length;
	}

	for( unsigned i=0; i < stream_data && (i+4)<len; i+=5)
	{
		enum ccx_stream_type stream_type = buf[i];
		unsigned elementary_PID = (((buf[i+1] & 0x1F) << 8)
				| buf[i+2]);
		unsigned ES_info_length = (((buf[i+3] & 0x0F) << 8)
				| buf[i+4]);


		if(stream_type == CCX_STREAM_TYPE_PRIVATE_MPEG2 &&
				ES_info_length  )
		{
			unsigned char *es_info = buf + i + 5;
			for (desc_len = 0;(buf + i + 5 + ES_info_length) > es_info ;es_info += desc_len)
			{
				void *ptr;
				enum ccx_mpeg_descriptor descriptor_tag = (enum ccx_mpeg_descriptor)(*es_info++);
				desc_len = (*es_info++);
				if(CCX_MPEG_DESC_DATA_COMP == descriptor_tag)
				{
					int16_t component_id = 0;
					if(!IS_FEASIBLE(ctx->codec, ctx->nocodec, CCX_CODEC_ISDB_CC))
						continue;
					if (desc_len < 2)
						break;

					component_id = RB16(es_info);
					if (component_id != 0x08)
						break;
					mprint ("*****ISDB subtitles detected\n");
					ptr = init_isdb_decoder();
					if (ptr == NULL)
						break;
					update_capinfo(ctx, elementary_PID, stream_type, CCX_CODEC_ISDB_CC, program_number, ptr);

				}
				if(CCX_MPEG_DSC_DVB_SUBTITLE == descriptor_tag)
				{
					struct dvb_config cnf;
#ifndef ENABLE_OCR
					if(ccx_options.write_format != CCX_OF_SPUPNG)
					{
						mprint ("DVB subtitles detected, OCR subsystem not present. Use -out=spupng for graphic output\n");
						continue;
					}
#endif
					if (!IS_FEASIBLE(ctx->codec, ctx->nocodec, CCX_CODEC_DVB))
						continue;

					memset((void*)&cnf,0,sizeof(struct dvb_config));
					ret = parse_dvb_description(&cnf,es_info,desc_len);
					if(ret < 0)
						break;
					ptr = dvbsub_init_decoder(&cnf);
					if (ptr == NULL)
						break;
					update_capinfo(ctx, elementary_PID, stream_type, CCX_CODEC_DVB, program_number, ptr);
					max_dif = 30;
				}
			}
		}
		else if(stream_type == CCX_STREAM_TYPE_PRIVATE_USER_MPEG2 && ES_info_length  )
		{
			//if this any generally used video stream tyoe get clashed with ATSC/SCTE standard
			//then this code can go in some atsc flag
			unsigned char *es_info = buf + i + 5;
			for (desc_len = 0;(buf + i + 5 + ES_info_length) > es_info ;es_info += desc_len)
			{
				enum ccx_mpeg_descriptor descriptor_tag = (enum ccx_mpeg_descriptor)(*es_info++);
				int nb_service;
				int is_608;
				int ser_i;
				desc_len = (*es_info++);
				if (CCX_MPEG_DSC_CAPTION_SERVICE == descriptor_tag)
				{
					nb_service = es_info[0] & 0x1f;
					for (ser_i = 0; ser_i < nb_service; ser_i++)
					{
						dbg_print(CCX_DMT_PMT, "CC SERVICE %d: language (%c%c%c)", nb_service,
							es_info[1], es_info[2], es_info[3]);
						is_608 = es_info[4] >> 7;
						dbg_print(CCX_DMT_PMT, "%s", is_608?" CEA-608":" CEA-708");
						dbg_print(CCX_DMT_PMT, "%s", is_608?" CEA-608":" CEA-708");
					}
				}
				update_capinfo(ctx, elementary_PID, stream_type, CCX_CODEC_ATSC_CC, program_number, NULL);
			}
		}