Files
2026-08-24 10:03:24 +08:00

584 lines
12 KiB
C

/*
* Copyright (C) 2017 Amlogic Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSEERROR_CODE_INVALID_OPERATION.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* DESCRIPTION
* This file implements a adaptor of audio decoder from Amlogic.
*
*/
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include "AmTsPlayer.h"
#include "mediasession.h"
#include "adecadaptor.h"
#define DEBUG
// #ifdef __cplusplus
// extern "C" {
// #endif
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static int initialized = 0;
static int in_deinit = 0;
static int ready = 0;
static am_tsplayer_handle session = 0;
static am_tsplayer_audio_codec g_acodec = AV_AUDIO_CODEC_AUTO;
static uint64_t timeout_ms = 10;
static uint32_t sleep_us = 1000;
#ifdef DEBUG
#define LOG(fmt, arg...) fprintf(stdout, "[adecadaptor] %s:%d, " fmt, __FUNCTION__, __LINE__, ##arg);
#else
#define LOG(fmt, arg...)
#endif
int init_adec()
{
int ret = ERROR_CODE_OK;
pthread_mutex_lock(&lock);
LOG("enter!\n");
if (initialized == 0)
{
ret = create_session(&session);
if (ret != ERROR_CODE_OK)
{
pthread_mutex_unlock(&lock);
LOG("create_session failed: %d\n", ret);
return ret;
}
initialized = 1;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int deinit_adec()
{
in_deinit = 1;
int ret = ERROR_CODE_OK;
pthread_mutex_lock(&lock);
LOG("enter!\n");
if (initialized != 0)
{
ret = release_session();
if (ret != ERROR_CODE_OK)
{
in_deinit = 0;
pthread_mutex_unlock(&lock);
LOG("release_session failed: %d\n", ret);
return ret;
}
initialized = 0;
}
in_deinit = 0;
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
static am_tsplayer_audio_codec codec_char_to_enum(const char *codec)
{
if (codec == NULL)
{
return AV_AUDIO_CODEC_AUTO;
}
if (strcasecmp(codec, "audio/mp2") == 0)
{
return AV_AUDIO_CODEC_MP2;
}
if (strcasecmp(codec, "audio/mp3") == 0)
{
return AV_AUDIO_CODEC_MP3;
}
if (strcasecmp(codec, "audio/x-ac3") == 0)
{
return AV_AUDIO_CODEC_AC3;
}
if (strcasecmp(codec, "audio/x-eac3") == 0)
{
return AV_AUDIO_CODEC_EAC3;
}
if (strcasecmp(codec, "audio/x-dts") == 0)
{
return AV_AUDIO_CODEC_DTS;
}
if (strcasecmp(codec, "audio/x-private1-dts") == 0)
{
return AV_AUDIO_CODEC_DTS;
}
if (strcasecmp(codec, "audio/aac") == 0)
{
return AV_AUDIO_CODEC_AAC;
}
if (strcasecmp(codec, "audio/x-latm") == 0)
{
return AV_AUDIO_CODEC_LATM;
}
if (strcasecmp(codec, "audio/x-raw") == 0)
{
return AV_AUDIO_CODEC_PCM;
}
if (strcasecmp(codec, "audio/ac4") == 0)
{
return AV_AUDIO_CODEC_AC4;
}
if (strcasecmp(codec, "audio/x-dra") == 0)
{
return AV_AUDIO_CODEC_DRA;
}
if (strcasecmp(codec, "audio/x-flac") == 0)
{
return AV_AUDIO_CODEC_FLAC;
}
if (strcasecmp(codec, "audio/x-vorbis") == 0)
{
return AV_AUDIO_CODEC_VORBIS;
}
if (strcasecmp(codec, "audio/x-opus") == 0)
{
return AV_AUDIO_CODEC_OPUS;
}
if (strcasecmp(codec, "audio/x-max") == 0)
{
return AV_AUDIO_CODEC_MAX;
}
return AV_AUDIO_CODEC_AUTO;
}
int configure_adec(const char *codec)
{
pthread_mutex_lock(&lock);
g_acodec = codec_char_to_enum(codec);
LOG("enter, acodec:%d!\n", g_acodec);
am_tsplayer_audio_params param = {g_acodec, 0x101, 0};
am_tsplayer_result ret = AM_TSPLAYER_OK;
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_setAudioParams(session, &param);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_setAudioParams failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int set_audio_rate(double rate)
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
pthread_mutex_lock(&lock);
LOG("enter, rate:%f!\n", rate);
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_startFast(session, (float)rate);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_startFast failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int start_adec()
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
pthread_mutex_lock(&lock);
LOG("enter!\n");
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
AmTsPlayer_setSyncMode(session, TS_SYNC_AMASTER);
ret = AmTsPlayer_startAudioDecoding(session);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_startAudioDecoding failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
ready = 1;
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int pause_adec()
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
pthread_mutex_lock(&lock);
LOG("enter!\n");
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_pauseAudioDecoding(session);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_pauseAudioDecoding failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
ready = 0;
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int resume_adec()
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
pthread_mutex_lock(&lock);
LOG("enter!\n");
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_resumeAudioDecoding(session);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_resumeAudioDecoding failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
ready = 1;
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int flush_adec()
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
pthread_mutex_lock(&lock);
LOG("enter!\n");
am_tsplayer_audio_params param = {g_acodec, 0x101, 0};
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_stopAudioDecoding(session);
ret |= AmTsPlayer_setAudioParams(session, &param);
ret |= AmTsPlayer_startAudioDecoding(session);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer stop&start failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int stop_adec()
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
pthread_mutex_lock(&lock);
LOG("enter!\n");
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_stopAudioDecoding(session);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_stopAudioDecoding failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
ready = 0;
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int decode_audio(void *data, int32_t size, uint64_t pts)
{
am_tsplayer_input_frame_buffer frame =
{TS_INPUT_BUFFER_TYPE_NORMAL, data, size, pts, 0};
am_tsplayer_result ret = AM_TSPLAYER_OK;
int retry = 100;
if (data == NULL || size < 0)
{
LOG("bad parameter!\n");
return ERROR_CODE_BAD_PARAMETER;
}
pthread_mutex_lock(&lock);
if (initialized == 0 || ready == 0)
{
pthread_mutex_unlock(&lock);
LOG("---uninitialized or not ready!\n");
return ERROR_CODE_INVALID_OPERATION;
}
do
{
ret = AmTsPlayer_writeFrameData(session, &frame, timeout_ms);
if ((AM_TSPLAYER_ERROR_RETRY == ret) && (0 == in_deinit))
{
usleep(sleep_us);
}
else
{
break;
}
} while ((retry-- > 0) && ret);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_writeFrameData failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int mute_audio(int32_t mute)
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
pthread_mutex_lock(&lock);
LOG("enter, mute:%d!\n", mute);
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("---uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_setAudioMute(session, mute, mute);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_setAudioMute(%d) failed: %d\n",
mute, ret);
return ERROR_CODE_BASE_ERROR;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int get_playing_position(int64_t *position_us)
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
if (position_us == NULL)
{
LOG("bad parameter!\n");
return ERROR_CODE_BAD_PARAMETER;
}
pthread_mutex_lock(&lock);
LOG("enter!\n");
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_getCurrentTime(session, position_us);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_getCurrentTime failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int get_volume(int32_t *volume)
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
if (volume == NULL)
{
LOG("bad parameter!\n");
return ERROR_CODE_BAD_PARAMETER;
}
pthread_mutex_lock(&lock);
LOG("enter!\n");
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_getAudioVolume(session, volume);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_getAudioVolume failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int set_volume(int32_t volume)
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
pthread_mutex_lock(&lock);
LOG("enter, vol:%d!\n", volume);
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_setAudioVolume(session, volume);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_setAudioVolume failed: %d, "
"volume: %d\n",
ret, volume);
return ERROR_CODE_BASE_ERROR;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
int get_audio_pts(uint64_t *apts)
{
am_tsplayer_result ret = AM_TSPLAYER_OK;
pthread_mutex_lock(&lock);
if (initialized == 0)
{
pthread_mutex_unlock(&lock);
LOG("uninitialized!\n");
return ERROR_CODE_INVALID_OPERATION;
}
ret = AmTsPlayer_getPts(session, TS_STREAM_AUDIO, apts);
if (ret != AM_TSPLAYER_OK)
{
pthread_mutex_unlock(&lock);
LOG("AmTsPlayer_getPts failed: %d\n", ret);
return ERROR_CODE_BASE_ERROR;
}
pthread_mutex_unlock(&lock);
return ERROR_CODE_OK;
}
// #ifdef __cplusplus
// }
// #endif