/** @internal @This sets the input flow definition. * * @param upipe description structure of the pipe * @param flow_def flow definition packet * @return an error code */ static int upipe_s337_encaps_set_flow_def(struct upipe *upipe, struct uref *flow_def) { if (flow_def == NULL) return UBASE_ERR_INVALID; const char *def; UBASE_RETURN(uref_flow_get_def(flow_def, &def)) uint64_t rate; UBASE_RETURN(uref_sound_flow_get_rate(flow_def, &rate)) if (ubase_ncmp(def, EXPECTED_FLOW_DEF)) return UBASE_ERR_INVALID; struct uref *flow_def_dup = uref_dup(flow_def); if (flow_def_dup == NULL) return UBASE_ERR_ALLOC; uref_flow_set_def(flow_def_dup, "sound.s32.s337.a52."); uref_sound_flow_set_channels(flow_def_dup, 2); uref_sound_flow_set_sample_size(flow_def_dup, 2*4); if (!ubase_check(uref_sound_flow_add_plane(flow_def_dup, "lr")) || !ubase_check(uref_sound_flow_set_rate(flow_def_dup, rate))) { uref_free(flow_def_dup); return UBASE_ERR_ALLOC; } upipe_s337_encaps_require_ubuf_mgr(upipe, flow_def_dup); return UBASE_ERR_NONE; }
/** @internal @This provides a flow format suggestion. * * @param upipe description structure of the pipe * @param request description structure of the request * @return an error code */ static int upipe_nacl_audio_provide_flow_format(struct upipe *upipe, struct urequest *request) { struct uref *flow_format = uref_dup(request->uref); UBASE_ALLOC_RETURN(flow_format); uref_sound_flow_clear_format(flow_format); uref_flow_set_def(flow_format, EXPECTED_FLOW_DEF); uref_sound_flow_set_channels(flow_format, 2); uref_sound_flow_set_sample_size(flow_format, 4); uref_sound_flow_set_planes(flow_format, 0); uref_sound_flow_add_plane(flow_format, "lr"); uref_sound_flow_set_rate(flow_format, SAMPLE_RATE); return urequest_provide_flow_format(request, flow_format); }
/** @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 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; }
/** @internal @This outputs audio buffers * * @param upipe description structure of the pipe * @param frame AVFrame structure * @param upump upump structure */ static void upipe_avcdec_output_audio(struct upipe *upipe, AVFrame *frame, struct upump *upump) { struct ubuf *ubuf; struct upipe_avcdec *upipe_avcdec = upipe_avcdec_from_upipe(upipe); struct uref *uref = frame->opaque; int bufsize = -1, avbufsize; size_t size = 0; uint8_t *buf; AVCodecContext *context = upipe_avcdec->context; /* fetch audio sample size (in case it has been reduced) */ avbufsize = av_samples_get_buffer_size(NULL, context->channels, frame->nb_samples, context->sample_fmt, 1); /* if uref has no attached ubuf (ie DR not supported) */ if (unlikely(!uref->ubuf)) { ubuf = ubuf_block_alloc(upipe_avcdec->ubuf_mgr, avbufsize); if (unlikely(!ubuf)) { upipe_throw_aerror(upipe); return; } ubuf_block_write(ubuf, 0, &bufsize, &buf); memcpy(buf, frame->data[0], bufsize); uref_attach_ubuf(uref, ubuf); } /* unmap, reduce block if needed */ uref_block_unmap(uref, 0); uref_block_size(uref, &size); if (unlikely(size != avbufsize)) { uref_block_resize(uref, 0, avbufsize); } /* TODO: set attributes/need a real ubuf_audio structure (?) */ if (!upipe_avcdec->output_flow) { #if 0 struct uref *outflow = uref_sound_flow_alloc_def(upipe_avcdec->uref_mgr, context->channels, av_get_bytes_per_sample(context->sample_fmt)); #else struct uref *outflow = uref_block_flow_alloc_def(upipe_avcdec->uref_mgr, "sound."); #endif uref_sound_flow_set_channels(outflow, context->channels); uref_sound_flow_set_sample_size(outflow, av_get_bytes_per_sample(context->sample_fmt)); uref_sound_flow_set_rate(outflow, context->sample_rate); upipe_avcdec_store_flow_def(upipe, outflow); } /* samples in uref */ uref_sound_flow_set_samples(uref, frame->nb_samples); /* index rap attribute */ upipe_avcdec_set_index_rap(upipe, uref); upipe_avcdec_output(upipe, uref, upump); }