/** @internal @This parses A/52 header. * * @param upipe description structure of the pipe * @return false in case the header is inconsistent */ static bool upipe_a52f_parse_a52(struct upipe *upipe) { struct upipe_a52f *upipe_a52f = upipe_a52f_from_upipe(upipe); uint8_t header[A52_SYNCINFO_SIZE + 2]; if (unlikely(!ubase_check(uref_block_extract(upipe_a52f->next_uref, 0, sizeof(header), header)))) return true; /* not enough data */ ssize_t next_frame_size = a52_get_frame_size(a52_get_fscod(header), a52_get_frmsizecod(header)); if (!next_frame_size) return false; if (likely(a52_sync_compare_formats(header, upipe_a52f->sync_header) && header[5] == upipe_a52f->sync_header[5] && header[6] == upipe_a52f->sync_header[6])) { /* identical sync */ upipe_a52f->next_frame_size = next_frame_size; return true; } /* sample rate */ uint64_t samplerate; switch (a52_get_fscod(header)) { case A52_FSCOD_48KHZ: samplerate = 48000; break; case A52_FSCOD_441KHZ: samplerate = 44100; break; case A52_FSCOD_32KHZ: samplerate = 32000; break; default: upipe_warn(upipe, "reserved fscod"); return false; } /* frame size */ upipe_a52f->next_frame_size = next_frame_size; /* channels */ int acmod = a52_get_acmod(header); int channels = acmod_chans[acmod].nfchans + ((header[6] >> (4 - acmod_chans[acmod].lfe_offset)) & 1); uint64_t octetrate = a52_bitrate_tab[a52_get_frmsizecod(header)] * 1000 / 8; memcpy(upipe_a52f->sync_header, header, A52_SYNCINFO_SIZE + 2); upipe_a52f->samplerate = samplerate; struct uref *flow_def = upipe_a52f_alloc_flow_def_attr(upipe); if (unlikely(!flow_def)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } UBASE_FATAL(upipe, uref_flow_set_complete(flow_def)) UBASE_FATAL(upipe, uref_flow_set_def(flow_def, "block.ac3.sound.")) UBASE_FATAL(upipe, uref_sound_flow_set_samples(flow_def, A52_FRAME_SAMPLES)) UBASE_FATAL(upipe, uref_sound_flow_set_rate(flow_def, samplerate)) UBASE_FATAL(upipe, uref_sound_flow_set_channels(flow_def, channels)) UBASE_FATAL(upipe, uref_clock_set_latency(flow_def, upipe_a52f->input_latency + UCLOCK_FREQ * A52_FRAME_SAMPLES / samplerate)) UBASE_FATAL(upipe, uref_block_flow_set_octetrate(flow_def, octetrate)) flow_def = upipe_a52f_store_flow_def_attr(upipe, flow_def); if (unlikely(!flow_def)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } upipe_a52f_store_flow_def(upipe, flow_def); return true; }
/** @internal @This works on a telx frame and outputs it. * * @param upipe description structure of the pipe * @param upump_p reference to pump that generated the buffer */ static void upipe_telxf_work(struct upipe *upipe, struct upump **upump_p) { struct upipe_telxf *upipe_telxf = upipe_telxf_from_upipe(upipe); uint64_t octetrate = (upipe_telxf->next_uref_size * upipe_telxf->fps.num + upipe_telxf->fps.den - 1) / upipe_telxf->fps.den; if (octetrate != upipe_telxf->octetrate) { upipe_telxf->octetrate = octetrate; struct uref *flow_def = upipe_telxf_alloc_flow_def_attr(upipe); if (unlikely(flow_def == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); uref_free(upipe_telxf->next_uref); goto upipe_telxf_work_err; } UBASE_FATAL(upipe, uref_pic_flow_set_fps(flow_def, upipe_telxf->fps)) UBASE_FATAL(upipe, uref_block_flow_set_octetrate(flow_def, upipe_telxf->octetrate)) flow_def = upipe_telxf_store_flow_def_attr(upipe, flow_def); if (unlikely(flow_def == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); uref_free(upipe_telxf->next_uref); goto upipe_telxf_work_err; } upipe_telxf_store_flow_def(upipe, flow_def); } upipe_telxf_sync_acquired(upipe); uint64_t duration = UCLOCK_FREQ * upipe_telxf->fps.den / upipe_telxf->fps.num; /* We work on encoded data so in the DTS domain. Rebase on DTS. */ uint64_t date; struct urational drift_rate; drift_rate.den = 0; uref_clock_get_rate(upipe_telxf->next_uref, &drift_rate); #define SET_DATE(dv) \ if (ubase_check(uref_clock_get_dts_##dv(upipe_telxf->next_uref, &date)))\ uref_clock_set_dts_##dv(&upipe_telxf->au_uref_s, date); \ if (ubase_check(uref_clock_get_dts_##dv(&upipe_telxf->au_uref_s, \ &date))) { \ uref_clock_set_dts_##dv(upipe_telxf->next_uref, date); \ uref_clock_set_dts_##dv(&upipe_telxf->au_uref_s, date + duration); \ } else if (ubase_check(uref_clock_get_cr_##dv(upipe_telxf->next_uref, \ &date))) { \ /* EN 300 472 Annex A */ \ uref_clock_set_dts_##dv(upipe_telxf->next_uref, \ date + MAX_DELAY_TELX); \ uref_clock_set_dts_##dv(&upipe_telxf->au_uref_s, date + \ MAX_DELAY_TELX + duration); \ } SET_DATE(sys) SET_DATE(prog) SET_DATE(orig) #undef SET_DATE uref_clock_set_dts_pts_delay(upipe_telxf->next_uref, 0); if (drift_rate.den) uref_clock_set_rate(upipe_telxf->next_uref, drift_rate); upipe_telxf_output(upipe, upipe_telxf->next_uref, upump_p); upipe_telxf_work_err: upipe_telxf->next_uref = NULL; upipe_telxf->next_uref_size = 0; }
/** @internal @This parses A/52 Annex E header. * * @param upipe description structure of the pipe * @return false in case the header is inconsistent */ static bool upipe_a52f_parse_a52e(struct upipe *upipe) { struct upipe_a52f *upipe_a52f = upipe_a52f_from_upipe(upipe); uint8_t header[A52_SYNCINFO_SIZE]; if (unlikely(!ubase_check(uref_block_extract(upipe_a52f->next_uref, 0, sizeof(header), header)))) return true; /* not enough data */ if (likely(a52e_sync_compare_formats(header, upipe_a52f->sync_header))) { /* identical sync */ upipe_a52f->next_frame_size = a52e_get_frame_size(a52e_get_frmsiz(header)); return true; } /* sample rate */ uint64_t samplerate; switch (a52e_get_fscod(header)) { case A52_FSCOD_48KHZ: samplerate = 48000; break; case A52_FSCOD_441KHZ: samplerate = 44100; break; case A52_FSCOD_32KHZ: samplerate = 32000; break; case A52_FSCOD_RESERVED: switch (a52e_get_fscod2(header)) { case A52E_FSCOD2_24KHZ: samplerate = 24000; break; case A52E_FSCOD2_2205KHZ: samplerate = 22050; break; case A52E_FSCOD2_16KHZ: samplerate = 16000; break; default: upipe_warn(upipe, "reserved fscod2"); return false; } break; default: /* never reached */ return false; } /* frame size */ upipe_a52f->next_frame_size = a52e_get_frame_size(a52e_get_frmsiz(header)); /* channels */ int acmod = a52e_get_acmod(header); int channels = acmod_chans[acmod].nfchans + a52e_get_lfeon(header); uint64_t octetrate = (upipe_a52f->next_frame_size * samplerate + A52_FRAME_SAMPLES - 1) / A52_FRAME_SAMPLES; memcpy(upipe_a52f->sync_header, header, A52_SYNCINFO_SIZE); upipe_a52f->samplerate = samplerate; struct uref *flow_def = upipe_a52f_alloc_flow_def_attr(upipe); if (unlikely(!flow_def)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } UBASE_FATAL(upipe, uref_flow_set_complete(flow_def)) UBASE_FATAL(upipe, uref_flow_set_def(flow_def, "block.eac3.sound.")) UBASE_FATAL(upipe, uref_sound_flow_set_samples(flow_def, A52_FRAME_SAMPLES)) UBASE_FATAL(upipe, uref_sound_flow_set_rate(flow_def, samplerate)) UBASE_FATAL(upipe, uref_sound_flow_set_channels(flow_def, channels)) UBASE_FATAL(upipe, uref_clock_set_latency(flow_def, upipe_a52f->input_latency + UCLOCK_FREQ * A52_FRAME_SAMPLES / samplerate)) UBASE_FATAL(upipe, uref_block_flow_set_octetrate(flow_def, octetrate)) flow_def = upipe_a52f_store_flow_def_attr(upipe, flow_def); if (unlikely(!flow_def)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } upipe_a52f_store_flow_def(upipe, flow_def); return true; }