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; }
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; }
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; }
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); }
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); } }