247 lines
7.5 KiB
C
247 lines
7.5 KiB
C
/*
|
|
* Copyright (C) 2010 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/LICENSE-2.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.
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _AUDIO_HWSYNC_H_
|
|
#define _AUDIO_HWSYNC_H_
|
|
|
|
#include <stdbool.h>
|
|
#ifdef BUILD_LINUX
|
|
#include <pthread.h>
|
|
#endif
|
|
|
|
#ifdef USE_MSYNC
|
|
#include <aml_avsync.h>
|
|
#include <aml_avsync_log.h>
|
|
#else
|
|
#include "aml_avsync_stub.h"
|
|
#endif
|
|
#include "audio_mediasync_wrap.h"
|
|
#define SYSTIME_CORRECTION_THRESHOLD (90000*10/100)
|
|
#define NSEC_PER_SECOND 1000000000ULL
|
|
#define HW_SYNC_STATE_HEADER 0
|
|
#define HW_SYNC_STATE_BODY 1
|
|
#define HW_SYNC_STATE_RESYNC 2
|
|
#define HW_SYNC_VERSION_SIZE 4
|
|
|
|
#define HW_AVSYNC_HEADER_SIZE_V1 16
|
|
#define HW_AVSYNC_HEADER_SIZE_V2 20
|
|
#define HW_AVSYNC_HEADER_SIZE_V3 36
|
|
|
|
/*head size is calculated with mOffset = ((int) Math.ceil(HEADER_V2_SIZE_BYTES / frameSizeInBytes)) * frameSizeInBytes;
|
|
*current we only support to 8ch, the headsize is 32
|
|
*/
|
|
#define HW_AVSYNC_MAX_HEADER_SIZE 40 /*max 8ch */
|
|
|
|
|
|
//TODO: After precisely calc the pts, change it back to 1s
|
|
#define APTS_DISCONTINUE_THRESHOLD (90000/10*11)
|
|
#define APTS_DISCONTINUE_THRESHOLD_MIN (90000/1000*100)
|
|
#define APTS_DISCONTINUE_THRESHOLD_MIN_35MS (90000/1000*35)
|
|
#define APTS_TSYNC_DROP_THRESHOLD_MIN_300MS (90000/1000*300)
|
|
#define APTS_TSYNC_START_WAIT_THRESHOLD_US (1*1000*1000)
|
|
|
|
#define APTS_DISCONTINUE_THRESHOLD_MAX (5*90000)
|
|
|
|
#define HWSYNC_APTS_NUM 512
|
|
#define HWSYNC_MAX_BODY_SIZE (65536) ///< Will do fine tune according to the bitstream.
|
|
#define HWSYNC_PTS_EOS UINT64_MAX
|
|
#define HWSYNC_PTS_NA (UINT64_MAX-1)
|
|
|
|
struct audio_stream_out;
|
|
|
|
enum hwsync_status {
|
|
CONTINUATION, // good sync condition
|
|
ADJUSTMENT, // can be adjusted by discarding or padding data
|
|
RESYNC, // pts need resync
|
|
};
|
|
|
|
typedef struct apts_tab {
|
|
int valid;
|
|
size_t offset;
|
|
uint64_t pts;
|
|
} apts_tab_t;
|
|
|
|
typedef enum {
|
|
ESSYNC_AUDIO_DROP = 0,
|
|
ESSYNC_AUDIO_OUTPUT = 1,
|
|
ESSYNC_AUDIO_EXIT = 2,
|
|
} sync_process_res;
|
|
|
|
typedef struct audio_mediasync {
|
|
void* handle;
|
|
int mediasync_id;
|
|
int64_t cur_outapts;
|
|
int64_t out_start_apts;
|
|
struct mediasync_audio_policy apolicy;
|
|
int64_t in_apts;
|
|
}audio_mediasync_t;//for AudioProcess mode
|
|
|
|
typedef struct audio_msync {
|
|
void *msync_session;
|
|
pthread_mutex_t msync_mutex;
|
|
pthread_cond_t msync_cond;
|
|
bool msync_start;
|
|
avs_audio_action msync_action;
|
|
int msync_action_delta;
|
|
uint32_t msync_rendered_pts;
|
|
bool first_apts_flag;//flag to indicate set first apts
|
|
bool msync_first_insert_flag;
|
|
uint64_t first_apts; //record and print
|
|
}audio_msync_t;//for AudioProcess mode
|
|
|
|
typedef enum {
|
|
AV_SYNC_AUDIO_UNKNOWN = 0,
|
|
AV_SYNC_AUDIO_NORMAL_OUTPUT,
|
|
AV_SYNC_AUDIO_DROP_PCM,
|
|
AV_SYNC_AUDIO_INSERT,
|
|
AV_SYNC_AUDIO_HOLD,
|
|
AV_SYNC_AUDIO_MUTE,
|
|
AV_SYNC_AUDIO_RESAMPLE,
|
|
AV_SYNC_AUDIO_ADJUST_CLOCK,
|
|
} av_sync_policy_e;
|
|
|
|
typedef struct audio_avsync {
|
|
audio_mediasync_t *mediasync_ctx;
|
|
audio_msync_t *msync_ctx;
|
|
uint64_t last_lookup_apts;
|
|
uint64_t last_dec_out_frame;
|
|
uint64_t last_output_apts;
|
|
apts_tab_t pts_tab[HWSYNC_APTS_NUM];
|
|
size_t payload_offset;
|
|
int (*get_tuning_latency)(struct audio_stream_out *stream);
|
|
pthread_mutex_t lock;
|
|
}avsync_ctx_t;
|
|
|
|
typedef struct audio_header {
|
|
/* header */
|
|
uint8_t hw_sync_header[HW_AVSYNC_MAX_HEADER_SIZE];
|
|
size_t hw_sync_header_cnt;
|
|
int hw_sync_state;
|
|
uint32_t hw_sync_body_cnt;
|
|
uint32_t hw_sync_frame_size;
|
|
int bvariable_frame_size; //toD
|
|
uint8_t hw_sync_body_buf[HWSYNC_MAX_BODY_SIZE];
|
|
uint8_t body_align_cnt; //toD
|
|
int version_num;
|
|
uint64_t last_apts_from_header;
|
|
uint64_t last_apts_from_header_raw;
|
|
bool eos;
|
|
uint64_t clip_front;
|
|
uint64_t clip_back;
|
|
pthread_mutex_t lock;
|
|
} audio_header_t;
|
|
|
|
typedef struct audio_hbbtvsync {
|
|
int vpts_mt_offset;//vpts -mediatime diff(ms)
|
|
int va_offset;//video -audio diff(ms) at mediatime
|
|
int sync_id;
|
|
} audio_hbbtvsync_t;
|
|
|
|
static inline bool hwsync_header_valid(uint8_t *header)
|
|
{
|
|
return (header[0] == 0x55) &&
|
|
(header[1] == 0x55) &&
|
|
(header[2] == 0x00 || header[2] == 0x01) &&
|
|
(header[3] == 0x01 || header[3] == 0x02 || header[3] == 0x03);
|
|
}
|
|
|
|
static inline uint64_t hwsync_header_get_pts(uint8_t *header)
|
|
{
|
|
return (((uint64_t)header[8]) << 56) |
|
|
(((uint64_t)header[9]) << 48) |
|
|
(((uint64_t)header[10]) << 40) |
|
|
(((uint64_t)header[11]) << 32) |
|
|
(((uint64_t)header[12]) << 24) |
|
|
(((uint64_t)header[13]) << 16) |
|
|
(((uint64_t)header[14]) << 8) |
|
|
((uint64_t)header[15]);
|
|
}
|
|
|
|
static inline uint32_t hwsync_header_get_size(uint8_t *header)
|
|
{
|
|
return (((uint32_t)header[4]) << 24) |
|
|
(((uint32_t)header[5]) << 16) |
|
|
(((uint32_t)header[6]) << 8) |
|
|
((uint32_t)header[7]);
|
|
}
|
|
|
|
static inline uint32_t hwsync_header_get_offset(uint8_t *header)
|
|
{
|
|
return (((uint32_t)header[16]) << 24) |
|
|
(((uint32_t)header[17]) << 16) |
|
|
(((uint32_t)header[18]) << 8) |
|
|
((uint32_t)header[19]);
|
|
}
|
|
|
|
static inline char hwsync_header_get_sub_version(uint8_t *header)
|
|
{
|
|
return header[2];
|
|
}
|
|
|
|
static inline uint64_t hwsync_header_get_clip_front(uint8_t *header)
|
|
{
|
|
return (((uint64_t)header[20]) << 56) |
|
|
(((uint64_t)header[21]) << 48) |
|
|
(((uint64_t)header[22]) << 40) |
|
|
(((uint64_t)header[23]) << 32) |
|
|
(((uint64_t)header[24]) << 24) |
|
|
(((uint64_t)header[25]) << 16) |
|
|
(((uint64_t)header[26]) << 8) |
|
|
((uint64_t)header[27]);
|
|
}
|
|
static inline uint64_t hwsync_header_get_clip_back(uint8_t *header)
|
|
{
|
|
return (((uint64_t)header[28]) << 56) |
|
|
(((uint64_t)header[29]) << 48) |
|
|
(((uint64_t)header[30]) << 40) |
|
|
(((uint64_t)header[31]) << 32) |
|
|
(((uint64_t)header[32]) << 24) |
|
|
(((uint64_t)header[33]) << 16) |
|
|
(((uint64_t)header[34]) << 8) |
|
|
((uint64_t)header[35]);
|
|
}
|
|
|
|
static inline uint64_t get_pts_gap(uint64_t a, uint64_t b)
|
|
{
|
|
if (a >= b) {
|
|
return (a - b);
|
|
} else {
|
|
return (b - a);
|
|
}
|
|
}
|
|
|
|
audio_header_t *audio_header_info_init(void);
|
|
void audio_header_info_reset(audio_header_t *p_header);
|
|
int audio_header_find_frame(audio_header_t *p_header,
|
|
const void *in_buffer, size_t in_bytes,
|
|
uint64_t *cur_pts, int *outsize);
|
|
|
|
void avsync_ctx_reset(avsync_ctx_t *avsync_ctx);
|
|
avsync_ctx_t *avsync_ctx_init(void);
|
|
audio_mediasync_t *mediasync_ctx_init(void);
|
|
audio_msync_t *msync_ctx_init(void);
|
|
void avsync_reset_apts_tbl(avsync_ctx_t *avsync_ctx);
|
|
int avsync_checkin_apts(avsync_ctx_t *avsync_ctx, size_t offset, uint64_t apts);
|
|
int avsync_lookup_apts(avsync_ctx_t *avsync_ctx, size_t offset, uint64_t *p_apts);
|
|
void msync_unblock_start(audio_msync_t *msync_ctx);
|
|
int msync_set_first_pts(audio_msync_t *msync_ctx, uint32_t pts);
|
|
bool skip_check_when_gap(struct audio_stream_out *stream, size_t offset, uint64_t apts);
|
|
int msync_get_policy(struct audio_stream_out *stream, uint64_t apts);
|
|
av_sync_policy_e get_and_map_avsync_policy(avsync_ctx_t *avsync_ctx, int avsync_type);
|
|
#endif
|