This commit is contained in:
刘可亮
2024-10-30 16:50:31 +08:00
parent 0ef85b55da
commit 661e71562d
458 changed files with 46555 additions and 12133 deletions

View File

@@ -20,6 +20,11 @@ config AIC_MPP_AVI_DEMUX
default n
depends on LPKG_MPP && AIC_MPP_PLAYER_INTERFACE
config AIC_MPP_FLAC_DEMUX
bool "Enable flac demux"
default n
depends on LPKG_MPP && AIC_MPP_PLAYER_INTERFACE && LPKG_USING_LIBFLAC
config AIC_MPP_RECORDER_INTERFACE
bool "Enable recorder interface and demo"
default n

View File

@@ -25,6 +25,7 @@ if GetDepend(['AIC_MPP_PLAYER_INTERFACE']):
path += [cwd + '/middle_media/base/parser/mp3']
path += [cwd + '/middle_media/base/parser/wav']
path += [cwd + '/middle_media/base/parser/avi']
path += [cwd + '/middle_media/base/parser/flac']
#mm
path += [cwd + '/middle_media/component/src']
@@ -59,6 +60,8 @@ CPPDEFINES = []
# mpp
if GetDepend(['LPKG_MPP']):
src += Glob('./base/memory/*.c')
src += Glob('./base/thread/*.c')
src += Glob('./base/ringbuf/*.c')
src += Glob('./ge/*.c')
src += Glob('./fb/*.c')
src += Glob('ve/decoder/*.c')
@@ -77,7 +80,9 @@ if GetDepend(['KERNEL_RTTHREAD']) and GetDepend(['LPKG_MPP']) and GetDepend(['AI
src += Glob('./mpp_test/bit_stream_parser.c')
src += Glob('./mpp_test/pic_crop_test.c')
src += Glob('./mpp_test/jpeg_encode_test.c')
src += Glob('./mpp_test/test_mpp_dec.c')
if GetDepend(['AIC_VE_DRV_V10']):
src += Glob('./mpp_test/test_mpp_dec.c')
if GetDepend(['KERNEL_RTTHREAD']) and GetDepend(['LPKG_MPP']) and GetDepend(['AIC_GE_TEST']):
src += Glob('./mpp_test/ge_test/public/*.c')
@@ -126,6 +131,13 @@ if GetDepend(['AIC_MPP_PLAYER_INTERFACE']):
if GetDepend(['AIC_MPP_PLAYER_VE_USE_FILL_FB']):
src += Glob('middle_media/player/player_dec_share_test.c')
if GetDepend(['LPKG_USING_LIBFLAC']):
src += Glob('middle_media/audio_decoder/decoder/flac/flac_decoder.c')
if GetDepend(['AIC_MPP_FLAC_DEMUX']):
src += Glob('middle_media/base/parser/flac/aic_flac_parser.c')
src += Glob('middle_media/base/parser/flac/flac.c')
if GetDepend(['AIC_MPP_AVI_DEMUX']):
src += Glob('middle_media/base/parser/avi/aic_avi_parser.c')
src += Glob('middle_media/base/parser/avi/avi.c')

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <che.jiang@artinchip.com>
* Desc: mpp ringbuf interface
*/
#ifndef MPP_RINGBUF_H
#define MPP_RINGBUF_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void *mpp_ringbuf_t;
mpp_ringbuf_t mpp_ringbuffer_create(int length);
void mpp_ringbuffer_destroy(mpp_ringbuf_t rb);
void mpp_ringbuffer_reset(mpp_ringbuf_t rb);
int mpp_ringbuffer_put(mpp_ringbuf_t rb, const unsigned char *ptr, int length);
int mpp_ringbuffer_get(mpp_ringbuf_t rb, unsigned char *ptr, int length);
int mpp_ringbuffer_data_len(mpp_ringbuf_t rb);
int mpp_ringbuffer_space_len(mpp_ringbuf_t rb);
#ifdef __cplusplus
}
#endif
#endif /* MPP_RINGBUF_H */

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <che.jiang@artinchip.com>
* Desc: mpp thread interface
*/
#ifndef MPP_THREAD_H
#define MPP_THREAD_H
#include <stdint.h>
#include <inttypes.h>
#include "mpp_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MPP_WAIT_FOREVER (-1)
typedef void *mpp_sem_t;
mpp_sem_t mpp_sem_create();
void mpp_sem_delete(mpp_sem_t sem);
int mpp_sem_signal(mpp_sem_t sem);
int mpp_sem_wait(mpp_sem_t sem, int64_t us);
#ifdef __cplusplus
}
#endif
#endif /* MPP_THREAD_H */

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <che.jiang@artinchip.com>
* Desc: mpp thread interface
*/
#include "mpp_ringbuf.h"
#include "mpp_log.h"
#include "mpp_mem.h"
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include "rtconfig.h"
#if defined(KERNEL_RTTHREAD)
#include "aic_osal.h"
#include <rtdevice.h>
#include <rtthread.h>
struct mpp_ringbuf_handle {
struct rt_ringbuffer ringbuf;
unsigned char *buf_pool;
int buf_len;
};
#endif
mpp_ringbuf_t mpp_ringbuffer_create(int length)
{
struct mpp_ringbuf_handle *h_ringbuf = NULL;
#if defined(KERNEL_RTTHREAD)
h_ringbuf = (struct mpp_ringbuf_handle *)mpp_alloc(sizeof(struct mpp_ringbuf_handle));
if (!h_ringbuf)
return NULL;
memset(h_ringbuf, 0, sizeof(struct mpp_ringbuf_handle));
h_ringbuf->buf_pool = aicos_malloc_align(MEM_DEFAULT, length, 64);
if (!h_ringbuf->buf_pool) {
loge("ERROR: allocating buffer pool(%d) failed\n", length);
mpp_free(h_ringbuf);
return NULL;
}
rt_ringbuffer_init(&h_ringbuf->ringbuf, h_ringbuf->buf_pool, length);
#else
/*Not support now*/
#endif
return (mpp_ringbuf_t)h_ringbuf;
}
void mpp_ringbuffer_destroy(mpp_ringbuf_t rb)
{
if (rb) {
#if defined(KERNEL_RTTHREAD)
struct mpp_ringbuf_handle *h_ringbuf = (struct mpp_ringbuf_handle *)rb;
aicos_free_align(MEM_DEFAULT, h_ringbuf->buf_pool);
mpp_free(rb);
#else
/*Not support now*/
#endif
}
}
void mpp_ringbuffer_reset(mpp_ringbuf_t rb)
{
if (rb) {
#if defined(KERNEL_RTTHREAD)
struct mpp_ringbuf_handle *h_ringbuf = (struct mpp_ringbuf_handle *)rb;
rt_ringbuffer_reset(&h_ringbuf->ringbuf);
#else
/*Not support now*/
#endif
}
}
int mpp_ringbuffer_put(mpp_ringbuf_t rb, const unsigned char *ptr, int length)
{
if (!rb) {
return -1;
}
#if defined(KERNEL_RTTHREAD)
struct mpp_ringbuf_handle *h_ringbuf = (struct mpp_ringbuf_handle *)rb;
return rt_ringbuffer_put(&h_ringbuf->ringbuf, ptr, length);
#else
/*Not support now*/
return -1;
#endif
}
int mpp_ringbuffer_get(mpp_ringbuf_t rb, unsigned char *ptr, int length)
{
if (!rb) {
return -1;
}
#if defined(KERNEL_RTTHREAD)
struct mpp_ringbuf_handle *h_ringbuf = (struct mpp_ringbuf_handle *)rb;
return rt_ringbuffer_get(&h_ringbuf->ringbuf, ptr, length);
#else
/*Not support now*/
return -1;
#endif
}
int mpp_ringbuffer_data_len(mpp_ringbuf_t rb)
{
if (!rb) {
return -1;
}
#if defined(KERNEL_RTTHREAD)
struct mpp_ringbuf_handle *h_ringbuf = (struct mpp_ringbuf_handle *)rb;
return rt_ringbuffer_data_len(&h_ringbuf->ringbuf);
#else
/*Not support now*/
return -1;
#endif
}
int mpp_ringbuffer_space_len(mpp_ringbuf_t rb)
{
if (!rb) {
return -1;
}
#if defined(KERNEL_RTTHREAD)
struct mpp_ringbuf_handle *h_ringbuf = (struct mpp_ringbuf_handle *)rb;
return rt_ringbuffer_space_len(&h_ringbuf->ringbuf);
#else
/*Not support now*/
return -1;
#endif
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <che.jiang@artinchip.com>
* Desc: mpp thread interface
*/
#include "mpp_thread.h"
#include "mpp_log.h"
#include "mpp_mem.h"
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include "rtconfig.h"
#if defined(KERNEL_RTTHREAD) || \
defined(KERNEL_FREERTOS) || \
defined(KERNEL_BAREMETAL) || \
defined(KERNEL_RHINO) || \
defined(KERNEL_UCOS_II)
#define MPP_USING_AIC_OSAL
#endif
#if defined(MPP_USING_AIC_OSAL)
#include "aic_osal.h"
struct mpp_sem_handle {
aicos_sem_t sem;
};
#else
#include <pthread.h>
struct mpp_sem_handle {
pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_condattr_t condattr;
int need_signal;
};
#endif
mpp_sem_t mpp_sem_create()
{
struct mpp_sem_handle *h_sem =
(struct mpp_sem_handle *)mpp_alloc(sizeof(struct mpp_sem_handle));
if (h_sem == NULL)
return NULL;
memset(h_sem, 0, sizeof(struct mpp_sem_handle));
#if defined(MPP_USING_AIC_OSAL)
h_sem->sem = aicos_sem_create(0);
if (!h_sem->sem) {
loge("aicos_sem_create err!!!\n");
return NULL;
}
#else
h_sem->need_signal = 0;
if (pthread_mutex_init(&h_sem->mutex, NULL) != 0) {
loge("pthread_mutex_init err!!!\n");
return NULL;
}
pthread_condattr_init(&h_sem->condattr);
pthread_condattr_setclock(&h_sem->condattr, CLOCK_REALTIME);
pthread_cond_init(&h_sem->cond, &h_sem->condattr);
#endif
return (mpp_sem_t)h_sem;
}
void mpp_sem_delete(mpp_sem_t sem)
{
if (sem) {
struct mpp_sem_handle *h_sem = (struct mpp_sem_handle *)sem;
#if defined(MPP_USING_AIC_OSAL)
aicos_sem_delete(h_sem->sem);
h_sem->sem = NULL;
#else
pthread_condattr_destroy(&h_sem->condattr);
pthread_cond_destroy(&h_sem->cond);
pthread_mutex_destroy(&h_sem->mutex);
#endif
mpp_free(sem);
}
}
int mpp_sem_signal(mpp_sem_t sem)
{
if (!sem)
return -1;
struct mpp_sem_handle *h_sem = (struct mpp_sem_handle *)sem;
#if defined(MPP_USING_AIC_OSAL)
aicos_sem_give(h_sem->sem);
#else
pthread_mutex_lock(&h_sem->mutex);
if (h_sem->need_signal) {
pthread_cond_signal(&h_sem->cond);
}
pthread_mutex_unlock(&h_sem->mutex);
#endif
return 0;
}
int mpp_sem_wait(mpp_sem_t sem, int64_t us)
{
if (!sem)
return -1;
struct mpp_sem_handle *h_sem = (struct mpp_sem_handle *)sem;
#if defined(MPP_USING_AIC_OSAL)
if (us == MPP_WAIT_FOREVER)
aicos_sem_take(h_sem->sem, AICOS_WAIT_FOREVER);
else
aicos_sem_take(h_sem->sem, (unsigned int)(us * 1000));
return 0;
#else
int ret;
pthread_mutex_lock(&h_sem->mutex);
if (us == MPP_WAIT_FOREVER) {
h_sem->need_signal = 1;
ret = pthread_cond_wait(&h_sem->cond, &h_sem->mutex);
h_sem->need_signal = 0;
} else {
struct timespec out_time;
uint64_t tmp;
ret = clock_gettime(CLOCK_REALTIME, &out_time);
out_time.tv_sec += us / (1 * 1000 * 1000);
tmp = out_time.tv_nsec / 1000 + us % (1 * 1000 * 1000);
out_time.tv_sec += tmp / (1 * 1000 * 1000);
tmp = tmp % (1 * 1000 * 1000);
out_time.tv_nsec = tmp * 1000;
h_sem->need_signal = 1;
ret = pthread_cond_timedwait(&h_sem->cond, &h_sem->mutex, &out_time);
h_sem->need_signal = 0;
}
pthread_mutex_unlock(&h_sem->mutex);
return ret;
#endif
}

View File

@@ -159,6 +159,8 @@ enum mpp_dec_errno {
// if frame manager not create, mpp_dec_get_frame return DEC_ERR_FM_NOT_CREATE.
// app should wait a minute to get frame
DEC_ERR_FM_NOT_CREATE = -3,
DEC_ERR_NOT_CREATE = -4,
};
#endif

View File

@@ -1,20 +1,29 @@
/*
* Copyright (C) 2020-2023 ArtInChip Technology Co. Ltd
*
* author: <jun.ma@artinchip.com>
* Desc: aic_audio_decoder interface
*/
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <jun.ma@artinchip.com>
* Desc: aic_audio_decoder interface
*/
#include "mpp_log.h"
#include "audio_decoder.h"
extern struct aic_audio_decoder* create_mp3_decoder();
#ifdef LPKG_USING_LIBFLAC
extern struct aic_audio_decoder* create_flac_decoder();
#endif
struct aic_audio_decoder* aic_audio_decoder_create(enum aic_audio_codec_type type)
{
if(type == MPP_CODEC_AUDIO_DECODER_MP3)
return create_mp3_decoder();
#ifdef LPKG_USING_LIBFLAC
else if (type == MPP_CODEC_AUDIO_DECODER_FLAC)
return create_flac_decoder();
#endif
return NULL;
}

View File

@@ -0,0 +1,565 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <che.jiang@artinchip.com>
* Desc: flac decoder interface
*/
#include <inttypes.h>
#include <pthread.h>
#include <rtthread.h>
#include <string.h>
#include <unistd.h>
#include "FLAC/stream_decoder.h"
#include "audio_decoder.h"
#include "mpp_dec_type.h"
#include "mpp_list.h"
#include "mpp_log.h"
#include "mpp_mem.h"
#include "mpp_thread.h"
#include "mpp_ringbuf.h"
#include "share/compat.h"
#define FLAC_BUFFER_LEN (16 * 1024)
#define FLAC_MIN_FRAME_SIZE 11
#define FLAC_THD_START 0
#define FLAC_THD_STOP 1
#define FLAC_THD_EXIT 2
//#define FLAC_WRITE_FILE
struct flac_stream_decoder_client {
struct aic_audio_decoder *decoder;
uint32_t current_metadata_number;
FLAC__bool ignore_errors;
FLAC__bool error_occurred;
};
struct flac_audio_decoder {
struct aic_audio_decoder decoder;
struct mpp_packet *curr_packet;
FLAC__StreamDecoder *stream_decoder;
unsigned char *flac_buffer;
uint32_t flac_buffer_len;
uint32_t channels;
uint32_t sample_rate;
uint32_t bits_per_sample;
FLAC__uint64 total_samples;
FLAC__uint64 have_samples;
uint32_t frame_id;
uint32_t frame_count;
struct flac_stream_decoder_client decoder_client_data;
mpp_ringbuf_t ringbuf;
pthread_t thread_id;
mpp_sem_t ringbuf_sem;
int packet_end_flag;
int read_end_flag;
int write_end_flag;
int thread_state;
};
static void *flac_decoder_thread(void *p_decoder_data);
#ifdef FLAC_WRITE_FILE
#define FLAC_WRITE_FILE_NAME "/sdcard/test.wav"
static FILE *fout_wav_file = NULL;
extern FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 x);
extern FLAC__bool write_little_endian_int16(FILE *f, FLAC__int16 x);
extern FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 x);
static void flac_decoder_write_file(struct aic_audio_decoder *decoder,
const FLAC__Frame *flac_frame,
const FLAC__int32 *const buffer[])
{
/* write WAVE header before we write the first frame */
int i = 0;
struct flac_audio_decoder *flac_decoder = (struct flac_audio_decoder *)decoder;
FLAC__uint64 total_samples = flac_decoder->total_samples;
unsigned sample_rate = flac_decoder->sample_rate;
unsigned channels = flac_decoder->channels;
unsigned bps = flac_decoder->bits_per_sample;
unsigned total_size = (FLAC__uint32)(total_samples * channels * (bps / 8));
if (flac_frame->header.number.sample_number == 0) {
if ((fout_wav_file = fopen(FLAC_WRITE_FILE_NAME, "wb")) == NULL) {
loge("ERROR: opening %s for output\n", FLAC_WRITE_FILE_NAME);
return;
}
if (
fwrite("RIFF", 1, 4, fout_wav_file) < 4 ||
!write_little_endian_uint32(fout_wav_file, total_size + 36) ||
fwrite("WAVEfmt ", 1, 8, fout_wav_file) < 8 ||
!write_little_endian_uint32(fout_wav_file, 16) ||
!write_little_endian_uint16(fout_wav_file, 1) ||
!write_little_endian_uint16(fout_wav_file, (FLAC__uint16)channels) ||
!write_little_endian_uint32(fout_wav_file, sample_rate) ||
!write_little_endian_uint32(fout_wav_file, sample_rate * channels * (bps / 8)) ||
!write_little_endian_uint16(fout_wav_file, (FLAC__uint16)(channels * (bps / 8))) ||
!write_little_endian_uint16(fout_wav_file, (FLAC__uint16)bps) ||
fwrite("data", 1, 4, fout_wav_file) < 4 ||
!write_little_endian_uint32(fout_wav_file, total_size)) {
loge("ERROR: write error\n");
return;
}
}
/* write decoded PCM samples */
if (fout_wav_file) {
for (i = 0; i < flac_frame->header.blocksize; i++) {
if (
!write_little_endian_int16(fout_wav_file, (FLAC__int16)buffer[0][i]) ||
!write_little_endian_int16(fout_wav_file, (FLAC__int16)buffer[1][i])
) {
loge("ERROR: write error\n");
return;
}
}
printf("write %u to wav file size %d\n.", flac_decoder->frame_id,
flac_frame->header.blocksize * channels);
}
if (fout_wav_file && flac_decoder->frame_id >= 200) {
fclose(fout_wav_file);
fout_wav_file = NULL;
}
}
#endif
static int flac_decoder_put_frame(struct aic_audio_decoder *decoder,
const FLAC__Frame *flac_frame,
const FLAC__int32 *const buffer[])
{
char *data;
int i = 0, pos = 0, try_cnt = 100;
struct flac_audio_decoder *flac_decoder = (struct flac_audio_decoder *)decoder;
struct aic_audio_frame *frame = NULL;
if (flac_decoder->sample_rate <= 0 || flac_decoder->channels < 2 ||
flac_decoder->frame_count < 1) {
loge("wrong flac decoder params: sample_rate %d, channels %d, frame_count %d.",
flac_decoder->sample_rate, flac_decoder->channels, flac_decoder->frame_count);
return -1;
}
if (flac_decoder->decoder.fm == NULL) {
struct audio_frame_manager_cfg cfg;
cfg.bits_per_sample = flac_decoder->bits_per_sample;
cfg.samples_per_frame = flac_decoder->channels * flac_frame->header.blocksize;
cfg.frame_count = flac_decoder->frame_count;
flac_decoder->decoder.fm = audio_fm_create(&cfg);
if (flac_decoder->decoder.fm == NULL) {
loge("audio_fm_create fail!!!\n");
}
return -1;
}
if (flac_decoder->thread_state || flac_decoder->write_end_flag)
return 0;
/*If all sample data has been received, exit directly*/
if (flac_decoder->have_samples > flac_decoder->total_samples)
return 0;
/*Try to get empty frame and write frame data*/
while (i++ < try_cnt) {
frame = audio_fm_decoder_get_frame(flac_decoder->decoder.fm);
if (frame)
break;
usleep(10000);
}
if (!frame) {
flac_decoder->have_samples += flac_frame->header.blocksize;
loge("get empty cur_sample %d, total_samples %"PRIu64", "
"have_samples %"PRIu64", timeout %d ms.",
flac_frame->header.blocksize, flac_decoder->total_samples,
flac_decoder->have_samples, try_cnt * 10);
return -1;
}
frame->pts = (flac_decoder->have_samples) * 1000000 / frame->sample_rate;
flac_decoder->have_samples += flac_frame->header.blocksize;
frame->channels = flac_frame->header.channels;
frame->sample_rate = flac_decoder->sample_rate;
frame->bits_per_sample = flac_decoder->bits_per_sample;
frame->id = flac_decoder->frame_id++;
frame->flag = flac_decoder->have_samples >= flac_decoder->total_samples ? FRAME_FLAG_EOS : 0;
data = frame->data;
if (frame->flag == FRAME_FLAG_EOS)
flac_decoder->write_end_flag = 1;
logd("write_pcm frame_id %d, blocksize %d, pts %lld.", flac_decoder->frame_id,
flac_frame->header.blocksize, frame->pts);
logd("write_pcm total_samples %" PRIu64 ", have_samples %" PRIu64 ".",
flac_decoder->total_samples, flac_decoder->have_samples);
for (i = 0; i < flac_frame->header.blocksize; i++) {
/* output sample(s) in 16-bit signed little-endian PCM */
data[pos++] = ((FLAC__int16)buffer[0][i] >> 0) & 0xff;
data[pos++] = ((FLAC__int16)buffer[0][i] >> 8) & 0xff;
if (frame->channels == 2) {
data[pos++] = ((FLAC__int16)buffer[1][i] >> 0) & 0xff;
data[pos++] = ((FLAC__int16)buffer[1][i] >> 8) & 0xff;
}
}
audio_fm_decoder_put_frame(flac_decoder->decoder.fm, frame);
return 0;
}
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *stream_decoder,
FLAC__byte buffer[],
size_t *bytes,
void *client_data)
{
struct flac_stream_decoder_client *decoder_client =
(struct flac_stream_decoder_client *)client_data;
struct flac_audio_decoder *flac_decoder =
(struct flac_audio_decoder *)decoder_client->decoder;
const size_t requested_bytes = *bytes;
int data_len = 0;
wait_next_data:
if (flac_decoder->thread_state != FLAC_THD_START) {
flac_decoder->read_end_flag = 1;
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
}
data_len = mpp_ringbuffer_data_len(flac_decoder->ringbuf);
/*If the data len less than the request len,
*should be wait enough data coming and then run decoder*/
if (data_len < requested_bytes && flac_decoder->packet_end_flag != FRAME_FLAG_EOS) {
mpp_sem_wait(flac_decoder->ringbuf_sem, MPP_WAIT_FOREVER);
goto wait_next_data;
} else if (data_len == 0 && flac_decoder->packet_end_flag == FRAME_FLAG_EOS) {
logd("flac decoder read the end of stream !!!\n");
flac_decoder->read_end_flag = 1;
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
}
logd("read_callback request byte %ld, data_len %d.", requested_bytes, data_len);
if (requested_bytes > 0) {
if (data_len < requested_bytes)
*bytes = mpp_ringbuffer_get(flac_decoder->ringbuf, buffer, data_len);
else
*bytes = mpp_ringbuffer_get(flac_decoder->ringbuf, buffer, requested_bytes);
if (*bytes == 0) {
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
} else {
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
} else {
return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
}
}
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *stream_decoder,
const FLAC__Frame *frame,
const FLAC__int32 *const buffer[],
void *client_data)
{
struct aic_audio_decoder *decoder =
((struct flac_stream_decoder_client *)client_data)->decoder;
if (frame->header.channels != 2) {
loge("ERROR: This frame contains %u channels (should be 2)\n", frame->header.channels);
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
if (buffer[0] == NULL) {
loge("ERROR: buffer [0] is NULL\n");
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
if (buffer[1] == NULL) {
loge("ERROR: buffer [1] is NULL\n");
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
/* write decoded PCM samples */
#ifdef FLAC_WRITE_FILE
flac_decoder_write_file(decoder, frame, buffer);
#endif
flac_decoder_put_frame(decoder, frame, buffer);
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
static void metadata_callback(const FLAC__StreamDecoder *stream_decoder,
const FLAC__StreamMetadata *metadata, void *client_data)
{
struct flac_audio_decoder *flac_decoder =
(struct flac_audio_decoder *)((struct flac_stream_decoder_client *)client_data)->decoder;
/* print some stats */
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
/* save for later */
flac_decoder->total_samples = metadata->data.stream_info.total_samples;
flac_decoder->sample_rate = metadata->data.stream_info.sample_rate;
flac_decoder->channels = metadata->data.stream_info.channels;
flac_decoder->bits_per_sample = metadata->data.stream_info.bits_per_sample;
printf("sample rate : %u Hz\n", flac_decoder->sample_rate);
printf("channels : %u\n", flac_decoder->channels);
printf("bits per sample: %u\n", flac_decoder->bits_per_sample);
printf("total samples : %" PRIu64 "\n", flac_decoder->total_samples);
}
}
static FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data)
{
struct flac_audio_decoder *flac_decoder =
(struct flac_audio_decoder *)((struct flac_stream_decoder_client *)client_data)->decoder;
if (flac_decoder->thread_state != FLAC_THD_START)
return true;
if (flac_decoder->read_end_flag &&
flac_decoder->have_samples >= flac_decoder->total_samples) {
printf("eof_callback read datalen 0\n");
return true;
} else {
return false;
}
}
static void error_callback(const FLAC__StreamDecoder *decoder,
FLAC__StreamDecoderErrorStatus status, void *client_data)
{
struct flac_audio_decoder *flac_decoder =
(struct flac_audio_decoder *)((struct flac_stream_decoder_client *)client_data)->decoder;
if (!flac_decoder->read_end_flag && (flac_decoder->thread_state == FLAC_THD_START))
loge("Got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
}
int __flac_decode_init(struct aic_audio_decoder *decoder, struct aic_audio_decode_config *config)
{
int ret = DEC_OK;
pthread_attr_t attr;
FLAC__StreamDecoderInitStatus init_status;
struct flac_audio_decoder *flac_decoder = (struct flac_audio_decoder *)decoder;
flac_decoder->ringbuf = mpp_ringbuffer_create(FLAC_BUFFER_LEN);
if (!flac_decoder->ringbuf) {
loge("ERROR: allocating flac ringbuffer failed\n");
return DEC_ERR_NULL_PTR;
}
flac_decoder->flac_buffer_len = FLAC_BUFFER_LEN;
flac_decoder->decoder.pm = audio_pm_create(config);
flac_decoder->frame_count = config->frame_count;
flac_decoder->frame_id = 0;
/*create flac stream decoder*/
flac_decoder->stream_decoder = FLAC__stream_decoder_new();
if (!flac_decoder->stream_decoder) {
loge("ERROR: allocating decoder\n");
ret = DEC_ERR_NULL_PTR;
goto exit;
}
(void)FLAC__stream_decoder_set_md5_checking(flac_decoder->stream_decoder, true);
flac_decoder->decoder_client_data.decoder = decoder;
init_status = FLAC__stream_decoder_init_stream(flac_decoder->stream_decoder,
read_callback,
NULL, NULL, NULL,
eof_callback,
write_callback,
metadata_callback,
error_callback,
&flac_decoder->decoder_client_data);
if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
loge("ERROR: initializing decoder: %s\n",
FLAC__StreamDecoderInitStatusString[init_status]);
ret = DEC_ERR_NOT_CREATE;
goto exit;
}
flac_decoder->ringbuf_sem = mpp_sem_create();
if (!flac_decoder->ringbuf_sem) {
loge("mpp_sem_create ringbuf sem fail!\n");
ret = DEC_ERR_NOT_CREATE;
goto exit;
}
/*create flac stream decoder*/
pthread_attr_init(&attr);
attr.stacksize = 16 * 1024;
attr.schedparam.sched_priority = 22;
flac_decoder->thread_state = FLAC_THD_START;
ret = pthread_create(&flac_decoder->thread_id, &attr,
flac_decoder_thread, flac_decoder);
if (ret) {
loge("thread create flac decoder failed %d!\n", ret);
ret = DEC_ERR_NOT_CREATE;
goto exit;
}
logi("__flac_decode_init success.");
return DEC_OK;
exit:
if (flac_decoder->ringbuf_sem) {
mpp_sem_delete(flac_decoder->ringbuf_sem);
flac_decoder->ringbuf_sem = NULL;
}
if (flac_decoder->ringbuf) {
mpp_ringbuffer_destroy(flac_decoder->ringbuf);
flac_decoder->ringbuf = NULL;
}
if (flac_decoder->stream_decoder) {
FLAC__stream_decoder_delete(flac_decoder->stream_decoder);
flac_decoder->stream_decoder = NULL;
}
if (flac_decoder->decoder.pm) {
audio_pm_destroy(flac_decoder->decoder.pm);
flac_decoder->decoder.pm = NULL;
}
return ret;
}
int __flac_decode_destroy(struct aic_audio_decoder *decoder)
{
struct flac_audio_decoder *flac_decoder = (struct flac_audio_decoder *)decoder;
if (!flac_decoder) {
return DEC_ERR_NOT_CREATE;
}
mpp_sem_signal(flac_decoder->ringbuf_sem);
if (flac_decoder->thread_state == FLAC_THD_START)
flac_decoder->thread_state = FLAC_THD_STOP;
/*wait thread exit and release decoder safety*/
while(flac_decoder->thread_state != FLAC_THD_EXIT)
usleep(5000);
if (flac_decoder->ringbuf_sem) {
mpp_sem_delete(flac_decoder->ringbuf_sem);
flac_decoder->ringbuf_sem = NULL;
}
pthread_join(flac_decoder->thread_id, (void *)NULL);
if (flac_decoder->ringbuf) {
mpp_ringbuffer_destroy(flac_decoder->ringbuf);
flac_decoder->ringbuf = NULL;
}
if (flac_decoder->stream_decoder) {
FLAC__stream_decoder_delete(flac_decoder->stream_decoder);
flac_decoder->stream_decoder = NULL;
}
if (flac_decoder->decoder.pm) {
audio_pm_destroy(flac_decoder->decoder.pm);
flac_decoder->decoder.pm = NULL;
}
if (flac_decoder->decoder.fm) {
audio_fm_destroy(flac_decoder->decoder.fm);
flac_decoder->decoder.fm = NULL;
}
mpp_free(flac_decoder);
return DEC_OK;
}
int __flac_decode_frame(struct aic_audio_decoder *decoder)
{
int ret = DEC_OK;
struct flac_audio_decoder *flac_decoder = (struct flac_audio_decoder *)decoder;
if (!flac_decoder) {
return DEC_ERR_NOT_CREATE;
}
if (flac_decoder->thread_state != FLAC_THD_START) {
return DEC_OK;
}
if ((flac_decoder->decoder.fm) &&
(audio_fm_get_empty_frame_num(flac_decoder->decoder.fm)) == 0) {
return DEC_NO_EMPTY_FRAME;
}
if (flac_decoder->decoder.pm &&
audio_pm_get_ready_packet_num(flac_decoder->decoder.pm) == 0) {
return DEC_NO_READY_PACKET;
}
if (mpp_ringbuffer_space_len(flac_decoder->ringbuf) == 0) {
mpp_sem_signal(flac_decoder->ringbuf_sem);
return DEC_NO_RENDER_FRAME;
}
flac_decoder->curr_packet = audio_pm_dequeue_ready_packet(flac_decoder->decoder.pm);
if (!flac_decoder->curr_packet) {
return DEC_NO_READY_PACKET;
}
/*Avoid the buffer not enough lead to flac decoder failed*/
while (mpp_ringbuffer_space_len(flac_decoder->ringbuf) < flac_decoder->curr_packet->size) {
mpp_sem_signal(flac_decoder->ringbuf_sem);
usleep(5000);
}
ret = mpp_ringbuffer_put(flac_decoder->ringbuf, flac_decoder->curr_packet->data,
flac_decoder->curr_packet->size);
mpp_sem_signal(flac_decoder->ringbuf_sem);
if (ret != flac_decoder->curr_packet->size) {
loge("ringbuffer put size %d < %d", ret, flac_decoder->curr_packet->size);
}
flac_decoder->packet_end_flag = flac_decoder->curr_packet->flag;
if (flac_decoder->curr_packet->flag == FRAME_FLAG_EOS) {
/*Active the flac decoder read_callback, avoid read_callback in wait status*/
mpp_sem_signal(flac_decoder->ringbuf_sem);
usleep(10000);
}
audio_pm_enqueue_empty_packet(flac_decoder->decoder.pm, flac_decoder->curr_packet);
return DEC_OK;
}
int __flac_decode_control(struct aic_audio_decoder *decoder, int cmd, void *param)
{
return DEC_OK;
}
int __flac_decode_reset(struct aic_audio_decoder *decoder)
{
return DEC_OK;
}
static void *flac_decoder_thread(void *p_decoder_data)
{
struct flac_audio_decoder *flac_decoder = (struct flac_audio_decoder *)p_decoder_data;
if (!flac_decoder->stream_decoder) {
loge("stream_decoder is not create");
flac_decoder->thread_state = FLAC_THD_EXIT;
return NULL;
}
FLAC__stream_decoder_process_until_end_of_stream(flac_decoder->stream_decoder);
flac_decoder->thread_state = FLAC_THD_EXIT;
printf("flac_decoder_thread exit.\n");
return NULL;
}
struct aic_audio_decoder_ops flac_decoder = {
.name = "flac",
.init = __flac_decode_init,
.destroy = __flac_decode_destroy,
.decode = __flac_decode_frame,
.control = __flac_decode_control,
.reset = __flac_decode_reset,
};
struct aic_audio_decoder *create_flac_decoder()
{
struct flac_audio_decoder *s =
(struct flac_audio_decoder *)mpp_alloc(sizeof(struct flac_audio_decoder));
if (s == NULL)
return NULL;
memset(s, 0, sizeof(struct flac_audio_decoder));
s->decoder.ops = &flac_decoder;
return &s->decoder;
}

View File

@@ -1,9 +1,11 @@
/*
* Copyright (C) 2020-2023 ArtInChip Technology Co. Ltd
*
* author: <jun.ma@artinchip.com>
* Desc: aic_audio_decoder interface
*/
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <jun.ma@artinchip.com>
* Desc: aic_audio_decoder interface
*/
#ifndef _AIC_AUDIO_DECODER_H_
@@ -16,6 +18,7 @@ enum aic_audio_codec_type {
MPP_CODEC_AUDIO_DECODER_MP3, // decoder
MPP_CODEC_AUDIO_DECODER_AAC,
MPP_CODEC_AUDIO_DECODER_PCM,
MPP_CODEC_AUDIO_DECODER_FLAC,
};
struct aic_audio_frame {

View File

@@ -40,6 +40,13 @@ struct aic_stream {
((const uint8_t*)(x))[0])
#endif
#ifndef AIC_RL24
# define AIC_RL24(x) \
(((uint32_t)((const uint8_t*)(x))[2] << 16) | \
(((const uint8_t*)(x))[1] << 8) | \
((const uint8_t*)(x))[0])
#endif
#ifndef AIC_RL32
# define AIC_RL32(x) \
(((uint32_t)((const uint8_t*)(x))[3] << 24) | \
@@ -48,6 +55,39 @@ struct aic_stream {
((const uint8_t*)(x))[0])
#endif
#ifndef AIC_RB16
# define AIC_RB16(x) \
((((const uint8_t*)(x))[0] << 8) | \
((const uint8_t*)(x))[1])
#endif
#ifndef AIC_RB24
# define AIC_RB24(x) \
(((uint32_t)((const uint8_t*)(x))[0] << 16) | \
(((const uint8_t*)(x))[1] << 8) | \
((const uint8_t*)(x))[2])
#endif
#ifndef AIC_RB32
# define AIC_RB32(x) \
(((uint32_t)((const uint8_t*)(x))[0] << 24) | \
(((const uint8_t*)(x))[1] << 16) | \
(((const uint8_t*)(x))[2] << 8) | \
((const uint8_t*)(x))[3])
#endif
#ifndef AIC_RB64
# define AIC_RB64(x) \
(((uint64_t)((const uint8_t*)(x))[0] << 56) | \
((uint64_t)((const uint8_t*)(x))[1] << 48) | \
((uint64_t)((const uint8_t*)(x))[2] << 40) | \
((uint64_t)((const uint8_t*)(x))[3] << 32) | \
((uint64_t)((const uint8_t*)(x))[4] << 24) | \
((uint64_t)((const uint8_t*)(x))[5] << 16) | \
((uint64_t)((const uint8_t*)(x))[6] << 8) | \
(uint64_t)((const uint8_t*)(x))[7])
#endif
#define aic_stream_read( \
stream, \
buf, \

View File

@@ -16,7 +16,9 @@
#ifdef AIC_MPP_AVI_DEMUX
#include "aic_avi_parser.h"
#endif
#ifdef AIC_MPP_FLAC_DEMUX
#include "aic_flac_parser.h"
#endif
struct aic_parser_create_tbl {
char file_type[7];
@@ -33,6 +35,9 @@ struct aic_parser_create_tbl create_tbl[] = {
#ifdef AIC_MPP_AVI_DEMUX
{"avi", 3, aic_avi_parser_create},
#endif
#ifdef AIC_MPP_FLAC_DEMUX
{"flac", 4, aic_flac_parser_create},
#endif
};
s32 aic_parser_create(unsigned char *uri, struct aic_parser **parser)
{

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <che.jiang@artinchip.com>
* Desc: aic flac parser
*/
#include <malloc.h>
#include <string.h>
#include <stddef.h>
#include <inttypes.h>
#include <fcntl.h>
#include "aic_mov_parser.h"
#include "mpp_log.h"
#include "mpp_mem.h"
#include "mpp_dec_type.h"
#include "aic_stream.h"
#include "flac.h"
#include "aic_flac_parser.h"
s32 flac_peek(struct aic_parser * parser, struct aic_parser_packet *pkt)
{
struct aic_flac_parser *flac_parser = (struct aic_flac_parser *)parser;
return flac_peek_packet(flac_parser,pkt);
}
s32 flac_read(struct aic_parser * parser, struct aic_parser_packet *pkt)
{
struct aic_flac_parser *flac_parser = (struct aic_flac_parser *)parser;
return flac_read_packet(flac_parser,pkt);
}
s32 flac_get_media_info(struct aic_parser *parser, struct aic_parser_av_media_info *media)
{
int i;
struct aic_flac_parser *c = (struct aic_flac_parser *)parser;
media->has_video = 0;
for (i = 0; i < c->nb_streams; i++) {
struct flac_stream_ctx *st = c->streams[i];
if (st->codecpar.codec_type == MPP_MEDIA_TYPE_AUDIO) {
media->has_audio = 1;
media->audio_stream.codec_type = MPP_CODEC_AUDIO_DECODER_FLAC;
media->audio_stream.bits_per_sample =
st->codecpar.bits_per_coded_sample;
media->audio_stream.nb_channel = st->codecpar.channels;
media->audio_stream.sample_rate = st->codecpar.sample_rate;
if (st->codecpar.extradata_size > 0) {
media->audio_stream.extra_data_size =
st->codecpar.extradata_size;
media->audio_stream.extra_data = st->codecpar.extradata;
}
logi("audio bits_per_sample: %d",
st->codecpar.bits_per_coded_sample);
logi("audio channels: %d", st->codecpar.channels);
logi("audio sample_rate: %d", st->codecpar.sample_rate);
logi("audio total_samples: %" PRId64 "", st->total_samples);
} else {
loge("unknown stream(%d) type: %d", i, st->codecpar.codec_type);
}
}
media->file_size = c->file_size;
return 0;
}
s32 flac_seek(struct aic_parser *parser, s64 time)
{
struct aic_flac_parser *flac_parser = (struct aic_flac_parser *)parser;
return flac_seek_packet(flac_parser,time);
}
s32 flac_init(struct aic_parser *parser)
{
struct aic_flac_parser *flac_parser = (struct aic_flac_parser *)parser;
if (flac_read_header(flac_parser)) {
loge("flac read header failed");
return -1;
}
return 0;
}
s32 flac_destroy(struct aic_parser *parser)
{
struct aic_flac_parser *flac_parser = (struct aic_flac_parser *)parser;
if (flac_parser == NULL) {
return -1;
}
flac_close(flac_parser);
aic_stream_close(flac_parser->stream);
mpp_free(flac_parser);
return 0;
}
s32 aic_flac_parser_create(unsigned char *uri, struct aic_parser **parser)
{
s32 ret = 0;
struct aic_flac_parser *flac_parser = NULL;
flac_parser = (struct aic_flac_parser *)mpp_alloc(sizeof(struct aic_flac_parser));
if (flac_parser == NULL) {
loge("mpp_alloc aic_parser for flac failed!!!!!\n");
ret = -1;
goto exit;
}
memset(flac_parser, 0, sizeof(struct aic_flac_parser));
if (aic_stream_open((char *)uri, &flac_parser->stream, O_RDONLY) < 0) {
loge("stream open %s fail", uri);
ret = -1;
goto exit;
}
flac_parser->base.get_media_info = flac_get_media_info;
flac_parser->base.peek = flac_peek;
flac_parser->base.read = flac_read;
flac_parser->base.destroy = flac_destroy;
flac_parser->base.seek = flac_seek;
flac_parser->base.init = flac_init;
*parser = &flac_parser->base;
return ret;
exit:
if (flac_parser->stream) {
aic_stream_close(flac_parser->stream);
}
if (flac_parser) {
mpp_free(flac_parser);
}
return ret;
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <che.jiang@artinchip.com>
* Desc: aic flac parser
*/
#ifndef __AIC_FLAC_PARSER_H__
#define __AIC_FLAC_PARSER_H__
#include "aic_parser.h"
#include "aic_stream.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
s32 aic_flac_parser_create(unsigned char* uri, struct aic_parser **parser);
#ifdef __cplusplus
}
#endif /* End of #ifdef __cplusplus */
#endif

View File

@@ -0,0 +1,206 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <che.jiang@artinchip.com>
* Desc: flac parser
*/
#include "flac.h"
#include "aic_stream.h"
#include "aic_tag.h"
#include "mpp_log.h"
#include "mpp_mem.h"
#include <inttypes.h>
#include <rtthread.h>
#include <stdlib.h>
#define SEEKPOINT_SIZE 18
#define FLAC_STREAMINFO_SIZE 34
#define FLAC_MAX_CHANNELS 8
#define FLAC_MIN_BLOCKSIZE 16
#define FLAC_MAX_BLOCKSIZE 65535
#define FLAC_MIN_FRAME_SIZE 11
#define RAW_PACKET_SIZE 1024
enum {
FLAC_CHMODE_INDEPENDENT = 0,
FLAC_CHMODE_LEFT_SIDE = 1,
FLAC_CHMODE_RIGHT_SIDE = 2,
FLAC_CHMODE_MID_SIDE = 3,
};
enum {
FLAC_METADATA_TYPE_STREAMINFO = 0,
FLAC_METADATA_TYPE_PADDING,
FLAC_METADATA_TYPE_APPLICATION,
FLAC_METADATA_TYPE_SEEKTABLE,
FLAC_METADATA_TYPE_VORBIS_COMMENT,
FLAC_METADATA_TYPE_CUESHEET,
FLAC_METADATA_TYPE_PICTURE,
FLAC_METADATA_TYPE_INVALID = 127
};
static struct flac_stream_ctx *flac_new_stream(struct aic_flac_parser *s)
{
struct flac_stream_ctx *sc;
sc = (struct flac_stream_ctx *)mpp_alloc(sizeof(struct flac_stream_ctx));
if (sc == NULL) {
return NULL;
}
memset(sc, 0, sizeof(struct flac_stream_ctx));
sc->index = s->nb_streams;
s->streams[s->nb_streams++] = sc;
return sc;
}
static inline void flac_parse_block_header(const uint8_t *block_header,
int *last, int *type, int *size)
{
int tmp = block_header[0];
if (last)
*last = tmp & 0x80;
if (type)
*type = tmp & 0x7F;
if (size)
*size = AIC_RB24(block_header + 1);
}
int flac_read_header(struct aic_flac_parser *s)
{
int ret, metadata_last = 0, metadata_type, metadata_size, found_streaminfo = 0;
uint8_t header[4];
uint8_t *buffer = NULL;
struct flac_stream_ctx *st = flac_new_stream(s);
if (!st)
return PARSER_NOMEM;
st->codecpar.codec_type = MPP_MEDIA_TYPE_AUDIO;
st->codecpar.codec_id = MPP_CODEC_AUDIO_DECODER_FLAC;
s->file_size = aic_stream_size(s->stream);
/* the parameters will be extracted from the compressed bitstream */
/* if fLaC marker is not found, assume there is no header */
if (aic_stream_rl32(s->stream) != MKTAG('f', 'L', 'a', 'C')) {
aic_stream_seek(s->stream, -4, SEEK_CUR);
return PARSER_OK;
}
/* process metadata blocks */
while ((aic_stream_tell(s->stream) < s->file_size) && !metadata_last) {
if (aic_stream_read(s->stream, header, 4) != 4)
return PARSER_INVALIDDATA;
flac_parse_block_header(header, &metadata_last, &metadata_type,
&metadata_size);
switch (metadata_type) {
/* allocate and read metadata block for supported types */
case FLAC_METADATA_TYPE_STREAMINFO:
buffer = mpp_alloc(metadata_size + 64);
if (!buffer) {
return PARSER_NOMEM;
}
if (aic_stream_read(s->stream, buffer, metadata_size) != metadata_size) {
return PARSER_NODATA;
}
break;
/* skip metadata block for unsupported types */
default:
ret = aic_stream_skip(s->stream, metadata_size);
if (ret < 0)
return ret;
}
if (metadata_type == FLAC_METADATA_TYPE_STREAMINFO) {
/* STREAMINFO can only occur once */
if (found_streaminfo) {
return PARSER_INVALIDDATA;
}
if (metadata_size != FLAC_STREAMINFO_SIZE) {
return PARSER_INVALIDDATA;
}
found_streaminfo = 1;
st->codecpar.sample_rate = AIC_RB24(buffer + 10) >> 4;
st->codecpar.channels = ((*(buffer + 12) >> 1) & 0x7) + 1;
st->codecpar.bits_per_coded_sample = ((AIC_RB16(buffer + 12) >> 4) & 0x1f) + 1;
st->total_samples = (AIC_RB64(buffer + 13) >> 24) & ((1ULL << 36) - 1);
mpp_free(buffer);
}
}
aic_stream_seek(s->stream, 0, SEEK_SET);
return PARSER_OK;
}
int flac_close(struct aic_flac_parser *s)
{
int i;
for (i = 0; i < s->nb_streams; i++) {
struct flac_stream_ctx *st = s->streams[i];
if (!st) {
continue;
}
mpp_free(st);
}
return PARSER_OK;
}
int flac_seek_packet(struct aic_flac_parser *s, s64 seek_time)
{
return PARSER_ERROR;
}
int flac_peek_packet(struct aic_flac_parser *s, struct aic_parser_packet *pkt)
{
int64_t pos;
static int64_t count = 0;
pos = aic_stream_tell(s->stream);
if (pos >= s->file_size) {
logd("Peek PARSER_EOS,%" PRId64 ",%" PRId64 "\n", pos, s->file_size);
return PARSER_EOS;
}
if (pos + RAW_PACKET_SIZE >= s->file_size)
pkt->size = s->file_size - pos;
else
pkt->size = RAW_PACKET_SIZE;
pkt->type = MPP_MEDIA_TYPE_AUDIO;
pkt->pts = count++;
return PARSER_OK;
}
int flac_read_packet(struct aic_flac_parser *s, struct aic_parser_packet *pkt)
{
int64_t pos;
int ret;
pos = aic_stream_tell(s->stream);
if (pos >= s->file_size) {
loge("PARSER_EOS,%" PRId64 ",%" PRId64 "\n", pos, s->file_size);
return PARSER_EOS;
}
ret = aic_stream_read(s->stream, pkt->data, pkt->size);
pos = aic_stream_tell(s->stream);
if (pos >= s->file_size) {
printf("Read PARSER_EOS,%" PRId64 ",%" PRId64 "\n", pos, s->file_size);
pkt->flag |= PACKET_EOS;
} else {
if (ret != pkt->size) {
loge("hope_len:%d,ret:%d\n", pkt->size, ret);
}
}
return PARSER_OK;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <che.jiang@artinchip.com>
* Desc: flac parser
*/
#ifndef __FLAC_H__
#define __FLAC_H__
#include "aic_parser.h"
#include <unistd.h>
#include "aic_tag.h"
struct flac_stream_ctx {
int index;
uint64_t total_samples;
struct aic_codec_param codecpar;
};
#define FLAC_MAX_TRACK_NUM 1
struct aic_flac_parser {
struct aic_parser base;
struct aic_stream *stream;
uint64_t file_size;
int nb_streams;
struct flac_stream_ctx *streams[FLAC_MAX_TRACK_NUM];
};
int flac_read_header(struct aic_flac_parser *s);
int flac_close(struct aic_flac_parser *s);
int flac_peek_packet(struct aic_flac_parser *s, struct aic_parser_packet *pkt);
int flac_seek_packet(struct aic_flac_parser *s, s64 seek_time);
int flac_read_packet(struct aic_flac_parser *s, struct aic_parser_packet *pkt);
#endif

View File

@@ -798,6 +798,21 @@ static void mm_audio_render_set_attr(mm_audio_render_data *p_audio_render_data)
p_audio_render_data->dev_id);
}
if (p_audio_render_data->volume_change) {
if (p_audio_render_data->render->set_volume(
p_audio_render_data->render,
p_audio_render_data->volume) == 0) {
p_audio_render_data->volume_change = 0;
} else {
loge("set_volume error\n");
}
} else {
p_audio_render_data->volume =
p_audio_render_data->render->get_volume(
p_audio_render_data->render);
logd("volume :%d\n", p_audio_render_data->volume);
}
/*initial state and attr not changed need do set new attr, avoid cost too much time*/
ret = p_audio_render_data->render->get_attr(p_audio_render_data->render, &ao_attr);
ao_attr.bits_per_sample = p_audio_render_data->frame.bits_per_sample;
@@ -815,20 +830,6 @@ static void mm_audio_render_set_attr(mm_audio_render_data *p_audio_render_data)
ao_attr.smples_per_frame = 32 * 1024;
p_audio_render_data->audio_render_attr = ao_attr;
if (p_audio_render_data->volume_change) {
if (p_audio_render_data->render->set_volume(
p_audio_render_data->render,
p_audio_render_data->volume) == 0) {
p_audio_render_data->volume_change = 0;
} else {
loge("set_volume error\n");
}
} else {
p_audio_render_data->volume =
p_audio_render_data->render->get_volume(
p_audio_render_data->render);
logd("volume :%d\n", p_audio_render_data->volume);
}
p_audio_render_data->audio_render_init_flag = 1;
logd("[%s:%d]bits_per_sample:%d,channels:%d,sample_rate:%d,pts:"FMT_d64"\n",
__FUNCTION__, __LINE__, p_audio_render_data->frame.bits_per_sample,

View File

@@ -1,9 +1,11 @@
/*
* Copyright (C) 2020-2023 ArtInChip Technology Co. Ltd
*
* author: <jun.ma@artinchip.com>
* Desc: mini_audio_player
*/
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <jun.ma@artinchip.com>
* Desc: mini_audio_player
*/
#include <string.h>
#include "aic_audio_decoder.h"
@@ -44,6 +46,7 @@ enum MINI_AUDIO_PLAYER_EVENT {
enum PLAYER_FILE_TYPE {
PLAYER_FILE_MP3 = 0,
PLAYER_FILE_WAV = 1,
PLAYER_FILE_FLAC = 2,
};
#define MINI_AUDIO_PLAYER_WAVE_BUFF_SIZE (4*1024)
@@ -215,8 +218,8 @@ static int mini_audio_player_open(struct mini_audio_player *player)
goto _exit;
}
}
} else if (!strncmp(ptr+1, "flac", 4)) {
player->type = PLAYER_FILE_FLAC;
} else {
MINI_AUDIO_PLAYER_ERROR("unsupport file type\n");
goto _exit;
@@ -241,8 +244,12 @@ static int mini_audio_player_open(struct mini_audio_player *player)
player->audio_info.nb_channel = media_info.audio_stream.nb_channel;
player->audio_info.bits_per_sample = media_info.audio_stream.bits_per_sample;
if (player->type == PLAYER_FILE_MP3) {
player->decoder = aic_audio_decoder_create(MPP_CODEC_AUDIO_DECODER_MP3);
if (player->type == PLAYER_FILE_MP3 || player->type == PLAYER_FILE_FLAC) {
if (player->type == PLAYER_FILE_MP3)
player->decoder = aic_audio_decoder_create(MPP_CODEC_AUDIO_DECODER_MP3);
else if (player->type == PLAYER_FILE_FLAC)
player->decoder = aic_audio_decoder_create(MPP_CODEC_AUDIO_DECODER_FLAC);
if (player->decoder == NULL) {
MINI_AUDIO_PLAYER_ERROR("aic_audio_decoder_create fail\n");
goto _exit;
@@ -262,6 +269,14 @@ static int mini_audio_player_open(struct mini_audio_player *player)
MINI_AUDIO_PLAYER_ERROR("aic_audio_render_init fail\n");
goto _exit;
}
// set volume
if (player->volume != 0) {
aic_audio_render_set_volume(player->render,player->volume);
} else {
player->volume = aic_audio_render_get_volume(player->render);
}
// set attr
attr.bits_per_sample = player->audio_info.bits_per_sample;
attr.channels = player->audio_info.nb_channel;
@@ -270,12 +285,6 @@ static int mini_audio_player_open(struct mini_audio_player *player)
MINI_AUDIO_PLAYER_ERROR("aic_audio_render_set_attr fail\n");
goto _exit;
}
// set volume
if (player->volume != 0) {
aic_audio_render_set_volume(player->render,player->volume);
} else {
player->volume = aic_audio_render_get_volume(player->render);
}
return 0;
_exit:
@@ -420,7 +429,11 @@ static void mini_audio_player_entry(void *parameter)
eos = 1;
}
}
aic_audio_decoder_decode(player->decoder);
decoder_ret = aic_audio_decoder_decode(player->decoder);
if (decoder_ret == DEC_NO_RENDER_FRAME) {
need_peek = 0;
usleep(5000);
}
decoder_ret = aic_audio_decoder_get_frame(player->decoder,&audio_frame);
if (decoder_ret == DEC_OK) {
aic_audio_render_rend(player->render,audio_frame.data,audio_frame.size);
@@ -428,6 +441,11 @@ static void mini_audio_player_entry(void *parameter)
if (audio_frame.flag & PARSER_EOS) {
player->state = MINI_AUDIO_PLAYER_STATE_STOPED;
}
} else if (eos && DEC_NO_RENDER_FRAME == decoder_ret &&
player->state != MINI_AUDIO_PLAYER_STATE_STOPED) {
/*Decoder in multithread conditions, should sleep until all data
*decoding to complete*/
usleep(5000);
}
} else {// wav
parser_ret = aic_parser_peek(player->parser,&parser_pkt);

View File

@@ -1,10 +1,11 @@
/*
* Copyright (C) 2020-2023 ArtInChip Technology Co. Ltd
*
* author: <jun.ma@artinchip.com>
* Desc: audio_player_demo
*/
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: <jun.ma@artinchip.com>
* Desc: audio_player_demo
*/
#include <stdio.h>
#include <stdlib.h>
@@ -72,7 +73,7 @@ static int read_dir(char* path, struct audio_file_list *files)
if (ptr == NULL)
continue;
if (strcmp(ptr, ".mp3") && strcmp(ptr, ".wav"))
if (strcmp(ptr, ".mp3") && strcmp(ptr, ".wav") && strcmp(ptr, ".flac"))
continue;
printf("name: %s\n", dir_file->d_name);

View File

@@ -545,6 +545,7 @@ static int player_demo_test(int argc, char **argv)
rt_device_t render_dev = RT_NULL;
struct aicfb_alpha_config alpha_bak = {0};
struct aicfb_alpha_config alpha = {0};
struct aicfb_layer_data layer = {0};
rt_device_t uart_dev = RT_NULL;
struct video_player_ctx *ctx = NULL;
@@ -591,6 +592,16 @@ static int player_demo_test(int argc, char **argv)
alpha.value = ctx->alpha_value;
rt_device_control(render_dev, AICFB_UPDATE_ALPHA_CONFIG, &alpha);
// store ui layer before playing
if (strcmp(PRJ_CHIP, "d12x") == 0) {
layer.layer_id = AICFB_LAYER_TYPE_UI;
if (rt_device_control(render_dev, AICFB_GET_LAYER_CONFIG, &layer) < 0) {
loge("get ui layer config failed\n");
ret = -1;
goto _EXIT_;
}
}
#ifdef _THREAD_TRACE_INFO_
memset(&thread_trace_infos,0x00,sizeof(struct thread_trace_info));
for (i = 0; i < 6 ;i++) {
@@ -696,6 +707,11 @@ _EXIT_:
}
}
if (strcmp(PRJ_CHIP, "d12x") == 0 && render_dev) {
// restore ui layer after playing
rt_device_control(render_dev,AICFB_UPDATE_LAYER_CONFIG,&layer);
}
if (render_dev) {
//restore alpha
rt_device_control(render_dev, AICFB_UPDATE_ALPHA_CONFIG, &alpha_bak);

View File

@@ -41,7 +41,7 @@ int mpp_vin_init(char *camera)
pr_err("Failed to find camera %s\n", camera);
return -1;
}
if (rt_device_open(g_camera_dev, 'r') < 0) {
if (rt_device_open(g_camera_dev, RT_DEVICE_FLAG_RDONLY) < 0) {
pr_err("Failed to open camera %s\n", camera);
return -1;
}