mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-29 01:06:56 +00:00
v1.1.1
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
33
packages/artinchip/mpp/base/include/mpp_ringbuf.h
Normal file
33
packages/artinchip/mpp/base/include/mpp_ringbuf.h
Normal 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 */
|
||||
36
packages/artinchip/mpp/base/include/mpp_thread.h
Normal file
36
packages/artinchip/mpp/base/include/mpp_thread.h
Normal 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 */
|
||||
130
packages/artinchip/mpp/base/ringbuf/mpp_ringbuf.c
Normal file
130
packages/artinchip/mpp/base/ringbuf/mpp_ringbuf.c
Normal 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
|
||||
}
|
||||
140
packages/artinchip/mpp/base/thread/mpp_thread.c
Normal file
140
packages/artinchip/mpp/base/thread/mpp_thread.c
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
19
packages/artinchip/mpp/middle_media/audio_decoder/decoder/aic_audio_decoder.c
Executable file → Normal file
19
packages/artinchip/mpp/middle_media/audio_decoder/decoder/aic_audio_decoder.c
Executable file → Normal 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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, \
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
206
packages/artinchip/mpp/middle_media/base/parser/flac/flac.c
Normal file
206
packages/artinchip/mpp/middle_media/base/parser/flac/flac.c
Normal 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;
|
||||
}
|
||||
38
packages/artinchip/mpp/middle_media/base/parser/flac/flac.h
Normal file
38
packages/artinchip/mpp/middle_media/base/parser/flac/flac.h
Normal 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
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user