Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced hdc #245

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/nrsc5.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ struct nrsc5_event_t
unsigned int program;
const uint8_t *data;
size_t count;
const uint8_t *enh_data;
size_t enh_count;
} hdc;
struct {
unsigned int program;
Expand Down
8 changes: 5 additions & 3 deletions src/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ void frame_process(frame_t *st, size_t length)
while (offset < audio_end - RS_CODEWORD_LEN)
{
unsigned int start = offset;
unsigned int j, lc_bits, loc_bytes, prog;
unsigned int j, lc_bits, loc_bytes, prog, seq;
unsigned short locations[MAX_AUDIO_PACKETS];
frame_header_t hdr = {0};
hef_t hef = {0};
Expand Down Expand Up @@ -512,6 +512,7 @@ void frame_process(frame_t *st, size_t length)
parse_hdlc(st, aas_push, st->psd_buf[prog], &st->psd_idx[prog], MAX_AAS_LEN, st->buffer + offset, start + hdr.la_location + 1 - offset);
offset = start + hdr.la_location + 1;

seq = hdr.seq;
for (j = 0; j < hdr.nop; ++j)
{
unsigned int cnt = start + locations[j] - offset;
Expand All @@ -528,7 +529,7 @@ void frame_process(frame_t *st, size_t length)
if (idx)
{
memcpy(&st->pdu[prog][hdr.stream_id][idx], st->buffer + offset, cnt);
input_pdu_push(st->input, st->pdu[prog][hdr.stream_id], cnt + idx, prog, hdr.stream_id);
input_pdu_push(st->input, st->pdu[prog][hdr.stream_id], cnt + idx, prog, hdr.stream_id, (seq - 1) & 0x3f);
}
else
{
Expand All @@ -542,7 +543,8 @@ void frame_process(frame_t *st, size_t length)
}
else
{
input_pdu_push(st->input, st->buffer + offset, cnt, prog, hdr.stream_id);
input_pdu_push(st->input, st->buffer + offset, cnt, prog, hdr.stream_id, seq);
seq = (seq + 1) & 0x3f;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sequence number also needs to be incremented in the case where the CRC is invalid. This line won't be reached due to the continue on line 523.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. Looking over this code, I feel like there are similar problems with st->pdu_idx[prog][hdr.stream_id] as well, so some refactoring might be warranted.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right. We should reset st->pdu_idx[prog][hdr.stream_id] back to zero in the j == 0 && hdr.pfirst case, regardless of whether the CRC is valid.

}

offset += cnt + 1;
Expand Down
4 changes: 2 additions & 2 deletions src/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ static void input_push_to_acquire(input_t *st)
st->used += acquire_push(&st->acq, &st->buffer[st->used], st->avail - st->used);
}

void input_pdu_push(input_t *st, uint8_t *pdu, unsigned int len, unsigned int program, unsigned int stream_id)
void input_pdu_push(input_t *st, uint8_t *pdu, unsigned int len, unsigned int program, unsigned int stream_id, unsigned int seq)
{
output_push(st->output, pdu, len, program, stream_id);
output_push(st->output, pdu, len, program, stream_id, seq);
}

void input_set_skip(input_t *st, unsigned int skip)
Expand Down
2 changes: 1 addition & 1 deletion src/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,5 @@ void input_push_cu8(input_t *st, uint8_t *buf, uint32_t len);
void input_push_cs16(input_t *st, int16_t *buf, uint32_t len);
void input_set_snr_callback(input_t *st, input_snr_cb_t cb, void *);
void input_set_skip(input_t *st, unsigned int skip);
void input_pdu_push(input_t *st, uint8_t *pdu, unsigned int len, unsigned int program, unsigned int stream_id);
void input_pdu_push(input_t *st, uint8_t *pdu, unsigned int len, unsigned int program, unsigned int stream_id, unsigned int seq);
void input_aas_push(input_t *st, uint8_t *psd, unsigned int len);
8 changes: 7 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ typedef struct {
FILE *hdc_file;
FILE *iq_file;
char *aas_files_path;
int decode_enhanced_stream;

audio_buffer_t *head, *tail, *free;
pthread_mutex_t mutex;
Expand Down Expand Up @@ -304,7 +305,7 @@ static void callback(const nrsc5_event_t *evt, void *opaque)
dump_hdc(st->hdc_file, evt->hdc.data, evt->hdc.count);

st->audio_packets++;
st->audio_bytes += evt->hdc.count * sizeof(evt->hdc.data[0]);
st->audio_bytes += evt->hdc.count * sizeof(evt->hdc.data[0]) + evt->hdc.enh_count * sizeof(evt->hdc.enh_data[0]);
if (st->audio_packets >= 32) {
log_info("Audio bit rate: %.1f kbps", (float)st->audio_bytes * 8 * 44100 / 2048 / st->audio_packets / 1000);
st->audio_packets = 0;
Expand Down Expand Up @@ -515,6 +516,7 @@ static int parse_args(state_t *st, int argc, char *argv[])
{ "dump-aas-files", required_argument, NULL, 1 },
{ "dump-hdc", required_argument, NULL, 2 },
{ "am", no_argument, NULL, 3 },
{ "enhanced", no_argument, NULL, 4 },
{ 0 }
};
const char *version = NULL;
Expand All @@ -539,6 +541,9 @@ static int parse_args(state_t *st, int argc, char *argv[])
case 3:
st->mode = NRSC5_MODE_AM;
break;
case 4:
st->decode_enhanced_stream = 1;
break;
case 'r':
st->input_name = strdup(optarg);
break;
Expand Down Expand Up @@ -746,6 +751,7 @@ int main(int argc, char *argv[])
return 1;
}
nrsc5_set_mode(radio, st->mode);
nrsc5_set_decode_enhanced_stream(radio, st->decode_enhanced_stream);
if (st->gain >= 0.0f)
nrsc5_set_gain(radio, st->gain);
nrsc5_set_callback(radio, callback, st);
Expand Down
9 changes: 8 additions & 1 deletion src/nrsc5.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,14 +565,16 @@ void nrsc5_report_lost_sync(nrsc5_t *st)
nrsc5_report(st, &evt);
}

void nrsc5_report_hdc(nrsc5_t *st, unsigned int program, const uint8_t *data, size_t count)
void nrsc5_report_hdc(nrsc5_t *st, unsigned int program, const uint8_t *data, size_t count, const uint8_t *enh_data, size_t enh_count)
{
nrsc5_event_t evt;

evt.event = NRSC5_EVENT_HDC;
evt.hdc.program = program;
evt.hdc.data = data;
evt.hdc.count = count;
evt.hdc.enh_data = enh_data;
evt.hdc.enh_count = enh_count;
nrsc5_report(st, &evt);
}

Expand Down Expand Up @@ -743,3 +745,8 @@ void nrsc5_report_sis(nrsc5_t *st, const char *country_code, int fcc_facility_id

nrsc5_report(st, &evt);
}

NRSC5_API void nrsc5_set_decode_enhanced_stream(nrsc5_t *st, int value)
{
st->decode_enhanced_stream = value;
}
83 changes: 75 additions & 8 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,59 @@
#include "private.h"
#include "unicode.h"

void output_push(output_t *st, uint8_t *pkt, unsigned int len, unsigned int program, unsigned int stream_id)
void output_push(output_t *st, uint8_t *pkt, unsigned int len, unsigned int program, unsigned int stream_id, unsigned int seq)
{
nrsc5_report_hdc(st->radio, program, pkt, len);
if (stream_id == 1)
{
// TODO: handle missing frames
audio_packet_t *enh = malloc(sizeof(*enh) + len);
enh->next = NULL;
enh->seq = seq;
enh->size = len;
memcpy(enh->data, pkt, len);

if (st->enhanced[program])
{
audio_packet_t *tail;
unsigned int count = 0;
for (tail = st->enhanced[program]; tail->next != NULL; tail = tail->next)
count++;
tail->next = enh;
st->enhanced_count[program]++;
}
else
{
st->enhanced[program] = enh;
}
return;
}
else if (stream_id != 0)
{
log_error("Unknown stream id: %d\n", stream_id);
return;
}

if (stream_id != 0)
return; // TODO: Process enhanced stream
audio_packet_t *enhanced = st->enhanced[program];
uint8_t *enh_data = NULL;
unsigned int enh_size = 0;
// HACK: delay the enhanced packets by 64 core packets then align seq numbers (which are in range 0-63)
if (st->enhanced_count[program] >= 64 && enhanced->seq == seq)
{
st->enhanced[program] = enhanced->next;
st->enhanced_count[program]--;

if (st->radio->decode_enhanced_stream)
{
enh_data = enhanced->data;
enh_size = enhanced->size;
}
}
else
{
enhanced = NULL;
}

nrsc5_report_hdc(st->radio, program, pkt, len, enh_data, enh_size);

#ifdef USE_FAAD2
void *buffer;
Expand All @@ -43,13 +90,16 @@ void output_push(output_t *st, uint8_t *pkt, unsigned int len, unsigned int prog
NeAACDecInitHDC(&st->aacdec[program], &samprate);
}

buffer = NeAACDecDecode(st->aacdec[program], &info, pkt, len);
buffer = NeAACDecDecodeHDC(st->aacdec[program], &info, pkt, len, enh_data, enh_size);
if (info.error > 0)
log_error("Decode error: %s", NeAACDecGetErrorMessage(info.error));

if (info.error == 0 && info.samples > 0)
nrsc5_report_audio(st->radio, program, buffer, info.samples);
#endif

if (enhanced != NULL)
free(enhanced);
}

static void aas_free_lot(aas_file_t *file)
Expand Down Expand Up @@ -92,27 +142,44 @@ static void aas_reset(output_t *st)
memset(st->services, 0, sizeof(st->services));
}

void audio_packets_free(audio_packet_t *list)
{
while (list != NULL)
{
audio_packet_t *p = list;
list = p->next;
free(p);
}
}

void output_reset(output_t *st)
{
aas_reset(st);

#ifdef USE_FAAD2
for (int i = 0; i < MAX_PROGRAMS; i++)
{
audio_packets_free(st->enhanced[i]);
st->enhanced[i] = NULL;
st->enhanced_count[i] = 0;

#ifdef USE_FAAD2
if (st->aacdec[i])
NeAACDecClose(st->aacdec[i]);
st->aacdec[i] = NULL;
}
#endif
}
}

void output_init(output_t *st, nrsc5_t *radio)
{
st->radio = radio;
#ifdef USE_FAAD2
for (int i = 0; i < MAX_PROGRAMS; i++)
{
st->enhanced[i] = NULL;
#ifdef USE_FAAD2
st->aacdec[i] = NULL;
#endif
}

memset(st->ports, 0, sizeof(st->ports));
memset(st->services, 0, sizeof(st->services));
Expand Down
12 changes: 11 additions & 1 deletion src/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,27 @@ typedef struct
sig_component_t component[MAX_SIG_COMPONENTS];
} sig_service_t;

typedef struct audio_packet_t
{
struct audio_packet_t *next;
unsigned int seq;
unsigned int size;
uint8_t data[];
} audio_packet_t;

typedef struct
{
nrsc5_t *radio;
#ifdef HAVE_FAAD2
NeAACDecHandle aacdec[MAX_PROGRAMS];
#endif
audio_packet_t *enhanced[MAX_PROGRAMS];
unsigned int enhanced_count[MAX_PROGRAMS];
aas_port_t ports[MAX_PORTS];
sig_service_t services[MAX_SIG_SERVICES];
} output_t;

void output_push(output_t *st, uint8_t *pkt, unsigned int len, unsigned int program, unsigned int stream_id);
void output_push(output_t *st, uint8_t *pkt, unsigned int len, unsigned int program, unsigned int stream_id, unsigned int seq);
void output_begin(output_t *st);
void output_reset(output_t *st);
void output_init(output_t *st, nrsc5_t *);
Expand Down
3 changes: 2 additions & 1 deletion src/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct nrsc5_t

input_t input;
output_t output;
int decode_enhanced_stream;
};

void nrsc5_report(nrsc5_t *, const nrsc5_event_t *evt);
Expand All @@ -45,7 +46,7 @@ void nrsc5_report_sync(nrsc5_t *);
void nrsc5_report_lost_sync(nrsc5_t *);
void nrsc5_report_mer(nrsc5_t *, float lower, float upper);
void nrsc5_report_ber(nrsc5_t *, float cber);
void nrsc5_report_hdc(nrsc5_t *, unsigned int program, const uint8_t *data, size_t count);
void nrsc5_report_hdc(nrsc5_t *, unsigned int program, const uint8_t *data, size_t count, const uint8_t *enh_data, size_t enh_count);
void nrsc5_report_audio(nrsc5_t *, unsigned int program, const int16_t *data, size_t count);
void nrsc5_report_lot(nrsc5_t *, uint16_t port, unsigned int lot, unsigned int size, uint32_t mime, const char *name, const uint8_t *data);
void nrsc5_report_sig(nrsc5_t *, sig_service_t *services, unsigned int count);
Expand Down
Loading