Skip to content

Conversation

@dbaluta
Copy link
Collaborator

@dbaluta dbaluta commented Mar 25, 2021

This patch series adds the final support patches for compress audio playback.
It mostly touches the codec_adapter() copy function which was initially designed only for PCM frames.

This patches are sent for an early review. They will eventually get merged after I will sort out @cujomalainey PR: #3881

@mrajwa @paulstelian97 @iuliana-prodan @cujomalainey @stolx please have a look.

@cujomalainey I will start working on sorting out #3881 from now on.

init_process API is used to initialize the processing phase.
(e.g for Cadence: search for valid header, decode header in order
to get parameters).

init_process needs to have access to the input frames so it will be
called by codec adapter copy() function.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
@dbaluta dbaluta changed the title RFC: Add support for compress audio RFC: Add final support for compress audio Mar 25, 2021
dbaluta added 2 commits March 25, 2021 21:06
local buffer is used to store the output of processing function.
So, we need to compute its size based on codec_adapter output buffer
not input buffer.

For non-compressed processing the current code works because input
and output buffer have equal sizes.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
processed field keeps the total number of processed bytes
from the input buffer. We need to update this field also
for the process_init operation.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
@dbaluta dbaluta force-pushed the compress branch 2 times, most recently from 2f800d3 to 66d0e4e Compare March 25, 2021 19:19
Copy link
Collaborator

Choose a reason for hiding this comment

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

We need to figure out what's with this hardcoding.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, yes! Will fix it asap.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would put this magic number in a define.
Also, maybe, it will be good to specify this limitation in commit message: "so far we support mp3 at 192khz and 24 bits".

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@thanks Iulia for the comment. What I actually plan to do is to create a generic function that given a codec and its parameters it will return the maximum amount of the output data.

Something like code_adapter_get_max_bytes? I just couldn't find a good name. This work is still RFC. We won't submit the code like that.

Copy link
Contributor

Choose a reason for hiding this comment

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

A generic function sounds good.
Regarding the naming, I think it's ok, but I'm not good with names either :)

Copy link
Member

Choose a reason for hiding this comment

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

Fwiw the 9212 should also be a topology 2.0 attribute (as this can also be enforced in any MP3 topology)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@lgirdwood this could be an option. It looks like at least for mp3 the number of samples resulted after decoding one frame is always the same 1152 (9217 = 1152 samples * 2 channels * 4 bytes / sample + 1). If this holds true for all the decoding algorithms then getting this via topology could be an option.

Copy link
Member

@plbossart plbossart Mar 26, 2021

Choose a reason for hiding this comment

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

I think it would be a grave mistake to use a single period.

if the scheduling is constrained by the output size, then it may happen that you have to decode multiple frames in the allocated time. In our past integration, the decoder was part of a different pipeline and scheduled with a lower priority, so that there were no peaks in the MCPS usage. I really think you have to decouple the codec_adapter from the dai scheduling....

Copy link
Collaborator Author

@dbaluta dbaluta Mar 26, 2021

Choose a reason for hiding this comment

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

@plbossart Definitely! That was my next step. I try to do it gradually and also have something that's working for our releases. Customers want to look at the DSP even if it isn't the final code.
I will try to see how we satisfy both requirements. In time! :)

  • the only thing that's definitely out of place right now is the m4 topology.

For the rest of the code:

  • existing DAP support (based on PCM frames, should still work)
  • no other functionality is impacted.

Next steps:
(1) decouple codec adapter from DAI scheduling. In fact here there is no clear line where should I do the decoupling.

Because codec_adapter has an output buffer that holds the decoded samples and DMA needs to copy based on DAI pace
each period "period_bytes" of data.
So, each DAI period I need to call codec_adapter_copy() to push data from codec_adapter local buffer to DMA buffer.

Also, the Host need to push data to codec_adapter based on its own pace. So, Host should copy one "compress period" of data each time the DAI has rendered one mp3 frame.

So, in simple terms:

  • Host should copy one mp3 compressed frame each 0.026 sec (compress period will be 26ms).
  • DAI should copy SAMPLE_RATE/1000 sampes each 1ms (compress period will be 1ms).

Also, we noticed that we could process around 3 to 4 MP3 frames within 1ms , so there is enough room for our simple sceario to work.

Copy link
Member

Choose a reason for hiding this comment

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

I think you should really have 3 pipelines
a) dai with mixer
b) PCM for notifications/beeps that may occur at any time
c) compressed. That pipe may run at a lower priority or larger granularity than the DAI period. The last thing you want it to try and complete one decode at a 26x speed, you have to spread the work across multiple dai periods otherwise you will underrun when your system is loaded.

IIRC in all implementations, the DAI typically works with O(ms) buffers, and the compressed pipeline can work with much larger frames. In fact if you look at newer codecs they will generate 4k or 8k samples in one frame. So you need some sort of ring buffer to adjust between codec and dai.

Copy link
Member

Choose a reason for hiding this comment

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

And I forget that you need an SRC on your compressed pipeline if you want to support all frequencies.

Copy link
Collaborator Author

@dbaluta dbaluta Mar 26, 2021

Choose a reason for hiding this comment

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

Nice suggestion. I wonder if compress and PCM can be supported on the sample sound card device on the Linux side.

dbaluta added 4 commits March 26, 2021 13:28
With compress audio the number of output bytes is usually greater
then the number of the input bytes.

Because of this, local buffer might have "valid" bytes even if the
current process operation didn't produce anything.

So, in this period we did not produce anything but we can still copy
some bytes from local_buffer to sink buffer.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
…sing

We need to make sure that the local buffer has enough room to hold
the output of the processing.

This means that for each type of decoding algorithm we need to know
the maximum possible output size and skip processing if local buffer
size is less than that.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Processing loop inside codec_adapter copy() function will take
the input buffer and try to process all the data available.

We need to 'consume' the source bytes and 'produce' the bytes
to local_buffer after each iteration not just at the end.

Failing to do so, will put wrong data for processing function
starting with second iteration.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Add topology to support compress playback for MP3 on i.MX8/i.MX8X
with wm8960 codec.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Copy link
Member

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

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

I assume we will support full passthrough mode for this work so this can be validated by CI without binary codecs ?

Copy link
Member

Choose a reason for hiding this comment

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

Fwiw the 9212 should also be a topology 2.0 attribute (as this can also be enforced in any MP3 topology)

@dbaluta
Copy link
Collaborator Author

dbaluta commented Mar 26, 2021

@lgirdwood yes we will support pass through. This is one of our tiny hopes to test the codec_adapter publicly without private binary blobs.

We need to clarify some things about pass through:

  • currently there is a simple pass through family of codecs [1]. This is already merged and I will take care that current patches do not break it.
  • there is a proposal to add a pass through codec type inside Cadence family of codecs [2]

@johnylin76 is there any update for [2]?

[1] https://github.com/thesofproject/sof/blob/master/src/audio/codec_adapter/codec/passthrough.c
[2] #3766


/* TODO: remove magic number and use possible maximum output per
* decoding algorithm type
* 9216 is maximum frame length bytes for mp3 at 192Khz, 24bits,
Copy link
Member

Choose a reason for hiding this comment

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

that makes no sense. mp3 never supported 192kHz and perceptual coders don't care about bit depth.

I don't recall what the max value was but this was something at 320 kbits/s

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@plbossart It is clear that I still need to read upon mp3 stuff and all. I'm still confused about all the version / etc.

I started with a sample mp3 file:

root@imx8qxpc0mek:~# file samples/lb.mp3    
samples/lb.mp3: MPEG ADTS, layer III, v1, 192 kbps, 48 kHz, Stereo

From the internet I have this:

// Bitrates - use [version][layer][bitrate]
const uint16_t mpeg_bitrates[4][4][16] = {
  { // Version 2.5
    { 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0 }, // Reserved
    { 0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0 }, // Layer 3
    { 0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0 }, // Layer 2
    { 0,  32,  48,  56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }  // Layer 1
  },
  { // Reserved
    { 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0 }, // Invalid
    { 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0 }, // Invalid
    { 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0 }, // Invalid
    { 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0 }  // Invalid
  },
  { // Version 2
    { 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0 }, // Reserved
    { 0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0 }, // Layer 3
    { 0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0 }, // Layer 2
    { 0,  32,  48,  56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }  // Layer 1
  },
  { // Version 1
    { 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0 }, // Reserved
    { 0,  32,  40,  48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 0 }, // Layer 3
    { 0,  32,  48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, 0 }, // Layer 2
    { 0,  32,  64,  96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, // Layer 1
  }
};

If my understanding is correct MP3 is MPEG-1 Audio Layer III or MPEG-2 Audio Layer III.

So, based on the table above mp3 should also support 192kHZ. But I admit my comment there is just bad! I will remove it.

Copy link
Member

Choose a reason for hiding this comment

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

you may be confusing kbs and kHz :-)

the rates are
version 1: 48, 44.1 and 32kHz
version 2: 24, 22.05 and 16 kHz
version 2.5: 12, 11.025 and 8 kHz (this is actually not a standard but an extension by FhG).

https://en.wikipedia.org/wiki/MP3 has most of the needed information.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, you are right the comment should be read 192kbps.

1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA)


# PCM Low Latency, id 0
Copy link
Member

Choose a reason for hiding this comment

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

PCM?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@plbossart copy paste of course.

# PCM Low Latency, id 0

dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture)
COMPR_PLAYBACK_ADD(Port0, 0, PIPELINE_PCM_1)
Copy link
Member

Choose a reason for hiding this comment

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

CompressedPort0?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Makes sense.

@lgirdwood lgirdwood closed this Mar 28, 2021
@lgirdwood lgirdwood deleted the branch thesofproject:master March 28, 2021 13:44
@lgirdwood
Copy link
Member

Please use "main" as PR target.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants