This commit is contained in:
刘可亮
2024-06-04 19:00:30 +08:00
parent 990c72f5be
commit 0a13af6a1d
1668 changed files with 342810 additions and 37726 deletions

View File

@@ -142,7 +142,6 @@ int decode_final_frame(struct aic_audio_decoder *decoder)
}
unproc_data_len = mp3_decoder->stream.bufend - mp3_decoder->stream.next_frame;
if (unproc_data_len <= 0) {
printf("something wrong happen\n");
return DEC_NO_RENDER_FRAME;
}
memcpy(mp3_decoder->mad_buffer,mp3_decoder->stream.next_frame,unproc_data_len);
@@ -150,8 +149,7 @@ int decode_final_frame(struct aic_audio_decoder *decoder)
mad_stream_buffer(&mp3_decoder->stream,mp3_decoder->mad_buffer,need_proc_data_len);
ret = mad_frame_decode(&mp3_decoder->frame,&mp3_decoder->stream);
if(ret != MAD_ERROR_NONE) {
printf("%s\n",mad_stream_errorstr(&mp3_decoder->stream));
printf("something wrong happen\n");
printf("%s:unproc_data_len:%d\n",mad_stream_errorstr(&mp3_decoder->stream),unproc_data_len);
return DEC_NO_RENDER_FRAME;
}
mad_synth_frame(&mp3_decoder->synth,&mp3_decoder->frame);
@@ -187,7 +185,25 @@ int __mp3_decode_frame(struct aic_audio_decoder *decoder)
if (audio_pm_get_ready_packet_num(mp3_decoder->decoder.pm) == 0) {
if (mp3_decoder->final_frame == 1) {
return decode_final_frame(decoder);
struct aic_audio_frame *frame;
ret = decode_final_frame(decoder);
if (ret == DEC_NO_EMPTY_FRAME || ret== DEC_OK) {
return ret;
}
if(ret == DEC_ERR_NULL_PTR) {
mp3_decoder->final_frame = 0;
return ret;
}
//When decoding the end frame fails, use zero data instead.
printf("decoding the end frame fail,use zero data instead\n");
frame = audio_fm_decoder_get_frame(mp3_decoder->decoder.fm);
memset(frame->data,0x00,frame->size);
frame->flag |= PACKET_FLAG_EOS;
audio_fm_decoder_put_frame(mp3_decoder->decoder.fm, frame);
mp3_decoder->final_frame = 0;
return DEC_OK;
}
return DEC_NO_READY_PACKET;
}

12
packages/artinchip/mpp/middle_media/base/CMakeLists.txt Executable file → Normal file
View File

@@ -1,5 +1,6 @@
set(BASE_MSG
message/aic_message.c
comm/aic_tag.c
)
set(BASE_STREAM
@@ -7,12 +8,20 @@ set(BASE_STREAM
stream/file/aic_file_stream.c
)
if (AVI_DEMUX)
set(DEMUX_AVI
parser/avi/aic_avi_parser.c
parser/avi/avi.c
)
endif()
set(BASE_PARSER
parser/aic_parser.c
parser/mov/aic_mov_parser.c
parser/mov/mov_tags.c
parser/mov/mov.c
parser/rawdata/aic_raw_parser.c
${DEMUX_AVI}
)
set(BASE_RENDER
@@ -33,9 +42,12 @@ add_library(openmax_base SHARED
target_link_libraries(openmax_base base asound)
target_include_directories(openmax_base PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/comm"
"${CMAKE_CURRENT_SOURCE_DIR}/parser/mov"
"${CMAKE_CURRENT_SOURCE_DIR}/parser/avi"
"${CMAKE_CURRENT_SOURCE_DIR}/parser/rawdata"
"${CMAKE_CURRENT_SOURCE_DIR}/stream/file"
)

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* author: <che.jiang@artinchip.com>
* Desc: avi tag
*/
#include <string.h>
#include "aic_tag.h"
#include "mpp_mem.h"
#include "mpp_log.h"
const struct codec_tag aic_codec_bmp_tags[] = {
{ CODEC_ID_H264, MKTAG('H', '2', '6', '4') },
{ CODEC_ID_H264, MKTAG('h', '2', '6', '4') },
{ CODEC_ID_H264, MKTAG('X', '2', '6', '4') },
{ CODEC_ID_H264, MKTAG('x', '2', '6', '4') },
{ CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
{ CODEC_ID_H264, MKTAG('D', 'A', 'V', 'C') },
{ CODEC_ID_H264, MKTAG('S', 'M', 'V', '2') },
{ CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') },
{ CODEC_ID_H264, MKTAG('Q', '2', '6', '4') }, /* QNAP surveillance system */
{ CODEC_ID_H264, MKTAG('V', '2', '6', '4') }, /* CCTV recordings */
{ CODEC_ID_H264, MKTAG('G', 'A', 'V', 'C') }, /* GeoVision camera */
{ CODEC_ID_H264, MKTAG('U', 'M', 'S', 'V') },
{ CODEC_ID_H264, MKTAG('t', 's', 'h', 'd') },
{ CODEC_ID_H264, MKTAG('I', 'N', 'M', 'C') },
{ CODEC_ID_MPEG4, MKTAG('F', 'M', 'P', '4') },
{ CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') },
{ CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0') },
{ CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
{ CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
{ CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
/* some broken AVIs use this */
{ CODEC_ID_MPEG4, MKTAG( 4 , 0 , 0 , 0 ) },
/* some broken AVIs use this */
{ CODEC_ID_MPEG4, MKTAG('Z', 'M', 'P', '4') },
{ CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', '1') },
{ CODEC_ID_MPEG4, MKTAG('B', 'L', 'Z', '0') },
{ CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
{ CODEC_ID_MPEG4, MKTAG('U', 'M', 'P', '4') },
{ CODEC_ID_MPEG4, MKTAG('W', 'V', '1', 'F') },
{ CODEC_ID_MPEG4, MKTAG('S', 'E', 'D', 'G') },
{ CODEC_ID_MPEG4, MKTAG('R', 'M', 'P', '4') },
{ CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') },
/* WaWv MPEG-4 Video Codec */
{ CODEC_ID_MPEG4, MKTAG('W', 'A', 'W', 'V') },
{ CODEC_ID_MPEG4, MKTAG('F', 'F', 'D', 'S') },
{ CODEC_ID_MPEG4, MKTAG('F', 'V', 'F', 'W') },
{ CODEC_ID_MPEG4, MKTAG('D', 'C', 'O', 'D') },
{ CODEC_ID_MPEG4, MKTAG('M', 'V', 'X', 'M') },
{ CODEC_ID_MPEG4, MKTAG('P', 'M', '4', 'V') },
{ CODEC_ID_MPEG4, MKTAG('S', 'M', 'P', '4') },
{ CODEC_ID_MPEG4, MKTAG('D', 'X', 'G', 'M') },
{ CODEC_ID_MPEG4, MKTAG('V', 'I', 'D', 'M') },
{ CODEC_ID_MPEG4, MKTAG('M', '4', 'T', '3') },
{ CODEC_ID_MPEG4, MKTAG('G', 'E', 'O', 'X') },
/* flipped video */
{ CODEC_ID_MPEG4, MKTAG('G', '2', '6', '4') },
/* flipped video */
{ CODEC_ID_MPEG4, MKTAG('H', 'D', 'X', '4') },
{ CODEC_ID_MPEG4, MKTAG('D', 'M', '4', 'V') },
{ CODEC_ID_MPEG4, MKTAG('D', 'M', 'K', '2') },
{ CODEC_ID_MPEG4, MKTAG('D', 'Y', 'M', '4') },
{ CODEC_ID_MPEG4, MKTAG('D', 'I', 'G', 'I') },
/* Ephv MPEG-4 */
{ CODEC_ID_MPEG4, MKTAG('E', 'P', 'H', 'V') },
{ CODEC_ID_MPEG4, MKTAG('E', 'M', '4', 'A') },
/* Divio MPEG-4 */
{ CODEC_ID_MPEG4, MKTAG('M', '4', 'C', 'C') },
{ CODEC_ID_MPEG4, MKTAG('S', 'N', '4', '0') },
{ CODEC_ID_MPEG4, MKTAG('V', 'S', 'P', 'X') },
{ CODEC_ID_MPEG4, MKTAG('U', 'L', 'D', 'X') },
{ CODEC_ID_MPEG4, MKTAG('G', 'E', 'O', 'V') },
{ CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
{ CODEC_ID_MJPEG, MKTAG('M', 'S', 'C', '2') }, /* Multiscope II */
{ CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') },
{ CODEC_ID_MJPEG, MKTAG('d', 'm', 'b', '1') },
{ CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') },
{ CODEC_ID_MJPEG, MKTAG('J', 'R', '2', '4') }, /* Quadrox Mjpeg */
/* Pegasus lossless JPEG */
{ CODEC_ID_MJPEG, MKTAG('J', 'P', 'G', 'L') },
/* JPEG-LS custom FOURCC for AVI - decoder */
{ CODEC_ID_MJPEG, MKTAG('M', 'J', 'L', 'S') },
{ CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') },
{ CODEC_ID_MJPEG, MKTAG('I', 'J', 'P', 'G') },
{ CODEC_ID_MJPEG, MKTAG('A', 'C', 'D', 'V') },
{ CODEC_ID_MJPEG, MKTAG('Q', 'I', 'V', 'G') },
/* SL M-JPEG */
{ CODEC_ID_MJPEG, MKTAG('S', 'L', 'M', 'J') },
/* Creative Webcam JPEG */
{ CODEC_ID_MJPEG, MKTAG('C', 'J', 'P', 'G') },
/* Intel JPEG Library Video Codec */
{ CODEC_ID_MJPEG, MKTAG('I', 'J', 'L', 'V') },
/* Midvid JPEG Video Codec */
{ CODEC_ID_MJPEG, MKTAG('M', 'V', 'J', 'P') },
{ CODEC_ID_MJPEG, MKTAG('A', 'V', 'I', '1') },
{ CODEC_ID_MJPEG, MKTAG('A', 'V', 'I', '2') },
{ CODEC_ID_MJPEG, MKTAG('M', 'T', 'S', 'J') },
/* Paradigm Matrix M-JPEG Codec */
{ CODEC_ID_MJPEG, MKTAG('Z', 'J', 'P', 'G') },
{ CODEC_ID_NONE, 0 }
};
const struct codec_tag aic_codec_wav_tags[] = {
{ CODEC_ID_PCM_S16LE, 0x0001 },
/* must come after s16le in this list */
{ CODEC_ID_PCM_U8, 0x0001 },
{ CODEC_ID_PCM_S24LE, 0x0001 },
{ CODEC_ID_PCM_S32LE, 0x0001 },
{ CODEC_ID_PCM_S64LE, 0x0001 },
{ CODEC_ID_PCM_F32LE, 0x0003 },
/* must come after f32le in this list */
{ CODEC_ID_PCM_F64LE, 0x0003 },
{ CODEC_ID_PCM_ALAW, 0x0006 },
{ CODEC_ID_PCM_MULAW, 0x0007 },
{ CODEC_ID_MP3, 0x0055 },
{ CODEC_ID_AAC, 0x00ff },
/* ADTS AAC */
{ CODEC_ID_AAC, 0x1600 },
{ CODEC_ID_AAC, 0x706d },
{ CODEC_ID_AAC, 0x4143 },
{ CODEC_ID_AAC, 0xA106 },
/* HACK/FIXME: Does Vorbis in WAV/AVI have an (in)official ID? */
{ CODEC_ID_NONE, 0 },
};
enum CodecID aic_codec_get_id(const struct codec_tag *tags, unsigned int tag)
{
int i;
for (i = 0; tags[i].id != CODEC_ID_NONE; i++) {
if (tag == tags[i].tag)
return tags[i].id;
}
return CODEC_ID_NONE;
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* author: <che.jiang@artinchip.com>
* Desc: aic tag, internal header for aic based (de)muxers
*/
#ifndef AIC_TAGS_H
#define AIC_TAGS_H
#include "aic_parser.h"
#include "aic_stream.h"
#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))
enum CodecID {
CODEC_ID_NONE,
/* video codecs */
CODEC_ID_MJPEG,
CODEC_ID_H264,
CODEC_ID_MPEG4,
/* various PCM "codecs" */
CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
CODEC_ID_PCM_S16LE = 0x10000,
CODEC_ID_PCM_S16BE,
CODEC_ID_PCM_U16LE,
CODEC_ID_PCM_U16BE,
CODEC_ID_PCM_S8,
CODEC_ID_PCM_U8,
CODEC_ID_PCM_MULAW,
CODEC_ID_PCM_ALAW,
CODEC_ID_PCM_S32LE,
CODEC_ID_PCM_S32BE,
CODEC_ID_PCM_U32LE,
CODEC_ID_PCM_U32BE,
CODEC_ID_PCM_S24LE,
CODEC_ID_PCM_S24BE,
CODEC_ID_PCM_U24LE,
CODEC_ID_PCM_U24BE,
CODEC_ID_PCM_S24DAUD,
CODEC_ID_PCM_ZORK,
CODEC_ID_PCM_S16LE_PLANAR,
CODEC_ID_PCM_DVD,
CODEC_ID_PCM_F32BE,
CODEC_ID_PCM_F32LE,
CODEC_ID_PCM_F64BE,
CODEC_ID_PCM_F64LE,
CODEC_ID_PCM_BLURAY,
CODEC_ID_PCM_LXF,
CODEC_ID_PCM_S8_PLANAR,
CODEC_ID_PCM_S24LE_PLANAR,
CODEC_ID_PCM_S32LE_PLANAR,
CODEC_ID_PCM_S16BE_PLANAR,
CODEC_ID_PCM_S64LE,
CODEC_ID_PCM_S64BE,
CODEC_ID_PCM_F16LE,
CODEC_ID_PCM_F24LE,
CODEC_ID_PCM_VIDC,
CODEC_ID_PCM_SGA,
CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3
CODEC_ID_AAC,
};
struct codec_tag {
enum CodecID id;
unsigned int tag;
};
struct aic_codec_param {
enum aic_parser_stream_type codec_type;
enum CodecID codec_id;
uint32_t codec_tag;
uint8_t *extradata;
int extradata_size;
int64_t bit_rate;
int bits_per_coded_sample;
/* Video only.*/
int width;
int height;
/* Audio only.*/
int channels;
int sample_rate;
int block_align;
};
extern const struct codec_tag aic_codec_bmp_tags[];
extern const struct codec_tag aic_codec_wav_tags[];
enum CodecID aic_codec_get_id(const struct codec_tag *tags, unsigned int tag);
#endif /* AIC_TAGS_H */

View File

@@ -14,13 +14,14 @@
#include "mpp_log.h"
#ifdef __cplusplus
extern "C"{
extern "C" {
#endif /* __cplusplus */
enum aic_parser_type {
PARSER_TYPE_UNKNOW = -1,
PARSER_TYPE_MOV,
PARSER_TYPE_RAW,
PARSER_TYPE_AVI,
};
enum aic_parser_stream_type {
@@ -34,9 +35,17 @@ enum parse_status {
PARSER_ERROR = -1,
PARSER_OK = 0,
PARSER_EOS = 1,
PARSER_NOMEM = 2,
PARSER_NODATA = 3,
PARSER_INVALIDDATA = 4,
PARSER_INVALIDPARAM = 5,
};
#define PACKET_EOS (1)
#define TIME_BASE 1000000LL
#define MPP_MAX(a, b) ((a)>(b)? (a) : (b))
#define MPP_MIN(a, b) ((a)<(b)? (a) : (b))
struct aic_parser_packet {
enum aic_parser_stream_type type;
void *data;

View File

@@ -9,7 +9,7 @@
#define __AIC_STREAM_H__
#ifdef __cplusplus
extern "C"{
extern "C" {
#endif /* __cplusplus */
#include "mpp_dec_type.h"
@@ -29,6 +29,20 @@ struct aic_stream {
s64 (*size)(struct aic_stream *stream);
};
#ifndef AIC_RL16
# define AIC_RL16(x) \
((((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) | \
(((const uint8_t*)(x))[2] << 16) | \
(((const uint8_t*)(x))[1] << 8) | \
((const uint8_t*)(x))[0])
#endif
#define aic_stream_read( \
stream, \
buf, \
@@ -52,6 +66,30 @@ struct aic_stream {
s32 aic_stream_open(char *uri, struct aic_stream **stream);
int aic_stream_skip(struct aic_stream* s, int len);
void aic_stream_w8(struct aic_stream* s, int b);
void aic_stream_write(struct aic_stream* s, const unsigned char *buf, int size);
void aic_stream_wl64(struct aic_stream* s, uint64_t val);
void aic_stream_wb64(struct aic_stream* s, uint64_t val);
void aic_stream_wl32(struct aic_stream* s, unsigned int val);
void aic_stream_wb32(struct aic_stream* s, unsigned int val);
void aic_stream_wl24(struct aic_stream* s, unsigned int val);
void aic_stream_wb24(struct aic_stream* s, unsigned int val);
void aic_stream_wl16(struct aic_stream* s, unsigned int val);
void aic_stream_wb16(struct aic_stream* s, unsigned int val);
int aic_stream_r8 (struct aic_stream* s);
unsigned int aic_stream_rl16(struct aic_stream* s);
unsigned int aic_stream_rl24(struct aic_stream* s);
unsigned int aic_stream_rl32(struct aic_stream* s);
uint64_t aic_stream_rl64(struct aic_stream* s);
unsigned int aic_stream_rb16(struct aic_stream* s);
unsigned int aic_stream_rb24(struct aic_stream* s);
unsigned int aic_stream_rb32(struct aic_stream* s);
uint64_t aic_stream_rb64(struct aic_stream* s);
#ifdef __cplusplus
#if __cplusplus
}

View File

@@ -11,10 +11,32 @@
#include "aic_raw_parser.h"
#include "aic_mp3_parser.h"
#include "aic_wav_parser.h"
#ifdef AIC_MPP_AVI_DEMUX
#include "aic_avi_parser.h"
#endif
struct aic_parser_create_tbl {
char file_type[7];
unsigned char len;
s32 (*parser)(unsigned char *uri, struct aic_parser **parser);
};
struct aic_parser_create_tbl create_tbl[] = {
{"mov", 3, aic_mov_parser_create},
{"mp4", 3, aic_mov_parser_create},
{"264", 3, aic_raw_parser_create},
{"mp3", 3, aic_mp3_parser_create},
{"wav", 3, aic_wav_parser_create},
#ifdef AIC_MPP_AVI_DEMUX
{"avi", 3, aic_avi_parser_create},
#endif
};
s32 aic_parser_create(unsigned char *uri, struct aic_parser **parser)
{
int i = 0;
char* ptr = NULL;
int size = 0;
if (uri == NULL) {
return -1;
@@ -25,14 +47,14 @@ s32 aic_parser_create(unsigned char *uri, struct aic_parser **parser)
return -1;
}
if (!strncmp(ptr+1, "mov", 3) || !strncmp(ptr+1, "mp4", 3)) {
return aic_mov_parser_create(uri, parser);
} else if (!strncmp(ptr+1, "264", 3)) {
return aic_raw_parser_create(uri, parser);
} else if (!strncmp(ptr+1, "mp3", 3)) {
return aic_mp3_parser_create(uri, parser);
} else if (!strncmp(ptr+1, "wav", 3)) {
return aic_wav_parser_create(uri, parser);
printf("parser for (%s)\n", uri);
size = sizeof(create_tbl)/sizeof(struct aic_parser_create_tbl);
for (i = 0; i < size; i++) {
if (!strncmp(ptr+1, create_tbl[i].file_type, create_tbl[i].len)) {
return create_tbl[i].parser(uri, parser);
}
}
logw("unkown parser for (%s)", uri);

View File

@@ -0,0 +1,177 @@
/*
* Copyright (C) 2020-2024 Artinchip Technology Co. Ltd
*
* author: <che.jiang@artinchip.com>
* Desc: aic_avi_parser
*/
#define LOG_TAG "avi_parse"
#include <malloc.h>
#include <string.h>
#include <stddef.h>
#include <fcntl.h>
#include <inttypes.h>
#include "aic_avi_parser.h"
#include "mpp_log.h"
#include "mpp_mem.h"
#include "mpp_dec_type.h"
#include "aic_stream.h"
#include "aic_parser.h"
#include "avi.h"
s32 avi_peek(struct aic_parser *parser, struct aic_parser_packet *pkt)
{
struct aic_avi_parser *avi_parse_parser = (struct aic_avi_parser *)parser;
return avi_peek_packet(avi_parse_parser, pkt);
}
s32 avi_read(struct aic_parser *parser, struct aic_parser_packet *pkt)
{
struct aic_avi_parser *avi_parse_parser = (struct aic_avi_parser *)parser;
return avi_read_packet(avi_parse_parser, pkt);
}
s32 avi_get_media_info(struct aic_parser *parser,
struct aic_parser_av_media_info *media)
{
int i;
int64_t duration = 0;
struct aic_avi_parser *c = (struct aic_avi_parser *)parser;
logi("================ media info =======================");
for (i = 0; i < c->nb_streams; i++) {
struct avi_stream_ctx *st = c->streams[i];
if (st->codecpar.codec_type == MPP_MEDIA_TYPE_VIDEO) {
media->has_video = 1;
if (st->codecpar.codec_id == CODEC_ID_H264)
media->video_stream.codec_type = MPP_CODEC_VIDEO_DECODER_H264;
else if (st->codecpar.codec_id == CODEC_ID_MJPEG)
media->video_stream.codec_type = MPP_CODEC_VIDEO_DECODER_MJPEG;
else
media->video_stream.codec_type = -1;
media->video_stream.width = st->codecpar.width;
media->video_stream.height = st->codecpar.height;
if (st->codecpar.extradata_size > 0) {
media->video_stream.extra_data_size =
st->codecpar.extradata_size;
media->video_stream.extra_data = st->codecpar.extradata;
}
logi("video codec_type: %d codec_id %d",
media->video_stream.codec_type, st->codecpar.codec_id);
logi("video width: %d, height: %d", st->codecpar.width,
st->codecpar.height);
logi("video extra_data_size: %d", st->codecpar.extradata_size);
} else if (st->codecpar.codec_type == MPP_MEDIA_TYPE_AUDIO) {
media->has_audio = 1;
if (st->codecpar.codec_id == CODEC_ID_MP3)
media->audio_stream.codec_type = MPP_CODEC_AUDIO_DECODER_MP3;
else if (st->codecpar.codec_id == CODEC_ID_AAC)
media->audio_stream.codec_type = MPP_CODEC_AUDIO_DECODER_AAC;
else
media->audio_stream.codec_type = MPP_CODEC_AUDIO_DECODER_UNKOWN;
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 extra_data_size: %d", st->codecpar.extradata_size);
} else {
loge("unknown stream(%d) type: %d", i, st->codecpar.codec_type);
}
if (st->duration > duration)
duration = st->duration;
}
media->file_size = aic_stream_size(c->stream);
media->seek_able = 1;
media->duration = duration;
return 0;
}
s32 avi_seek(struct aic_parser *parser, s64 time)
{
s32 ret = 0;
struct aic_avi_parser *avi_parse_parser = (struct aic_avi_parser *)parser;
ret = avi_seek_packet(avi_parse_parser, time);
return ret;
}
s32 avi_parse_init(struct aic_parser *parser)
{
struct aic_avi_parser *avi_parse_parser = (struct aic_avi_parser *)parser;
if (avi_read_header(avi_parse_parser) < 0) {
loge("avi_parse open failed");
return -1;
}
return 0;
}
s32 avi_parse_destroy(struct aic_parser *parser)
{
struct aic_avi_parser *avi_parser = (struct aic_avi_parser *)parser;
if (parser == NULL) {
return -1;
}
avi_read_close(avi_parser);
aic_stream_close(avi_parser->stream);
mpp_free(avi_parser);
return 0;
}
s32 aic_avi_parser_create(unsigned char *uri, struct aic_parser **parser)
{
s32 ret = 0;
struct aic_avi_parser *avi_parser = NULL;
avi_parser =
(struct aic_avi_parser *)mpp_alloc(sizeof(struct aic_avi_parser));
if (avi_parser == NULL) {
loge("mpp_alloc aic_parser failed!!!!!\n");
ret = -1;
goto exit;
}
memset(avi_parser, 0, sizeof(struct aic_avi_parser));
if (aic_stream_open((char *)uri, &avi_parser->stream) < 0) {
loge("stream open fail");
ret = -1;
goto exit;
}
avi_parser->base.get_media_info = avi_get_media_info;
avi_parser->base.peek = avi_peek;
avi_parser->base.read = avi_read;
avi_parser->base.destroy = avi_parse_destroy;
avi_parser->base.seek = avi_seek;
avi_parser->base.init = avi_parse_init;
*parser = &avi_parser->base;
return ret;
exit:
if (avi_parser->stream) {
aic_stream_close(avi_parser->stream);
}
if (avi_parser) {
mpp_free(avi_parser);
}
return ret;
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
*
* author: <che.jiang@artinchip.com>
* Desc: aic_avi_parser
*/
#ifndef __AIC_AVI_PARSER_H__
#define __AIC_AVI_PARSER_H__
#include "aic_parser.h"
#include "aic_stream.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
s32 aic_avi_parser_create(unsigned char *uri, struct aic_parser **parser);
#ifdef __cplusplus
}
#endif /* End of #ifdef __cplusplus */
#endif

View File

@@ -0,0 +1,992 @@
/*
* Copyright (C) 2020-2024 Artinchip Technology Co. Ltd
*
* author: <che.jiang@artinchip.com>
* Desc: avi.c
*/
#define LOG_TAG "avi"
#include <inttypes.h>
#include <stdlib.h>
#include "aic_stream.h"
#include "avi.h"
#include "mpp_mem.h"
#include "mpp_log.h"
#include "aic_parser.h"
#include "aic_tag.h"
static const char avi_headers[][8] = {
{ 'R', 'I', 'F', 'F', 'A', 'V', 'I', ' ' },
{ 'R', 'I', 'F', 'F', 'A', 'V', 'I', 'X' },
{ 'R', 'I', 'F', 'F', 'A', 'V', 'I', 0x19 },
{ 'O', 'N', '2', ' ', 'O', 'N', '2', 'f' },
{ 'R', 'I', 'F', 'F', 'A', 'M', 'V', ' ' },
{ 0 }
};
static int avi_load_index(struct aic_avi_parser *s);
int alloc_extradata(struct aic_codec_param *par, int size)
{
mpp_free(par->extradata);
par->extradata_size = 0;
if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
return -1;
par->extradata = mpp_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!par->extradata)
return -1;
memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
par->extradata_size = size;
return 0;
}
int get_extradata(struct aic_codec_param *par, struct aic_stream *pb, int size)
{
int ret = alloc_extradata(par, size);
if (ret < 0)
return ret;
ret = aic_stream_read(pb, par->extradata, size);
if (ret != size) {
mpp_free(par->extradata);
par->extradata_size = 0;
logi("Failed to read extradata of size %d\n", size);
return ret;
}
return ret;
}
int get_video_extradata(struct aic_stream *c, struct avi_stream_ctx *st)
{
int ret = PARSER_OK;
// FIXME: check if the encoder really did this correctly
if (st->codecpar.extradata_size & 1)
aic_stream_r8(c);
/* Extract palette from extradata if bpp <= 8.
* This code assumes that extradata contains only palette.
* This is true for all paletted codecs implemented in
* FFmpeg. */
if (st->codecpar.extradata_size &&
(st->codecpar.bits_per_coded_sample <= 8)) {
int pal_size = (1 << st->codecpar.bits_per_coded_sample) << 2;
const uint8_t *pal_src;
pal_size = MPP_MIN(pal_size, st->codecpar.extradata_size);
pal_src =
st->codecpar.extradata + st->codecpar.extradata_size - pal_size;
/* Exclude the "BottomUp" field from the palette */
if (pal_src - st->codecpar.extradata >= 9 &&
!memcmp(st->codecpar.extradata + st->codecpar.extradata_size - 9,
"BottomUp", 9))
pal_src -= 9;
// for (i = 0; i < pal_size / 4; i++)
// ast->pal[i] = 0xFFU<<24 | AV_RL32(pal_src + 4 * i);
// ast->has_pal = 1;
}
logi("video width %d, height %d\n", st->codecpar.width,
st->codecpar.height);
if (st->codecpar.codec_tag == 0 && st->codecpar.height > 0 &&
st->codecpar.extradata_size < 1U << 30) {
int old_extradata_size =
st->codecpar.extradata_size + AV_INPUT_BUFFER_PADDING_SIZE;
st->codecpar.extradata_size += 9;
void *extradata = mpp_alloc(st->codecpar.extradata_size +
AV_INPUT_BUFFER_PADDING_SIZE);
if (!extradata) {
st->codecpar.extradata_size = 0;
return PARSER_NOMEM;
} else {
memcpy(extradata, st->codecpar.extradata, old_extradata_size);
mpp_free(st->codecpar.extradata);
st->codecpar.extradata = extradata;
memcpy(st->codecpar.extradata + st->codecpar.extradata_size - 9,
"BottomUp", 9);
}
}
return ret;
}
/* "big_endian" values are needed for RIFX file format */
int get_wav_header(struct aic_stream *pb, struct aic_codec_param *par, int size,
int big_endian)
{
int id;
uint64_t bitrate = 0;
if (size < 14) {
loge("wav header size < 14");
return PARSER_INVALIDDATA;
}
par->codec_type = MPP_MEDIA_TYPE_AUDIO;
if (!big_endian) {
id = aic_stream_rl16(pb);
if (id != 0x0165) {
par->channels = aic_stream_rl16(pb);
par->sample_rate = aic_stream_rl32(pb);
bitrate = aic_stream_rl32(pb) * 8LL;
par->block_align = aic_stream_rl16(pb);
}
} else {
id = aic_stream_rb16(pb);
par->channels = aic_stream_rb16(pb);
par->sample_rate = aic_stream_rb32(pb);
bitrate = aic_stream_rb32(pb) * 8LL;
par->block_align = aic_stream_rb16(pb);
}
if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */
par->bits_per_coded_sample = 8;
} else {
if (!big_endian) {
par->bits_per_coded_sample = aic_stream_rl16(pb);
} else {
par->bits_per_coded_sample = aic_stream_rb16(pb);
}
}
if (id == 0xFFFE) {
par->codec_tag = 0;
} else {
par->codec_tag = id;
par->codec_id = aic_codec_get_id(aic_codec_wav_tags, id);
}
if (size >= 18 &&
id != 0x0165) { /* We're obviously dealing with WAVEFORMATEX */
int cbSize = aic_stream_rl16(pb); /* cbSize */
if (big_endian) {
loge("WAVEFORMATEX support for RIFX files");
return PARSER_ERROR;
}
size -= 18;
cbSize = MPP_MIN(size, cbSize);
if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */
cbSize -= 22;
size -= 22;
}
/*audio decoder not support extradata, may be failed */
#if 0
if (cbSize > 0) {
if (get_extradata(par, pb, cbSize) < 0)
return PARSER_INVALIDDATA;
size -= cbSize;
}
#endif
/* It is possible for the chunk to contain garbage at the end */
if (size > 0)
aic_stream_skip(pb, size);
} else if (id == 0x0165 && size >= 32) {
int nb_streams, i;
size -= 4;
if (get_extradata(par, pb, size) < 0)
return PARSER_INVALIDDATA;
nb_streams = AIC_RL16(par->extradata + 4);
par->sample_rate = AIC_RL32(par->extradata + 12);
par->channels = 0;
bitrate = 0;
if (size < 8 + nb_streams * 20)
return PARSER_INVALIDDATA;
for (i = 0; i < nb_streams; i++)
par->channels += par->extradata[8 + i * 20 + 17];
}
par->bit_rate = bitrate;
if (par->sample_rate <= 0) {
loge("Invalid sample rate: %d\n", par->sample_rate);
return PARSER_INVALIDDATA;
}
return 0;
}
int get_bmp_header(struct aic_stream *pb, struct aic_codec_param *par,
unsigned int *size)
{
int tag1;
uint32_t size_ = aic_stream_rl32(pb);
if (size)
*size = size_;
par->width = aic_stream_rl32(pb);
par->height = (int32_t)aic_stream_rl32(pb);
aic_stream_rl16(pb); /* planes */
aic_stream_rl16(pb); /* depth */
tag1 = aic_stream_rl32(pb);
aic_stream_rl32(pb); /* ImageSize */
aic_stream_rl32(pb); /* XPelsPerMeter */
aic_stream_rl32(pb); /* YPelsPerMeter */
aic_stream_rl32(pb); /* ClrUsed */
aic_stream_rl32(pb); /* ClrImportant */
return tag1;
}
static inline int get_duration(struct avi_stream *ast, int len)
{
if (ast->sample_size)
return len;
else if (ast->dshow_block_align)
return (len + (int64_t)ast->dshow_block_align - 1) /
ast->dshow_block_align;
else
return 1;
}
static int64_t get_time(int64_t timestamp, uint32_t rate, uint32_t scale)
{
if (!(scale && rate)) {
loge("scale/rate is %" PRIu32 "/%" PRIu32 " which is invalid. "
"(This file has been generated by broken software.)\n",
scale, rate);
rate = 25;
scale = 1;
}
return (int64_t)(timestamp * TIME_BASE * scale) / rate;
}
static int find_index_by_pts(struct avi_stream_ctx *st, s64 pts)
{
int i, index = 0;
int64_t min = INT64_MAX;
int64_t sample_pts = 0;
int64_t diff = 0;
struct avi_index_entry *cur_sample = NULL;
struct avi_stream *ast = st->priv_data;
for (i = 0; i < st->nb_index_entries; i++) {
cur_sample = &st->index_entries[i];
sample_pts = get_time(cur_sample->timestamp, ast->rate, ast->scale);
diff = MPP_ABS(pts, sample_pts);
if (diff < min) {
min = diff;
index = i;
}
}
return index;
}
static int find_video_index_by_pts(struct avi_stream_ctx *video_st, s64 pts)
{
int i, index = 0;
int64_t min = INT64_MAX;
int64_t sample_pts = 0;
int64_t diff = 0;
struct avi_index_entry *cur_sample = NULL;
struct avi_stream *ast = video_st->priv_data;
logd("nb_index_entries:%d\n", video_st->nb_index_entries);
/* First step: find current frame by pts*/
for (i = 0; i < video_st->nb_index_entries; i++) {
cur_sample = &video_st->index_entries[i];
sample_pts = get_time(cur_sample->timestamp, ast->rate, ast->scale);
diff = MPP_ABS(pts, sample_pts);
if (diff < min) {
min = diff;
index = i;
}
}
/* Second step find the key frame before current frame*/
while (index--) {
cur_sample = &video_st->index_entries[index];
if (cur_sample->flags == 1) {
return index;
}
}
return PARSER_ERROR;
}
static int get_riff(struct aic_avi_parser *s)
{
struct aic_stream *c = s->stream;
struct avi_context *avi = &s->avi_c;
char header[8] = { 0 };
int i;
/* check RIFF header */
aic_stream_read(c, header, 4);
avi->riff_end = aic_stream_rl32(c); /* RIFF chunk size */
avi->riff_end += aic_stream_tell(c); /* RIFF chunk end */
aic_stream_read(c, header + 4, 4);
for (i = 0; avi_headers[i][0]; i++)
if (!memcmp(header, avi_headers[i], 8))
break;
if (!avi_headers[i][0])
return PARSER_ERROR;
if (header[7] == 0x19)
logi("This file has been generated by a totally broken muxer.\n");
return PARSER_OK;
}
static struct avi_stream_ctx *avi_new_stream(struct aic_avi_parser *s)
{
struct avi_stream_ctx *sc;
sc = (struct avi_stream_ctx *)mpp_alloc(sizeof(struct avi_stream_ctx));
if (sc == NULL) {
return NULL;
}
memset(sc, 0, sizeof(struct avi_stream_ctx));
sc->index = s->nb_streams;
s->streams[s->nb_streams++] = sc;
return sc;
}
int get_avi_header(struct aic_stream *c, struct avi_context *avi)
{
int frame_period = aic_stream_rl32(c);
aic_stream_rl32(c); /* max. bytes per second */
aic_stream_rl32(c);
avi->non_interleaved |= aic_stream_rl32(c) & AVIF_MUSTUSEINDEX;
aic_stream_skip(c, 2 * 4);
aic_stream_rl32(c);
aic_stream_rl32(c);
aic_stream_rl32(c); /* avih_width */
aic_stream_rl32(c); /* avih_height */
return frame_period;
}
int get_strh_info(struct aic_avi_parser *s, unsigned int size,
int frame_period, int *stream_index, int *type)
{
struct avi_stream_ctx *st = NULL;
struct avi_stream *ast = NULL;
struct aic_stream *c = s->stream;
int codec_type = MPP_MEDIA_TYPE_UNKNOWN;
int tag1 = aic_stream_rl32(c); /* stream_type, vids、auds */
unsigned int handler = aic_stream_rl32(c); /* codec tag */
if (tag1 == MKTAG('p', 'a', 'd', 's')) {
aic_stream_skip(c, size - 8);
return PARSER_OK;
} else {
(*stream_index)++;
st = avi_new_stream(s);
if (!st)
return PARSER_ERROR;
st->index = *stream_index;
ast = mpp_alloc(sizeof(struct avi_stream));
if (!ast)
return PARSER_ERROR;
st->priv_data = ast;
memset(st->priv_data, 0, sizeof(struct avi_stream));
}
ast->handler = handler;
aic_stream_rl32(c); /* flags */
aic_stream_rl16(c); /* priority */
aic_stream_rl16(c); /* language */
aic_stream_rl32(c); /* initial frame */
ast->scale = aic_stream_rl32(c);
ast->rate = aic_stream_rl32(c);
if (!(ast->scale && ast->rate)) {
logw("scale/rate is %" PRIu32 "/%" PRIu32 " which is invalid. "
"(This file has been generated by broken software.)\n",
ast->scale, ast->rate);
if (frame_period) {
ast->rate = 1000000;
ast->scale = frame_period;
} else {
ast->rate = 25;
ast->scale = 1;
}
}
ast->cum_len = aic_stream_rl32(c); /* start */
st->nb_frames = aic_stream_rl32(c);
aic_stream_rl32(c); /* buffer size */
aic_stream_rl32(c); /* quality */
if (ast->cum_len > 3600LL * ast->rate / ast->scale) {
loge("crazy start time, iam scared, giving up\n");
ast->cum_len = 0;
}
ast->sample_size = aic_stream_rl32(c);
ast->cum_len *= MPP_MAX(1, ast->sample_size);
switch (tag1) {
case MKTAG('v', 'i', 'd', 's'):
codec_type = MPP_MEDIA_TYPE_VIDEO;
ast->sample_size = 0;
break;
case MKTAG('a', 'u', 'd', 's'):
codec_type = MPP_MEDIA_TYPE_AUDIO;
break;
case MKTAG('t', 'x', 't', 's'):
case MKTAG('d', 'a', 't', 's'):
default:
logi("unknown stream type %X\n", tag1);
}
*type = codec_type;
st->duration = get_time(st->nb_frames, ast->rate, ast->scale);
ast->frame_offset = ast->cum_len;
aic_stream_skip(c, size - 12 * 4);
return PARSER_OK;
}
int get_strf_info(struct aic_avi_parser *s, int stream_index, unsigned int size,
int codec_type, uint64_t list_end)
{
int ret = PARSER_OK;
struct aic_stream *c = s->stream;
struct avi_context *avi = &s->avi_c;
unsigned int tag1;
unsigned int esize;
struct avi_stream_ctx *st;
struct avi_stream *ast = NULL;
st = s->streams[stream_index];
st->cur_sample_idx = 0;
ast = st->priv_data;
logi("strf: size=%d, codec_type=%d, stream_idx=%d, nb_streams=%d", size,
codec_type, stream_index, s->nb_streams);
if (!size && (codec_type == MPP_MEDIA_TYPE_AUDIO ||
codec_type == MPP_MEDIA_TYPE_VIDEO))
return PARSER_OK;
if (stream_index >= (unsigned)s->nb_streams) {
aic_stream_skip(c, size);
return PARSER_OK;
} else {
uint64_t cur_pos = aic_stream_tell(c);
if (cur_pos < list_end)
size = MPP_MIN(size, list_end - cur_pos);
}
switch (codec_type) {
case MPP_MEDIA_TYPE_VIDEO:
tag1 = get_bmp_header(c, &st->codecpar, &esize);
st->codecpar.codec_type = MPP_MEDIA_TYPE_VIDEO;
st->codecpar.codec_tag = tag1;
st->codecpar.codec_id = aic_codec_get_id(aic_codec_bmp_tags, tag1);
if (size > 10 * 4 && size < (1 << 30) && size < avi->fsize) {
if (esize == size - 1 && (esize & 1)) {
st->codecpar.extradata_size = esize - 10 * 4;
} else {
st->codecpar.extradata_size = size - 10 * 4;
}
if (st->codecpar.extradata) {
logw(
"New extradata in strf chunk, freeing previous one.\n");
}
ret = get_extradata(&st->codecpar, c,
st->codecpar.extradata_size);
if (ret < 0)
return ret;
}
ret = get_video_extradata(c, st);
if (ret < 0)
return ret;
// aic_stream_skip(c, size - 5 * 4);
break;
case MPP_MEDIA_TYPE_AUDIO:
ret = get_wav_header(c, &st->codecpar, size, 0);
if (ret < 0)
return ret;
/* 2-aligned
* (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */
if (size & 1)
aic_stream_skip(c, 1);
if (st->codecpar.codec_id == CODEC_ID_AAC &&
ast->dshow_block_align <= 4 && ast->dshow_block_align) {
logd("overriding invalid dshow_block_align of %d\n",
ast->dshow_block_align);
ast->dshow_block_align = 0;
}
if ((st->codecpar.codec_id == CODEC_ID_AAC &&
ast->dshow_block_align == 1024 && ast->sample_size == 1024) ||
(st->codecpar.codec_id == CODEC_ID_AAC &&
ast->dshow_block_align == 4096 && ast->sample_size == 4096) ||
(st->codecpar.codec_id == CODEC_ID_MP3 &&
ast->dshow_block_align == 1152 && ast->sample_size == 1152)) {
logd("overriding sample_size\n");
ast->sample_size = 0;
}
break;
default:
st->codecpar.codec_type = MPP_MEDIA_TYPE_UNKNOWN;
st->codecpar.codec_id = CODEC_ID_NONE;
st->codecpar.codec_tag = 0;
aic_stream_skip(c, size);
break;
}
return PARSER_OK;
}
int get_strd_info(struct aic_avi_parser *s, int stream_index, uint64_t list_end,
unsigned int *size)
{
int ret = PARSER_OK;
struct avi_stream_ctx *st = NULL;
struct aic_stream *c = s->stream;
if (stream_index >= (unsigned)s->nb_streams ||
s->streams[stream_index]->codecpar.extradata_size ||
s->streams[stream_index]->codecpar.codec_tag ==
MKTAG('H', '2', '6', '4')) {
aic_stream_skip(c, *size);
} else {
uint64_t cur_pos = aic_stream_tell(c);
if (cur_pos < list_end)
*size = MPP_MIN(*size, list_end - cur_pos);
st = s->streams[stream_index];
if ((*size) < (1 << 30)) {
if (st->codecpar.extradata) {
logw("New extradata in strd chunk, free previous one.\n");
}
if ((ret = get_extradata(&st->codecpar, c, *size)) < 0)
return ret;
}
//FIXME check if the encoder really did this correctly
if (st->codecpar.extradata_size & 1)
aic_stream_r8(c);
}
return PARSER_OK;
}
int avi_read_header(struct aic_avi_parser *s)
{
struct aic_stream *c = s->stream;
struct avi_context *avi = &s->avi_c;
unsigned int tag, tag1, size;
int ret, codec_type, stream_index, frame_period;
uint64_t list_end = 0;
int64_t pos;
avi->stream_index = -1;
ret = get_riff(s);
if (ret < 0)
return ret;
avi->io_fsize = avi->fsize = aic_stream_size(c);
if (avi->fsize <= 0 || avi->fsize < avi->riff_end)
avi->fsize = avi->riff_end == 8 ? INT64_MAX : avi->riff_end;
/* first list tag */
stream_index = -1;
codec_type = -1;
frame_period = 0;
for (;;) {
tag = aic_stream_rl32(c);
size = aic_stream_rl32(c);
logi("tag 0x%x, size %d\n", tag, size);
switch (tag) {
case MKTAG('L', 'I', 'S', 'T'):
list_end = aic_stream_tell(c) + size;
tag1 = aic_stream_rl32(c);
if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
avi->movi_list = aic_stream_tell(c) - 4;
if (size)
avi->movi_end = avi->movi_list + size + (size & 1);
else
avi->movi_end = avi->fsize;
goto end_of_header;
}
break;
case MKTAG('I', 'D', 'I', 'T'): {
unsigned char date[64] = { 0 };
size += (size & 1);
size -=
aic_stream_read(c, date, MPP_MIN(size, sizeof(date) - 1));
aic_stream_skip(c, size);
break;
}
case MKTAG('d', 'm', 'l', 'h'):
aic_stream_skip(c, size + (size & 1));
break;
case MKTAG('a', 'm', 'v', 'h'):
case MKTAG('a', 'v', 'i', 'h'): /* AVI header */
frame_period = get_avi_header(c, avi);
aic_stream_skip(c, size - 10 * 4);
break;
case MKTAG('s', 't', 'r', 'h'): /* stream header */
ret = get_strh_info(s, size, frame_period, &stream_index,
&codec_type);
if (ret != PARSER_OK) {
goto fail;
}
break;
case MKTAG('s', 't', 'r', 'f'): /* stream header */
ret =
get_strf_info(s, stream_index, size, codec_type, list_end);
if (ret != PARSER_OK)
return ret;
break;
case MKTAG('s', 't', 'r', 'd'):
get_strd_info(s, stream_index, list_end, &size);
break;
case MKTAG('i', 'n', 'd', 'x'):
pos = aic_stream_tell(c);
aic_stream_seek(c, pos + size, SEEK_SET);
break;
case MKTAG('v', 'p', 'r', 'p'):
aic_stream_skip(c, size);
break;
case MKTAG('s', 't', 'r', 'n'):
break;
default:
if (size > 1000000) {
loge("Something went wrong during header parsing, "
"tag 0x%x has size %u, "
"I will ignore it and try to continue anyway.\n",
tag, size);
avi->movi_list = aic_stream_tell(c) - 4;
avi->movi_end = avi->fsize;
goto end_of_header;
}
/* Do not fail for very large idx1 tags */
case MKTAG('i', 'd', 'x', '1'): /* skip tag */
size += (size & 1);
aic_stream_skip(c, size);
break;
}
}
end_of_header:
/* check stream number */
if (stream_index != s->nb_streams - 1) {
logi("stream_index:%d != nb_streams - 1:%d", stream_index,
s->nb_streams - 1);
fail:
return PARSER_ERROR;
}
if (!avi->index_loaded)
avi_load_index(s);
avi->index_loaded |= 1;
return PARSER_OK;
}
static struct avi_index_entry *avi_find_next_sample(struct aic_avi_parser *c,
struct avi_stream_ctx **st)
{
int i;
struct avi_index_entry *sample = NULL;
int64_t best_dts = INT64_MAX;
/* find the sample with the smallest dts from every streams */
for (i = 0; i < c->nb_streams; i++) {
struct avi_stream_ctx *cur_st = c->streams[i];
struct avi_stream *ast = cur_st->priv_data;
if ((cur_st->codecpar.codec_type != MPP_MEDIA_TYPE_VIDEO) &&
(cur_st->codecpar.codec_type != MPP_MEDIA_TYPE_AUDIO)) {
continue;
}
if (cur_st->cur_sample_idx < cur_st->nb_index_entries) {
struct avi_index_entry *cur_sample =
&cur_st->index_entries[cur_st->cur_sample_idx];
int64_t dts =
get_time(cur_sample->timestamp, ast->rate, ast->scale);
if (!sample || dts < best_dts) {
sample = cur_sample;
best_dts = dts;
*st = cur_st;
}
}
}
if (*st) {
(*st)->cur_sample_idx++;
}
return sample;
}
int avi_read_packet(struct aic_avi_parser *s, struct aic_parser_packet *pkt)
{
struct aic_stream *c = s->stream;
aic_stream_seek(c, s->cur_sample->pos, SEEK_SET);
aic_stream_read(c, pkt->data, s->cur_sample->size);
return PARSER_OK;
}
/* XXX: We make the implicit supposition that the positions are sorted
* for each stream. */
static int avi_read_idx1(struct aic_avi_parser *s, int size)
{
struct avi_context *avi = &s->avi_c;
struct aic_stream *c = s->stream;
int nb_index_entries, i;
struct avi_stream_ctx *st;
struct avi_stream *ast;
int64_t pos;
unsigned int index, tag, flags, len, first_packet = 1;
int64_t last_pos = -1;
unsigned last_idx = -1;
int64_t idx1_pos, first_packet_pos = 0, data_offset = 0;
int anykey = 0;
nb_index_entries = size / 16;
if (nb_index_entries <= 0)
return PARSER_ERROR;
idx1_pos = aic_stream_tell(c);
aic_stream_seek(c, avi->movi_list + 4, SEEK_SET);
avi->stream_index = -1;
aic_stream_seek(c, idx1_pos, SEEK_SET);
logi("size %d, nb_index_entries %d\n", size, nb_index_entries);
/* Read the entries and sort them in each stream component. */
for (i = 0; i < nb_index_entries; i++) {
tag = aic_stream_rl32(c); //chunk id
flags = aic_stream_rl32(c); //keyframe
pos = aic_stream_rl32(c); //data offset in file
len = aic_stream_rl32(c); //data size
index = ((tag & 0xff) - '0') * 10;
index += (tag >> 8 & 0xff) - '0';
if (index >= s->nb_streams)
continue;
st = s->streams[index];
ast = st->priv_data;
/* Skip 'xxpc' palette change entries in the index until a logic
* to process these is properly implemented. */
if ((tag >> 16 & 0xff) == 'p' && (tag >> 24 & 0xff) == 'c')
continue;
if (first_packet && first_packet_pos) {
if (avi->movi_list + 4 != pos || pos + 500 > first_packet_pos)
data_offset = first_packet_pos - pos;
first_packet = 0;
}
pos += data_offset;
logd(
"stream(%d) len=%d cum_len=%d, sample_size=%d, dshow_block_align=%d\n",
index, len, (int)ast->cum_len, ast->sample_size,
ast->dshow_block_align);
/* even if we have only a single stream, we should
* switch to non-interleaved to get correct timestamps */
if (last_pos == pos)
avi->non_interleaved = 1;
if (!st->alloc_entries_flag) {
struct avi_index_entry *index_entries =
mpp_alloc(st->nb_frames * sizeof(struct avi_index_entry));
if (!index_entries) {
loge("no mem for stream %d index_entries \n", index);
return PARSER_NOMEM;
}
st->index_entries = index_entries;
st->alloc_entries_flag = 1;
st->nb_index_entries = 0;
ast->cum_len = 0;
}
if (last_idx != pos && len && st->alloc_entries_flag) {
st->index_entries[st->nb_index_entries].pos =
avi->movi_list + pos + 8;
st->index_entries[st->nb_index_entries].timestamp = ast->cum_len;
st->index_entries[st->nb_index_entries].min_distance = 0;
st->index_entries[st->nb_index_entries].size = len;
st->index_entries[st->nb_index_entries].flags =
(flags & AVIIF_INDEX) ? 1 : 0;
last_idx = pos;
st->nb_index_entries++;
}
ast->cum_len += get_duration(ast, len);
last_pos = pos;
anykey |= flags & AVIIF_INDEX;
}
if (!anykey) {
for (index = 0; index < s->nb_streams; index++) {
st = s->streams[index];
if (st->nb_index_entries)
st->index_entries[0].flags |= 1;
}
}
return PARSER_OK;
}
static int avi_load_index(struct aic_avi_parser *s)
{
struct avi_context *avi = &s->avi_c;
struct aic_stream *c = s->stream;
uint32_t tag, size;
int64_t pos = aic_stream_tell(c);
int64_t next;
int ret = PARSER_ERROR;
if (aic_stream_seek(c, avi->movi_end, SEEK_SET) < 0)
goto the_end; // maybe truncated file
logd("movi_end=0x%" PRIx64 "\n", avi->movi_end);
for (;;) {
tag = aic_stream_rl32(c);
size = aic_stream_rl32(c);
next = aic_stream_tell(c) + size + (size & 1);
if (tag == MKTAG('i', 'd', 'x', '1') && avi_read_idx1(s, size) >= 0) {
avi->index_loaded = 2;
ret = 0;
} else if (tag == MKTAG('L', 'I', 'S', 'T')) {
aic_stream_rl32(c);
} else if (!ret) {
break;
}
if (aic_stream_seek(c, next, SEEK_SET) < 0)
break; // something is wrong here
}
the_end:
aic_stream_seek(c, pos, SEEK_SET);
return ret;
}
int avi_read_close(struct aic_avi_parser *s)
{
int i;
for (i = 0; i < s->nb_streams; i++) {
struct avi_stream_ctx *st = s->streams[i];
if (!st) {
continue;
}
if (st->codecpar.extradata) {
mpp_free(st->codecpar.extradata);
}
struct avi_stream *ast = st->priv_data;
if (ast) {
mpp_free(ast);
}
if (st->index_entries) {
mpp_free(st->index_entries);
}
mpp_free(st);
}
return PARSER_OK;
}
int avi_peek_packet(struct aic_avi_parser *s, struct aic_parser_packet *pkt)
{
struct avi_stream_ctx *st = NULL;
struct avi_index_entry *sample = NULL;
static struct avi_stream *ast = NULL;
sample = avi_find_next_sample(s, &st);
if (!sample) {
// eos
return PARSER_EOS;
}
s->cur_sample = sample;
pkt->size = sample->size;
pkt->type = st->codecpar.codec_type;
pkt->flag = 0;
ast = st->priv_data;
if (ast) {
pkt->pts = get_time(sample->timestamp, ast->rate, ast->scale);
}
if (st->cur_sample_idx == st->nb_index_entries) {
// eos now
logw("[%s:%d] this stream eos\n", __FUNCTION__, __LINE__);
pkt->flag = PACKET_EOS;
}
// logd("peek packet(%d), size %d, type %d, pos=0x%"PRIx64", timestamp=%d, pts=%d\n",
// st->cur_sample_idx, pkt->size, pkt->type, sample->pos, (int)sample->timestamp, (int)pkt->pts);
return PARSER_OK;
}
int avi_seek_packet(struct aic_avi_parser *s, s64 pts)
{
int i;
struct avi_stream_ctx *cur_st = NULL;
struct avi_stream_ctx *video_st = NULL;
struct avi_stream_ctx *audio_st = NULL;
struct avi_index_entry *cur_sample = NULL;
static struct avi_stream *video_ast = NULL;
for (i = 0; i < s->nb_streams; i++) {
cur_st = s->streams[i];
if ((!video_st) &&
(cur_st->codecpar.codec_type ==
MPP_MEDIA_TYPE_VIDEO)) { // only support first video stream
video_st = s->streams[i];
video_ast = video_st->priv_data;
} else if ((!audio_st) &&
(cur_st->codecpar.codec_type ==
MPP_MEDIA_TYPE_AUDIO)) { // only support first audio stream
audio_st = s->streams[i];
}
}
if (video_st) {
video_st->cur_sample_idx = find_video_index_by_pts(video_st, pts);
if (video_st->cur_sample_idx < 0) {
loge("no keyframes\n");
return PARSER_ERROR;
}
}
if (audio_st) {
int64_t tmp;
tmp = pts;
if (video_st) {
cur_sample = &video_st->index_entries[video_st->cur_sample_idx];
tmp = get_time(cur_sample->timestamp, video_ast->rate,
video_ast->scale);
}
audio_st->cur_sample_idx = find_index_by_pts(audio_st, tmp);
}
return PARSER_OK;
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2020-2024 Artinchip Technology Co. Ltd
*
* author: <che.jiang@artinchip.com>
* Desc: avi.h
*/
#ifndef __AVI_H__
#define __AVI_H__
#include <unistd.h>
#include "aic_parser.h"
#include "aic_tag.h"
#define AVIF_HASINDEX 0x00000010 // Index at end of file?
#define AVIF_MUSTUSEINDEX 0x00000020
#define AVIF_ISINTERLEAVED 0x00000100
#define AVIF_TRUSTCKTYPE 0x00000800 // Use CKType to find key frames?
#define AVIF_WASCAPTUREFILE 0x00010000
#define AVIF_COPYRIGHTED 0x00020000
#define AVI_MAX_RIFF_SIZE 0x40000000LL
/* stream header flags */
#define AVISF_VIDEO_PALCHANGES 0x00010000
/* index flags */
#define AVIIF_INDEX 0x00000010
#define AVIIF_NO_TIME 0x00000100
#define AV_INPUT_BUFFER_PADDING_SIZE 64
struct avi_index_entry {
int64_t pos;
int64_t timestamp; // dts
int size;
int min_distance;
int flags;
};
struct avi_stream {
/* current frame (video) or byte (audio) counter * (used to compute the pts) */
int64_t frame_offset;
uint32_t handler;
uint32_t scale;
uint32_t rate;
/* size of one sample (or packet) * (in the rate/scale sense) in bytes */
int sample_size;
int64_t cum_len; /* temporary storage (used during seek) */
/* block align variable used to emulate bugs in * the MS dshow demuxer */
int dshow_block_align;
};
struct avi_stream_ctx {
void *priv_data;
int index;
int64_t nb_frames;
int64_t duration;
int cur_sample_idx;
struct aic_codec_param codecpar;
int nb_index_entries;
int alloc_entries_flag;
struct avi_index_entry *index_entries;
};
struct avi_context {
int64_t riff_end;
int64_t movi_end;
int64_t fsize;
int64_t io_fsize;
int64_t movi_list;
int64_t last_pkt_pos;
int index_loaded;
int is_odml;
int non_interleaved;
int stream_index;
int odml_depth;
int use_odml;
#define MAX_ODML_DEPTH 1000
int64_t dts_max;
};
#define AVI_MAX_TRACK_NUM 8
struct aic_avi_parser {
struct aic_parser base;
struct aic_stream *stream;
struct avi_context avi_c;
int nb_streams;
struct avi_stream_ctx *streams[AVI_MAX_TRACK_NUM];
struct avi_index_entry *cur_sample;
};
int avi_read_header(struct aic_avi_parser *s);
int avi_read_close(struct aic_avi_parser *s);
int avi_peek_packet(struct aic_avi_parser *c, struct aic_parser_packet *pkt);
int avi_seek_packet(struct aic_avi_parser *c, s64 pts);
int avi_read_packet(struct aic_avi_parser *s, struct aic_parser_packet *pkt);
#endif /* __AVIDEC_H__ */

View File

@@ -13,9 +13,7 @@
#include "mpp_mem.h"
#include "mpp_log.h"
#define TIME_BASE 1000000LL
#define MPP_MAX(a, b) ((a)>(b)? (a) : (b))
#define MPP_MIN(a, b) ((a)<(b)? (a) : (b))
/* those functions parse an atom */
@@ -27,65 +25,6 @@ struct mov_parse_table {
static int mov_read_default(struct aic_mov_parser *c, struct mov_atom atom);
static int stream_skip(struct aic_stream* s, int len)
{
return aic_stream_seek(s, len, SEEK_CUR);
}
static unsigned int r8(struct aic_stream* s)
{
unsigned char val;
aic_stream_read(s, &val, 1);
return val;
}
static unsigned int rb16(struct aic_stream* s)
{
unsigned int val;
val = r8(s) << 8;
val |= r8(s);
return val;
}
static unsigned int rb24(struct aic_stream* s)
{
unsigned int val;
val = rb16(s) << 16;
val |= r8(s);
return val;
}
static unsigned int rb32(struct aic_stream* s)
{
unsigned int val;
val = rb16(s) << 16;
val |= rb16(s);
return val;
}
static uint64_t rb64(struct aic_stream* s)
{
uint64_t val;
val = (uint64_t)rb32(s) << 32;
val |= (uint64_t)rb32(s);
return val;
}
static unsigned int rl16(struct aic_stream* s)
{
unsigned int val;
val = r8(s);
val |= r8(s) << 8;
return val;
}
static unsigned int rl32(struct aic_stream* s)
{
unsigned int val;
val = rl16(s);
val |= rl16(s) << 16;
return val;
}
static int64_t get_time(int64_t pts, int64_t st_time_scale)
{
@@ -98,7 +37,7 @@ static int mov_read_moov(struct aic_mov_parser *c, struct mov_atom atom)
if (c->find_moov) {
loge("find duplicated moov atom. skipped it");
stream_skip(c->stream, atom.size);
aic_stream_skip(c->stream, atom.size);
return 0;
}
@@ -112,44 +51,44 @@ static int mov_read_mvhd(struct aic_mov_parser *c, struct mov_atom atom)
{
int i;
//int64_t createion_time;
int version = r8(c->stream);
rb24(c->stream);
int version = aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
if (version == 1) {
rb64(c->stream); // create time
rb64(c->stream); // modify time
aic_stream_rb64(c->stream); // create time
aic_stream_rb64(c->stream); // modify time
} else {
rb32(c->stream); // create time
rb32(c->stream); // modify time
aic_stream_rb32(c->stream); // create time
aic_stream_rb32(c->stream); // modify time
}
c->time_scale = rb32(c->stream);
c->time_scale = aic_stream_rb32(c->stream);
if (c->time_scale <= 0) {
loge("Invalid mvhd time scale %d, default to 1", c->time_scale);
c->time_scale = 1;
}
c->duration = (version == 1) ? rb64(c->stream) : rb32(c->stream);
c->duration = (version == 1) ? aic_stream_rb64(c->stream) : aic_stream_rb32(c->stream);
rb32(c->stream); // preferred scale
rb16(c->stream); /* preferred volume */
aic_stream_rb32(c->stream); // preferred scale
aic_stream_rb16(c->stream); /* preferred volume */
stream_skip(c->stream, 10); /* reserved */
aic_stream_skip(c->stream, 10); /* reserved */
/* movie display matrix, store it in main context and use it later on */
for (i=0; i<3; i++) {
c->movie_display_matrix[i][0] = rb32(c->stream); // 16.16 fixed point
c->movie_display_matrix[i][1] = rb32(c->stream); // 16.16 fixed point
c->movie_display_matrix[i][2] = rb32(c->stream); // 2.30 fixed point
c->movie_display_matrix[i][0] = aic_stream_rb32(c->stream); // 16.16 fixed point
c->movie_display_matrix[i][1] = aic_stream_rb32(c->stream); // 16.16 fixed point
c->movie_display_matrix[i][2] = aic_stream_rb32(c->stream); // 2.30 fixed point
}
rb32(c->stream); /* preview time */
rb32(c->stream); /* preview duration */
rb32(c->stream); /* poster time */
rb32(c->stream); /* selection time */
rb32(c->stream); /* selection duration */
rb32(c->stream); /* current time */
rb32(c->stream); /* next track ID */
aic_stream_rb32(c->stream); /* preview time */
aic_stream_rb32(c->stream); /* preview duration */
aic_stream_rb32(c->stream); /* poster time */
aic_stream_rb32(c->stream); /* selection time */
aic_stream_rb32(c->stream); /* selection duration */
aic_stream_rb32(c->stream); /* current time */
aic_stream_rb32(c->stream); /* next track ID */
return 0;
}
@@ -403,10 +342,10 @@ static void mov_build_index(struct aic_mov_parser *c, struct mov_stream_ctx *st)
static int mov_codec_id(struct mov_stream_ctx *st, uint32_t format)
{
int id = codec_get_id(mov_audio_tags, format);
int id = aic_codec_get_id(mov_audio_tags, format);
if (st->type == MPP_MEDIA_TYPE_VIDEO)
id = codec_get_id(mov_video_tags, format);
id = aic_codec_get_id(mov_video_tags, format);
return id;
}
@@ -445,29 +384,29 @@ static int mov_read_tkhd(struct aic_mov_parser *c, struct mov_atom atom)
return 0;
st = c->streams[c->nb_streams - 1];
version = r8(c->stream);
rb24(c->stream);
version = aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
if (version == 1) {
rb64(c->stream);
rb64(c->stream);
aic_stream_rb64(c->stream);
aic_stream_rb64(c->stream);
} else {
rb32(c->stream);
rb32(c->stream);
aic_stream_rb32(c->stream);
aic_stream_rb32(c->stream);
}
st->id = rb32(c->stream);
rb32(c->stream); /* reserved */
st->id = aic_stream_rb32(c->stream);
aic_stream_rb32(c->stream); /* reserved */
/* highlevel (considering edits) duration in movie timebase */
(version == 1) ? rb64(c->stream) : rb32(c->stream);
rb32(c->stream); /* reserved */
rb32(c->stream); /* reserved */
(version == 1) ? aic_stream_rb64(c->stream) : aic_stream_rb32(c->stream);
aic_stream_rb32(c->stream); /* reserved */
aic_stream_rb32(c->stream); /* reserved */
rb16(c->stream); /* layer */
rb16(c->stream); /* alternate group */
rb16(c->stream); /* volume */
rb16(c->stream); /* reserved */
aic_stream_rb16(c->stream); /* layer */
aic_stream_rb16(c->stream); /* alternate group */
aic_stream_rb16(c->stream); /* volume */
aic_stream_rb16(c->stream); /* reserved */
// read in the display matrix (outlined in ISO 14496-12, Section 6.2.2)
// they're kept in fixed point format through all calculations
@@ -475,14 +414,14 @@ static int mov_read_tkhd(struct aic_mov_parser *c, struct mov_atom atom)
// side data, but the scale factor is not needed to calculate aspect ratio
for (i = 0; i < 3; i++) {
rb32(c->stream); // 16.16 fixed point
rb32(c->stream); // 16.16 fixed point
rb32(c->stream); // 2.30 fixed point
aic_stream_rb32(c->stream); // 16.16 fixed point
aic_stream_rb32(c->stream); // 16.16 fixed point
aic_stream_rb32(c->stream); // 2.30 fixed point
}
width = rb32(c->stream); // 16.16 fixed point track width
height = rb32(c->stream); // 16.16 fixed point track height
width = aic_stream_rb32(c->stream); // 16.16 fixed point track width
height = aic_stream_rb32(c->stream); // 16.16 fixed point track height
st->width = width >> 16;
st->height = height >> 16;
@@ -496,11 +435,11 @@ static int mov_read_hdlr(struct aic_mov_parser *c, struct mov_atom atom)
int64_t title_size;
struct mov_stream_ctx *st;
r8(c->stream);
rb24(c->stream);
aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
rl32(c->stream);
type = rl32(c->stream);
aic_stream_rl32(c->stream);
type = aic_stream_rl32(c->stream);
st = c->streams[c->nb_streams-1];
@@ -509,9 +448,9 @@ static int mov_read_hdlr(struct aic_mov_parser *c, struct mov_atom atom)
else if (type == MKTAG('s','o','u','n'))
st->type = MPP_MEDIA_TYPE_AUDIO;
rb32(c->stream); /* component manufacture */
rb32(c->stream); /* component flags */
rb32(c->stream); /* component flags mask */
aic_stream_rb32(c->stream); /* component manufacture */
aic_stream_rb32(c->stream); /* component flags */
aic_stream_rb32(c->stream); /* component flags mask */
title_size = atom.size - 24;
if (title_size > 0) {
@@ -527,27 +466,27 @@ static int mov_read_stsd_video(struct aic_mov_parser *c, struct mov_stream_ctx *
//uint32_t tmp, bit_depth, grayscale, color_table_id;
uint32_t tmp, bit_depth;
rb16(c->stream); /* version */
rb16(c->stream); /* revision level */
rl32(c->stream);
rb32(c->stream); /* temporal quality */
rb32(c->stream); /* spatial quality */
aic_stream_rb16(c->stream); /* version */
aic_stream_rb16(c->stream); /* revision level */
aic_stream_rl32(c->stream);
aic_stream_rb32(c->stream); /* temporal quality */
aic_stream_rb32(c->stream); /* spatial quality */
st->width = rb16(c->stream);
st->height = rb16(c->stream);
st->width = aic_stream_rb16(c->stream);
st->height = aic_stream_rb16(c->stream);
rb32(c->stream); /* horiz resolution */
rb32(c->stream); /* vert resolution */
rb32(c->stream); /* data size, always 0 */
rb16(c->stream); /* frames per samples */
aic_stream_rb32(c->stream); /* horiz resolution */
aic_stream_rb32(c->stream); /* vert resolution */
aic_stream_rb32(c->stream); /* data size, always 0 */
aic_stream_rb16(c->stream); /* frames per samples */
stream_skip(c->stream, 32); /* compress name*/
aic_stream_skip(c->stream, 32); /* compress name*/
tmp = rb16(c->stream); /* bit depth */
tmp = aic_stream_rb16(c->stream); /* bit depth */
bit_depth = tmp & 0x1f;
//grayscale = tmp & 0x20;
rb16(c->stream);
aic_stream_rb16(c->stream);
if ((bit_depth == 1 || bit_depth == 2 || bit_depth == 4 || bit_depth == 8)) {
logw("video is pallet");
}
@@ -557,42 +496,42 @@ static int mov_read_stsd_video(struct aic_mov_parser *c, struct mov_stream_ctx *
static int mov_read_stsd_audio(struct aic_mov_parser *c, struct mov_stream_ctx *st)
{
uint16_t version = rb16(c->stream);
uint16_t version = aic_stream_rb16(c->stream);
rb16(c->stream); /* revision level */
rl32(c->stream); /* vendor */
aic_stream_rb16(c->stream); /* revision level */
aic_stream_rl32(c->stream); /* vendor */
st->channels = rb16(c->stream);
st->bits_per_sample = rb16(c->stream);
st->channels = aic_stream_rb16(c->stream);
st->bits_per_sample = aic_stream_rb16(c->stream);
rb16(c->stream); /* compress id */
rb16(c->stream); /* packet size = 0 */
aic_stream_rb16(c->stream); /* compress id */
aic_stream_rb16(c->stream); /* packet size = 0 */
st->sample_rate = (rb32(c->stream) >> 16);
st->sample_rate = (aic_stream_rb32(c->stream) >> 16);
if (!c->isom) {
if (version == 1) {
rb32(c->stream); /* bytes per packet */
st->samples_per_frame = rb32(c->stream); /* sample per frame */
st->bytes_per_frame = rb32(c->stream); /* bytes per frame */
rb32(c->stream); /* bytes per sample */
aic_stream_rb32(c->stream); /* bytes per packet */
st->samples_per_frame = aic_stream_rb32(c->stream); /* sample per frame */
st->bytes_per_frame = aic_stream_rb32(c->stream); /* bytes per frame */
aic_stream_rb32(c->stream); /* bytes per sample */
} else if (version == 2) {
rb32(c->stream); /* sizeof struct only */
aic_stream_rb32(c->stream); /* sizeof struct only */
union int_float64{
long long i;
double f;
};
union int_float64 v;
v.i = rb64(c->stream);
v.i = aic_stream_rb64(c->stream);
st->sample_rate = v.f;
st->channels = rb32(c->stream);
rb32(c->stream);
st->bits_per_sample = rb32(c->stream);
st->channels = aic_stream_rb32(c->stream);
aic_stream_rb32(c->stream);
st->bits_per_sample = aic_stream_rb32(c->stream);
rb32(c->stream); /* lpcm format specific flag */
st->bytes_per_frame = rb32(c->stream);
st->samples_per_frame = rb32(c->stream);
aic_stream_rb32(c->stream); /* lpcm format specific flag */
st->bytes_per_frame = aic_stream_rb32(c->stream);
st->samples_per_frame = aic_stream_rb32(c->stream);
}
}
@@ -618,13 +557,13 @@ static int mov_read_stsd_entries(struct aic_mov_parser *c, int entries)
//int ret, dref_id = 1;
int ret;
int64_t start_pos = aic_stream_tell(c->stream);
int64_t size = rb32(c->stream);
uint32_t format = rl32(c->stream);
int64_t size = aic_stream_rb32(c->stream);
uint32_t format = aic_stream_rl32(c->stream);
if (size >= 16) {
rb32(c->stream);
rb16(c->stream);
rb16(c->stream);
aic_stream_rb32(c->stream);
aic_stream_rb16(c->stream);
aic_stream_rb16(c->stream);
} else if (size <= 7) {
loge("invalid size %"PRId64" in stsd", size);
return -1;
@@ -645,7 +584,7 @@ static int mov_read_stsd_entries(struct aic_mov_parser *c, int entries)
if ((ret = mov_read_default(c, a)) < 0)
return ret;
} else if (a.size > 0) {
stream_skip(c->stream, a.size);
aic_stream_skip(c->stream, a.size);
}
st->stsd_count ++;
@@ -663,9 +602,9 @@ static int mov_read_stsd(struct aic_mov_parser *c, struct mov_atom atom)
return 0;
st = c->streams[c->nb_streams-1];
st->stsd_version = r8(c->stream);
rb24(c->stream);
entries = rb32(c->stream);
st->stsd_version = aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
entries = aic_stream_rb32(c->stream);
/* Each entry contains a size (4 bytes) and format (4 bytes). */
if (entries <= 0 || entries > atom.size / 8 || entries > 1024) {
@@ -696,9 +635,9 @@ static int mov_read_stts(struct aic_mov_parser *c, struct mov_atom atom)
if (c->nb_streams < 1)
return 0;
r8(c->stream); /* version */
rb24(c->stream); /* flags */
entries = rb32(c->stream);
aic_stream_r8(c->stream); /* version */
aic_stream_rb24(c->stream); /* flags */
entries = aic_stream_rb32(c->stream);
if (st->stts_data) {
logw("duplicated stts data");
@@ -713,8 +652,8 @@ static int mov_read_stts(struct aic_mov_parser *c, struct mov_atom atom)
int sample_duration;
unsigned int sample_count;
sample_count = rb32(c->stream);
sample_duration = rb32(c->stream);
sample_count = aic_stream_rb32(c->stream);
sample_duration = aic_stream_rb32(c->stream);
st->stts_data[i].count = sample_count;
st->stts_data[i].duration = sample_duration;
@@ -738,9 +677,9 @@ static int mov_read_stsc(struct aic_mov_parser *c, struct mov_atom atom)
struct mov_stream_ctx *st = c->streams[c->nb_streams-1];
r8(c->stream);
rb24(c->stream);
entries = rb32(c->stream);
aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
entries = aic_stream_rb32(c->stream);
if (entries*12+4 > atom.size) {
loge("stsc size error");
@@ -762,9 +701,9 @@ static int mov_read_stsc(struct aic_mov_parser *c, struct mov_atom atom)
return -1;
for (i=0; i<entries; i++) {
st->stsc_data[i].first = rb32(c->stream);
st->stsc_data[i].count = rb32(c->stream);
st->stsc_data[i].id = rb32(c->stream);
st->stsc_data[i].first = aic_stream_rb32(c->stream);
st->stsc_data[i].count = aic_stream_rb32(c->stream);
st->stsc_data[i].id = aic_stream_rb32(c->stream);
}
// check stsc data valid
@@ -812,22 +751,22 @@ static int mov_read_stsz(struct aic_mov_parser *c, struct mov_atom atom)
struct mov_stream_ctx *st = c->streams[c->nb_streams-1];
r8(c->stream);
rb24(c->stream);
aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
if (atom.type == MKTAG('s','t','s','z')) {
sample_size = rb32(c->stream);
sample_size = aic_stream_rb32(c->stream);
if (!st->sample_size) /* do not overwrite value computed in stsd */
st->sample_size = sample_size;
st->stsz_sample_size = sample_size;
//field_size = 32;
} else {
sample_size = 0;
rb24(c->stream);
r8(c->stream); //field_size
aic_stream_rb24(c->stream);
aic_stream_r8(c->stream); //field_size
}
entries = rb32(c->stream);
entries = aic_stream_rb32(c->stream);
if (!entries)
return 0;
@@ -848,7 +787,7 @@ static int mov_read_stsz(struct aic_mov_parser *c, struct mov_atom atom)
return -1;
for (i=0; i<entries; i++) {
st->sample_sizes[i] = rb32(c->stream);
st->sample_sizes[i] = aic_stream_rb32(c->stream);
if (st->sample_sizes[i] < 0) {
loge("invalid sample size: %d", st->sample_sizes[i]);
return -1;
@@ -868,9 +807,9 @@ static int mov_read_stco(struct aic_mov_parser *c, struct mov_atom atom)
struct mov_stream_ctx *st = c->streams[c->nb_streams-1];
r8(c->stream);
rb24(c->stream);
entries = rb32(c->stream);
aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
entries = aic_stream_rb32(c->stream);
if (!entries) {
logw("stco entries is 0");
@@ -889,11 +828,11 @@ static int mov_read_stco(struct aic_mov_parser *c, struct mov_atom atom)
if (atom.type == MKTAG('s','t','c','o')) {
for (i=0; i<entries; i++) {
st->chunk_offsets[i] = rb32(c->stream);
st->chunk_offsets[i] = aic_stream_rb32(c->stream);
}
} else if (atom.type == MKTAG('c','o','6','4')) {
for (i=0; i<entries; i++) {
st->chunk_offsets[i] = rb64(c->stream);
st->chunk_offsets[i] = aic_stream_rb64(c->stream);
}
} else {
return -1;
@@ -922,9 +861,9 @@ static int mov_read_ctts(struct aic_mov_parser *c, struct mov_atom atom)
struct mov_stream_ctx *st = c->streams[c->nb_streams-1];
r8(c->stream);
rb24(c->stream);
entries = rb32(c->stream);
aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
entries = aic_stream_rb32(c->stream);
if (!entries) {
logw("ctts entries is 0");
@@ -943,8 +882,8 @@ static int mov_read_ctts(struct aic_mov_parser *c, struct mov_atom atom)
return -1;
for (i=0; i<entries; i++) {
int count = rb32(c->stream);
int duration = rb32(c->stream);
int count = aic_stream_rb32(c->stream);
int duration = aic_stream_rb32(c->stream);
total_count += count;
@@ -995,9 +934,9 @@ static int mov_read_stss(struct aic_mov_parser *c, struct mov_atom atom)
struct mov_stream_ctx *st = c->streams[c->nb_streams-1];
r8(c->stream);
rb24(c->stream);
entries = rb32(c->stream);
aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
entries = aic_stream_rb32(c->stream);
if (!entries) {
logw("stts entries is 0");
@@ -1014,7 +953,7 @@ static int mov_read_stss(struct aic_mov_parser *c, struct mov_atom atom)
st->keyframes = mpp_alloc(entries*sizeof(*st->keyframes));
for (i=0; i<entries; i++) {
st->keyframes[i] = rb32(c->stream);
st->keyframes[i] = aic_stream_rb32(c->stream);
}
return 0;
@@ -1033,25 +972,25 @@ static int mov_read_mdhd(struct aic_mov_parser *c, struct mov_atom atom)
return -1;
}
version = r8(c->stream);
rb24(c->stream);
version = aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
if (version > 1) {
rb64(c->stream);
rb64(c->stream);
aic_stream_rb64(c->stream);
aic_stream_rb64(c->stream);
} else {
rb32(c->stream);
rb32(c->stream);
aic_stream_rb32(c->stream);
aic_stream_rb32(c->stream);
}
st->time_scale = rb32(c->stream);
st->time_scale = aic_stream_rb32(c->stream);
if (st->time_scale <= 0) {
st->time_scale = c->time_scale;
}
st->duration = (version == 1) ? rb64(c->stream) : rb32(c->stream);
st->duration = (version == 1) ? aic_stream_rb64(c->stream) : aic_stream_rb32(c->stream);
rb16(c->stream);
rb16(c->stream);
aic_stream_rb16(c->stream);
aic_stream_rb16(c->stream);
return 0;
}
@@ -1088,7 +1027,7 @@ static int mov_read_ftyp(struct aic_mov_parser *c, struct mov_atom atom)
if (strcmp((char*)type, "qt "))
c->isom = 1;
rb32(c->stream); // minor version
aic_stream_rb32(c->stream); // minor version
return 0;
}
@@ -1104,11 +1043,11 @@ static int mov_read_mdat(struct aic_mov_parser *c, struct mov_atom atom)
static int mp4_read_desc(struct aic_stream *s, int *tag)
{
int len = 0;
*tag = r8(s);
*tag = aic_stream_r8(s);
int count = 4;
while (count--) {
int c = r8(s);
int c = aic_stream_r8(s);
len = (len << 7) | (c & 0x7f);
if (!(c & 0x80))
break;
@@ -1124,13 +1063,13 @@ static int mp4_read_dec_config_descr(struct aic_mov_parser *c, struct mov_stream
enum CodecID codec_id;
int len, tag;
int object_type_id = r8(c->stream);
r8(c->stream);
rb24(c->stream);
rb32(c->stream);
rb32(c->stream); // avg bitrate
int object_type_id = aic_stream_r8(c->stream);
aic_stream_r8(c->stream);
aic_stream_rb24(c->stream);
aic_stream_rb32(c->stream);
aic_stream_rb32(c->stream); // avg bitrate
codec_id = codec_get_id(mp4_obj_type, object_type_id);
codec_id = aic_codec_get_id(mp4_obj_type, object_type_id);
if (codec_id)
st->id = codec_id;
@@ -1160,13 +1099,13 @@ static int mov_read_esds(struct aic_mov_parser *c, struct mov_atom atom)
if (c->nb_streams < 1)
return 0;
st = c->streams[c->nb_streams-1];
rb32(c->stream);
aic_stream_rb32(c->stream);
mp4_read_desc(c->stream, &tag);
if (tag == MP4ESDescrTag) {
rb24(c->stream);
aic_stream_rb24(c->stream);
} else {
rb16(c->stream);
aic_stream_rb16(c->stream);
}
mp4_read_desc(c->stream, &tag);
@@ -1231,13 +1170,13 @@ static int mov_read_default(struct aic_mov_parser *c, struct mov_atom atom)
a.size = atom.size;
a.type = 0;
if (atom.size >= 8) {
a.size = rb32(c->stream);
a.type = rl32(c->stream);
a.size = aic_stream_rb32(c->stream);
a.type = aic_stream_rl32(c->stream);
total_size += 8;
if (a.size == 1 && total_size + 8 <= atom.size) {
// 64 bit extended size
a.size = rb64(c->stream) - 8;
a.size = aic_stream_rb64(c->stream) - 8;
total_size += 8;
}
}
@@ -1267,7 +1206,7 @@ static int mov_read_default(struct aic_mov_parser *c, struct mov_atom atom)
}
if (!parse) {
stream_skip(c->stream, a.size);
aic_stream_skip(c->stream, a.size);
} else {
int64_t start_pos = aic_stream_tell(c->stream);
int64_t left;
@@ -1285,7 +1224,7 @@ static int mov_read_default(struct aic_mov_parser *c, struct mov_atom atom)
left = a.size - aic_stream_tell(c->stream) + start_pos;
if (left > 0) {
/* skip garbage at atom end */
stream_skip(c->stream, left);
aic_stream_skip(c->stream, left);
} else if (left < 0) {
loge("overread end of atom %"PRIx32"", a.type);
aic_stream_seek(c->stream, left, SEEK_CUR);
@@ -1296,7 +1235,7 @@ static int mov_read_default(struct aic_mov_parser *c, struct mov_atom atom)
}
if (total_size < atom.size && atom.size < 0x7ffff)
stream_skip(c->stream, atom.size - total_size);
aic_stream_skip(c->stream, atom.size - total_size);
c->atom_depth --;
return 0;

View File

@@ -22,7 +22,7 @@ const struct codec_tag mov_audio_tags[] = {
{ CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') },
{ CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') },
{ CODEC_ID_MP3, MKTAG('m', 'p', '3', ' ') }, /* vlc */
{ CODEC_ID_MP3, 0x6D730055 },
{ CODEC_ID_MP3, 0x6D730055 },
{ CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') },
{ CODEC_ID_PCM_F32BE, MKTAG('f', 'l', '3', '2') },
{ CODEC_ID_PCM_F32LE, MKTAG('f', 'l', '3', '2') },
@@ -77,13 +77,3 @@ const struct codec_tag mov_video_tags[] = {
{ CODEC_ID_NONE, 0 },
};
enum CodecID codec_get_id(const struct codec_tag *tags, unsigned int tag)
{
int i;
for (i=0; tags[i].id != CODEC_ID_NONE; i++) {
if (tag == tags[i].tag)
return tags[i].id;
}
return CODEC_ID_NONE;
}

View File

@@ -8,67 +8,11 @@
#ifndef __MOV_TAGS__
#define __MOV_TAGS__
#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))
enum CodecID {
CODEC_ID_NONE,
/* video codecs */
CODEC_ID_MJPEG,
CODEC_ID_H264,
/* various PCM "codecs" */
CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
CODEC_ID_PCM_S16LE = 0x10000,
CODEC_ID_PCM_S16BE,
CODEC_ID_PCM_U16LE,
CODEC_ID_PCM_U16BE,
CODEC_ID_PCM_S8,
CODEC_ID_PCM_U8,
CODEC_ID_PCM_MULAW,
CODEC_ID_PCM_ALAW,
CODEC_ID_PCM_S32LE,
CODEC_ID_PCM_S32BE,
CODEC_ID_PCM_U32LE,
CODEC_ID_PCM_U32BE,
CODEC_ID_PCM_S24LE,
CODEC_ID_PCM_S24BE,
CODEC_ID_PCM_U24LE,
CODEC_ID_PCM_U24BE,
CODEC_ID_PCM_S24DAUD,
CODEC_ID_PCM_ZORK,
CODEC_ID_PCM_S16LE_PLANAR,
CODEC_ID_PCM_DVD,
CODEC_ID_PCM_F32BE,
CODEC_ID_PCM_F32LE,
CODEC_ID_PCM_F64BE,
CODEC_ID_PCM_F64LE,
CODEC_ID_PCM_BLURAY,
CODEC_ID_PCM_LXF,
CODEC_ID_PCM_S8_PLANAR,
CODEC_ID_PCM_S24LE_PLANAR,
CODEC_ID_PCM_S32LE_PLANAR,
CODEC_ID_PCM_S16BE_PLANAR,
CODEC_ID_PCM_S64LE,
CODEC_ID_PCM_S64BE,
CODEC_ID_PCM_F16LE,
CODEC_ID_PCM_F24LE,
CODEC_ID_PCM_VIDC,
CODEC_ID_PCM_SGA,
CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3
CODEC_ID_AAC,
};
struct codec_tag {
enum CodecID id;
unsigned int tag;
};
#include "aic_tag.h"
extern const struct codec_tag mov_audio_tags[];
extern const struct codec_tag mov_video_tags[];
extern const struct codec_tag mp4_obj_type[];
enum CodecID codec_get_id(const struct codec_tag *tags, unsigned int tag);
#endif

View File

@@ -37,12 +37,20 @@ int wav_read_header(struct aic_wav_parser *s)
ret = -1;
goto _exit;
}
r_len = aic_stream_read(s->stream, &(s->wav_info.data_block), sizeof(struct wave_data));
if (r_len != sizeof(struct wave_data)) {
loge("read wave_data fail");
ret = -1;
goto _exit;
}
do {
int len = 0;
len = aic_stream_read(s->stream, &(s->wav_info.data_block), sizeof(struct wave_data));
if (len != sizeof(struct wave_data)) {
ret = -1;
goto _exit;
} else if (strncmp(s->wav_info.data_block.data_id, "data", 4)) {
aic_stream_seek(s->stream, s->wav_info.data_block.data_size, SEEK_CUR);
} else {
break;
}
} while(1);
s->bits_per_sample = s->wav_info.fmt_block.wav_format.bits_per_sample;
s->channels = s->wav_info.fmt_block.wav_format.channels;
s->sample_rate = s->wav_info.fmt_block.wav_format.sample_rate;

View File

@@ -74,7 +74,7 @@ s32 rt_audio_render_set_attr(struct aic_audio_render *render,struct aic_audio_re
stream = AUDIO_STREAM_REPLAY;
rt_device_control(rt_render->snd_dev, AUDIO_CTL_START, (void *)&stream);
rt_thread_mdelay(100);
rt_thread_mdelay(200);
return 0;
}

View File

@@ -4,7 +4,8 @@
* author: <jun.ma@artinchip.com>
* Desc: aic_stream
*/
#include <stdio.h>
#include <unistd.h>
#include "aic_stream.h"
#include "aic_file_stream.h"
@@ -15,3 +16,136 @@ s32 aic_stream_open(char *uri, struct aic_stream **stream)
ret = file_stream_open(uri, stream);
return ret;
}
int aic_stream_skip(struct aic_stream *s, int len)
{
return aic_stream_seek(s, len, SEEK_CUR);
}
void aic_stream_w8(struct aic_stream *s, int b)
{
/* aic_stream_write(s, &val, 1);*/
}
void aic_stream_wl32(struct aic_stream *s, unsigned int val)
{
aic_stream_w8(s, (uint8_t)val);
aic_stream_w8(s, (uint8_t)(val >> 8));
aic_stream_w8(s, (uint8_t)(val >> 16));
aic_stream_w8(s, val >> 24);
}
void aic_stream_wb32(struct aic_stream *s, unsigned int val)
{
aic_stream_w8(s, val >> 24);
aic_stream_w8(s, (uint8_t)(val >> 16));
aic_stream_w8(s, (uint8_t)(val >> 8));
aic_stream_w8(s, (uint8_t)val);
}
void aic_stream_wl64(struct aic_stream *s, uint64_t val)
{
aic_stream_wl32(s, (uint32_t)(val & 0xffffffff));
aic_stream_wl32(s, (uint32_t)(val >> 32));
}
void aic_stream_wb64(struct aic_stream *s, uint64_t val)
{
aic_stream_wb32(s, (uint32_t)(val >> 32));
aic_stream_wb32(s, (uint32_t)(val & 0xffffffff));
}
void aic_stream_wl16(struct aic_stream *s, unsigned int val)
{
aic_stream_w8(s, (uint8_t)val);
aic_stream_w8(s, (int)val >> 8);
}
void aic_stream_wb16(struct aic_stream *s, unsigned int val)
{
aic_stream_w8(s, (int)val >> 8);
aic_stream_w8(s, (uint8_t)val);
}
void aic_stream_wl24(struct aic_stream *s, unsigned int val)
{
aic_stream_wl16(s, val & 0xffff);
aic_stream_w8(s, (int)val >> 16);
}
void aic_stream_wb24(struct aic_stream *s, unsigned int val)
{
aic_stream_wb16(s, (int)val >> 8);
aic_stream_w8(s, (uint8_t)val);
}
int aic_stream_r8(struct aic_stream *s)
{
unsigned char val;
aic_stream_read(s, &val, 1);
return val;
}
unsigned int aic_stream_rl16(struct aic_stream *s)
{
unsigned int val;
val = aic_stream_r8(s);
val |= aic_stream_r8(s) << 8;
return val;
}
unsigned int aic_stream_rl24(struct aic_stream *s)
{
unsigned int val;
val = aic_stream_rl16(s);
val |= aic_stream_r8(s) << 16;
return val;
}
unsigned int aic_stream_rl32(struct aic_stream *s)
{
unsigned int val;
val = aic_stream_rl16(s);
val |= aic_stream_rl16(s) << 16;
return val;
}
uint64_t aic_stream_rl64(struct aic_stream *s)
{
uint64_t val;
val = (uint64_t)aic_stream_rl32(s);
val |= (uint64_t)aic_stream_rl32(s) << 32;
return val;
}
unsigned int aic_stream_rb16(struct aic_stream *s)
{
unsigned int val;
val = aic_stream_r8(s) << 8;
val |= aic_stream_r8(s);
return val;
}
unsigned int aic_stream_rb24(struct aic_stream *s)
{
unsigned int val;
val = aic_stream_rb16(s) << 8;
val |= aic_stream_r8(s);
return val;
}
unsigned int aic_stream_rb32(struct aic_stream *s)
{
unsigned int val;
val = aic_stream_rb16(s) << 16;
val |= aic_stream_rb16(s);
return val;
}
uint64_t aic_stream_rb64(struct aic_stream *s)
{
uint64_t val;
val = (uint64_t)aic_stream_rb32(s) << 32;
val |= (uint64_t)aic_stream_rb32(s);
return val;
}

View File

@@ -136,6 +136,29 @@ static int volume(int* vol,char ch)
return volume;
}
static void show_cpu_usage()
{
#ifdef LPKG_USING_CPU_USAGE
static int index = 0;
char data_str[64];
float value = 0.0;
if (index++ % 30 == 0) {
value = cpu_load_average();
#ifdef AIC_PRINT_FLOAT_CUSTOM
int cpu_i;
int cpu_frac;
cpu_i = (int)value;
cpu_frac = (value - cpu_i) * 100;
snprintf(data_str, sizeof(data_str), "%d.%02d\n", cpu_i, cpu_frac);
#else
snprintf(data_str, sizeof(data_str), "%.2f\n", value);
#endif
printf("cpu_loading:%s\n",data_str);
}
#endif
}
static void audio_player_demo(int argc, char **argv)
{
int i,j;
@@ -221,27 +244,7 @@ static void audio_player_demo(int argc, char **argv)
break;
}
usleep(100*1000);
#ifdef LPKG_USING_CPU_USAGE
{
static int index = 0;
char data_str[64];
float value = 0.0;
if (index++ % 30 == 0) {
value = cpu_load_average();
#ifdef AIC_PRINT_FLOAT_CUSTOM
int cpu_i;
int cpu_frac;
cpu_i = (int)value;
cpu_frac = (value - cpu_i) * 100;
snprintf(data_str, sizeof(data_str), "%d.%02d\n", cpu_i, cpu_frac);
#else
snprintf(data_str, sizeof(data_str), "%.2f\n", value);
#endif
printf("cpu_loading:%s\n",data_str);
}
}
#endif
show_cpu_usage();
}
}
}

View File

@@ -555,8 +555,26 @@ static OMX_ERRORTYPE OMX_DemuxerSetParameter(
tmp1 = ((OMX_PARAM_SKIP_TRACK*)pComponentParameterStructure)->nPortIndex;
if (tmp1 == DEMUX_PORT_AUDIO_INDEX) {
pDemuxerDataType->nSkipTrack |= DEMUX_SKIP_AUDIO_TRACK;
aic_pthread_mutex_lock(&pDemuxerDataType->sAudioPktLock);
if (!mpp_list_empty(&pDemuxerDataType->sOutAudioReadyPkt)) {
DEMUXER_OUT_PACKET *pPktNode = NULL,*pPktNode1 = NULL;
mpp_list_for_each_entry_safe(pPktNode, pPktNode1, &pDemuxerDataType->sOutAudioReadyPkt, sList) {
mpp_list_del(&pPktNode->sList);
mpp_list_add_tail(&pPktNode->sList, &pDemuxerDataType->sOutVideoEmptyPkt);
}
}
aic_pthread_mutex_unlock(&pDemuxerDataType->sAudioPktLock);
} else if (tmp1 == DEMUX_PORT_VIDEO_INDEX) {
pDemuxerDataType->nSkipTrack |= DEMUX_SKIP_VIDEO_TRACK;
aic_pthread_mutex_lock(&pDemuxerDataType->sVideoPktLock);
if (!mpp_list_empty(&pDemuxerDataType->sOutVideoReadyPkt)) {
DEMUXER_OUT_PACKET *pPktNode = NULL,*pPktNode1 = NULL;
mpp_list_for_each_entry_safe(pPktNode, pPktNode1, &pDemuxerDataType->sOutVideoReadyPkt, sList) {
mpp_list_del(&pPktNode->sList);
mpp_list_add_tail(&pPktNode->sList, &pDemuxerDataType->sOutVideoEmptyPkt);
}
}
aic_pthread_mutex_unlock(&pDemuxerDataType->sVideoPktLock);
}
break;
default:

View File

@@ -64,6 +64,7 @@ struct aic_player {
s64 video_pts;
s64 audio_pts;
s32 volume;
s32 rotation_angle;
s8 mute;
s8 seeking;
};
@@ -430,6 +431,13 @@ s32 aic_player_start(struct aic_player *player)
goto _EXIT;
}
if (player->disp_rect.width != 0 && player->disp_rect.height != 0) {
aic_player_set_disp_rect(player,&player->disp_rect);
}
if (player->rotation_angle != MPP_ROTATION_0) {
aic_player_set_rotation(player,player->rotation_angle);
}
if (OMX_ErrorNone !=OMX_SetupTunnel(player->demuxer_handle, DEMUX_PORT_VIDEO_INDEX, player->vdecoder_handle, VDEC_PORT_IN_INDEX)) {
loge("OMX_SetupTunnel error.\n");
goto _EXIT;
@@ -492,6 +500,10 @@ _AUDIO:
goto _EXIT;
}
if (player->volume != 0) {
aic_player_set_volum(player,player->volume);
}
if (OMX_ErrorNone !=OMX_SetupTunnel(player->demuxer_handle, DEMUX_PORT_AUDIO_INDEX, player->adecoder_handle, ADEC_PORT_IN_INDEX)) {
loge("OMX_SetupTunnel error.\n");
goto _EXIT;
@@ -960,7 +972,7 @@ s32 aic_player_get_media_info(struct aic_player *player,struct av_media_info *me
s32 aic_player_get_screen_size(struct aic_player *player,struct mpp_size *screen_size)
{
OMX_PARAM_SCREEN_SIZE rect;
OMX_PARAM_SCREEN_SIZE rect = {0};
if (!player->media_info.has_video || !player->video_render_handle) {
loge("no video!!!!\n");
@@ -975,11 +987,11 @@ s32 aic_player_get_screen_size(struct aic_player *player,struct mpp_size *screen
s32 aic_player_set_disp_rect(struct aic_player *player,struct mpp_rect *disp_rect)
{
OMX_CONFIG_RECTTYPE rect;
OMX_CONFIG_RECTTYPE rect = {0};
player->disp_rect = *disp_rect;
if (!player->media_info.has_video || !player->video_render_handle) {
loge("no video!!!!\n");
return -1;
return 0;
}
rect.nLeft = disp_rect->x;
rect.nTop = disp_rect->y;
@@ -1003,6 +1015,7 @@ s32 aic_player_get_disp_rect(struct aic_player *player,struct mpp_rect *disp_rec
disp_rect->y = rect.nTop;
disp_rect->width = rect.nWidth;
disp_rect->height = rect.nHeight;
player->disp_rect = *disp_rect;
return 0;
}
@@ -1039,13 +1052,10 @@ s32 aic_player_set_mute(struct aic_player *player)
s32 aic_player_set_volum(struct aic_player *player,s32 vol)
{
OMX_PARAM_AUDIO_VOLUME sVolume;
if (!player->media_info.has_audio || !player->audio_render_handle) {
loge("aic_player_set_volum\n");
return -1;
}
logd("aic_player_set_volum\n");
player->volume = vol;
if (!player->media_info.has_audio || !player->audio_render_handle) {
return 0;
}
sVolume.nVolume = vol;
OMX_SetParameter(player->audio_render_handle, OMX_IndexVendorAudioRenderVolume, &sVolume);
return 0;
@@ -1053,13 +1063,14 @@ s32 aic_player_set_volum(struct aic_player *player,s32 vol)
s32 aic_player_get_volum(struct aic_player *player,s32 *vol)
{
OMX_PARAM_AUDIO_VOLUME sVolume;
OMX_PARAM_AUDIO_VOLUME sVolume = {0};
if (!player->media_info.has_audio || !player->audio_render_handle || !vol) {
return -1;
}
OMX_GetParameter(player->video_render_handle, OMX_IndexVendorAudioRenderVolume, &sVolume);
*vol = sVolume.nVolume;
player->volume = sVolume.nVolume;
return 0;
}
@@ -1072,10 +1083,6 @@ s32 aic_player_capture(struct aic_player *player, struct aic_capture_info *captu
s32 aic_player_set_rotation(struct aic_player *player, int rotation_angle)
{
OMX_CONFIG_ROTATIONTYPE rotation;
if (!player->media_info.has_video || !player->video_render_handle) {
loge("no video!!!!\n");
return -1;
}
if (rotation_angle != MPP_ROTATION_0
&& rotation_angle != MPP_ROTATION_90
@@ -1084,6 +1091,10 @@ s32 aic_player_set_rotation(struct aic_player *player, int rotation_angle)
loge("param error!!!!\n");
return -1;
}
player->rotation_angle = rotation_angle;
if (!player->media_info.has_video || !player->video_render_handle) {
return 0;
}
rotation.nRotation = rotation_angle;
if (OMX_ErrorNone != OMX_SetConfig(player->video_render_handle,OMX_IndexConfigCommonRotate,&rotation)) {
loge("no video!!!!\n");
@@ -1094,7 +1105,7 @@ s32 aic_player_set_rotation(struct aic_player *player, int rotation_angle)
s32 aic_player_get_rotation(struct aic_player *player)
{
OMX_CONFIG_ROTATIONTYPE rotation;
OMX_CONFIG_ROTATIONTYPE rotation = {0};
if (!player->media_info.has_video || !player->video_render_handle) {
loge("no video!!!!\n");
return -1;
@@ -1104,7 +1115,7 @@ s32 aic_player_get_rotation(struct aic_player *player)
loge("no video!!!!\n");
return -1;
}
player->rotation_angle = rotation.nRotation;
return rotation.nRotation;
}

View File

@@ -2,7 +2,7 @@
* Copyright (C) 2020-2023 ArtInChip Technology Co. Ltd
*
* author: <jun.ma@artinchip.com>
* Desc: OMX_VdecComponent tunneld OMX_VideoRenderComponent demo
* Desc: player_demo
*/
#include <string.h>
@@ -39,18 +39,27 @@
#define PLAYER_DEMO_FILE_MAX_NUM 128
#define PLAYER_DEMO_FILE_PATH_MAX_LEN 256
#define BUFFER_LEN 16
static int g_player_end = 0;
static int g_player_stop = 0;
static int g_demuxer_detected_flag = 0;
static int g_sync_flag = AIC_PLAYER_PREPARE_SYNC;
static struct av_media_info g_media_info;
struct file_list {
char *file_path[PLAYER_DEMO_FILE_MAX_NUM];
int file_num;
};
struct video_player_ctx {
struct aic_player *player;
struct file_list files;
int volume;
int loop_time;
int seek_loop;
int rotation;
int alpha_value;
int player_end;
int player_stop;
struct av_media_info media_info;
};
struct video_player_ctx *g_video_player_ctx = NULL;
static void print_help(const char* prog)
{
printf("name: %s\n", prog);
@@ -59,16 +68,12 @@ static void print_help(const char* prog)
"\t-i input stream file name\n"
"\t-t directory of test files\n"
"\t-l loop time\n"
"\t-c save capture file path,default /sdcard/video/capture.jpg \n"
"\t-W capture widht\n"
"\t-H capture height\n"
"\t-q capture quality\n"
"\t-r rotation\n"
"\t-h help\n\n"
"Example1(test single file for 1 time): player_demo -i /mnt/video/test.mp4 \n"
"Example2(test single file for 3 times): player_demo -i /mnt/video/test.mp4 -l 3 \n"
"Example3(test some files for 1 time ) : player_demo -t /mnt/video \n"
"Example4(test some files for 3 times ): player_demo -t /mnt/video -l 3 \n"
"Example3(test dir for 1 time ) : player_demo -t /mnt/video \n"
"Example4(test dir for 3 times ): player_demo -t /mnt/video -l 3 \n"
"---------------------------------------------------------------------------------------\n"
"-------------------------------control key while playing-------------------------------\n"
"---------------------------------------------------------------------------------------\n"
@@ -81,8 +86,24 @@ static void print_help(const char* prog)
"('b'): back seek -8s \n"
"('z'): seek to begin pos \n"
"('m': enter/eixt mute \n"
"('e'): eixt app \n"
"('c'): capture pic,firstly,please pause and then capture \n");
"('e'): eixt app \n");
}
static int read_file(char* path, struct file_list *files)
{
int file_path_len;
file_path_len = strlen(path);
printf("file_path_len:%d\n",file_path_len);
if (file_path_len > PLAYER_DEMO_FILE_PATH_MAX_LEN-1) {
printf("file_path_len too long \n");
return -1;
}
files->file_path[0] = (char *)aicos_malloc(MEM_DEFAULT,file_path_len+1);
files->file_path[0][file_path_len] = '\0';
strcpy(files->file_path[0], path);
files->file_num = 1;
printf("file path: %s\n", files->file_path[0]);
return 0;
}
static int read_dir(char* path, struct file_list *files)
@@ -104,7 +125,7 @@ static int read_dir(char* path, struct file_list *files)
if (ptr == NULL)
continue;
if (strcmp(ptr, ".h264") && strcmp(ptr, ".264") && strcmp(ptr, ".mp4") && strcmp(ptr, ".mp3"))
if (strcmp(ptr, ".h264") && strcmp(ptr, ".264") && strcmp(ptr, ".mp4") && strcmp(ptr, ".mp3") && strcmp(ptr, ".avi"))
continue;
logd("name: %s", dir_file->d_name);
@@ -134,33 +155,20 @@ static int read_dir(char* path, struct file_list *files)
void player_demo_stop(void)
{
g_player_stop = 1;
if (g_video_player_ctx)
g_video_player_ctx->player_stop = 1;
}
s32 event_handle(void* app_data,s32 event,s32 data1,s32 data2)
{
int ret = 0;
struct video_player_ctx *ctx = (struct video_player_ctx *)app_data;
switch(event) {
case AIC_PLAYER_EVENT_PLAY_END:
g_player_end = 1;
ctx->player_end = 1;
logd("g_player_end\n");
break;
case AIC_PLAYER_EVENT_PLAY_TIME:
break;
case AIC_PLAYER_EVENT_DEMUXER_FORMAT_DETECTED:
if (AIC_PLAYER_PREPARE_ASYNC == g_sync_flag) {
g_demuxer_detected_flag = 1;
logd("AIC_PLAYER_EVENT_DEMUXER_FORMAT_DETECTED\n");
}
break;
case AIC_PLAYER_EVENT_DEMUXER_FORMAT_NOT_DETECTED:
if (AIC_PLAYER_PREPARE_ASYNC == g_sync_flag) {
logd("AIC_PLAYER_EVENT_DEMUXER_FORMAT_NOT_DETECTED\n");
logd("cur file format not detected,play next file!!!!!!\n");
g_player_end = 1;
}
break;
default:
break;
@@ -168,8 +176,9 @@ s32 event_handle(void* app_data,s32 event,s32 data1,s32 data2)
return ret;
}
static int set_volume(struct aic_player *player,int volume)
static int set_volume(struct video_player_ctx *player_ctx,int volume)
{
struct video_player_ctx *ctx = player_ctx;
if (volume < 0) {
volume = 0;
} else if (volume < 101) {
@@ -178,13 +187,14 @@ static int set_volume(struct aic_player *player,int volume)
volume = 100;
}
logd("volume:%d\n",volume);
return aic_player_set_volum(player,volume);
return aic_player_set_volum(ctx->player,volume);
}
static int do_seek(struct aic_player *player,int forward)
static int do_seek(struct video_player_ctx *player_ctx,int forward)
{
s64 pos;
pos = aic_player_get_play_time(player);
struct video_player_ctx *ctx = player_ctx;
pos = aic_player_get_play_time(ctx->player);
if (pos == -1) {
loge("aic_player_get_play_time error!!!!\n");
return -1;
@@ -197,13 +207,13 @@ static int do_seek(struct aic_player *player,int forward)
if (pos < 0) {
pos = 0;
} else if (pos < g_media_info.duration) {
} else if (pos < ctx->media_info.duration) {
} else {
pos = g_media_info.duration;
pos = ctx->media_info.duration;
}
if (aic_player_seek(player,pos) != 0) {
if (aic_player_seek(ctx->player,pos) != 0) {
loge("aic_player_seek error!!!!\n");
return -1;
}
@@ -211,23 +221,25 @@ static int do_seek(struct aic_player *player,int forward)
return 0;
}
static int do_rotation_common(struct aic_player *player, u32 rotation)
static int do_rotation_common(struct video_player_ctx *player_ctx, u32 rotation)
{
struct video_player_ctx *ctx = player_ctx;
if (rotation > MPP_ROTATION_270) {
loge("Invalid rotation: %d\n", rotation);
rotation = MPP_ROTATION_0;
}
logd("Rotation %d\n", rotation * 90);
aic_player_set_rotation(player, rotation);
aic_player_set_rotation(ctx->player, rotation);
return 0;
}
static int do_rotation(struct aic_player *player)
static int do_rotation(struct video_player_ctx *player_ctx)
{
static int index = 0;
struct video_player_ctx *ctx = player_ctx;
do_rotation_common(player, index % 4);
do_rotation_common(ctx, index % 4);
index++;
return 0;
}
@@ -280,25 +292,26 @@ out:
return 0;
}
static int start_play(struct aic_player *player,int volume)
static int start_play(struct video_player_ctx *player_ctx)
{
int ret = -1;
static struct av_media_info media_info;
struct mpp_size screen_size;
struct video_player_ctx *ctx = player_ctx;
ret = aic_player_start(player);
ret = aic_player_start(ctx->player);
if (ret != 0) {
loge("aic_player_start error!!!!\n");
return -1;
}
printf("[%s:%d]aic_player_start ok\n",__FUNCTION__,__LINE__);
ret = aic_player_get_media_info(player,&media_info);
ret = aic_player_get_media_info(ctx->player,&media_info);
if (ret != 0) {
loge("aic_player_get_media_info error!!!!\n");
return -1;
}
g_media_info = media_info;
ctx->media_info = media_info;
logd("aic_player_get_media_info duration:"FMT_x64",file_size:"FMT_x64"\n",media_info.duration,media_info.file_size);
logd("has_audio:%d,has_video:%d,"
@@ -313,7 +326,7 @@ static int start_play(struct aic_player *player,int volume)
,media_info.audio_stream.sample_rate);
if (media_info.has_video) {
ret = aic_player_get_screen_size(player, &screen_size);
ret = aic_player_get_screen_size(ctx->player, &screen_size);
if (ret != 0) {
loge("aic_player_get_screen_size error!!!!\n");
return -1;
@@ -327,7 +340,7 @@ static int start_play(struct aic_player *player,int volume)
loge("Failed to calculate the size of screen\n");
return -1;
}
ret = aic_player_set_disp_rect(player, &disp_rect);//attention:disp not exceed screen_size
ret = aic_player_set_disp_rect(ctx->player, &disp_rect);//attention:disp not exceed screen_size
if (ret != 0) {
loge("aic_player_set_disp_rect error\n");
return -1;
@@ -335,17 +348,20 @@ static int start_play(struct aic_player *player,int volume)
logd("aic_player_set_disp_rect ok\n");
}
if (ctx->rotation)
do_rotation_common(ctx, ctx->rotation);
}
if (media_info.has_audio) {
ret = set_volume(player,volume);
ret = set_volume(ctx,ctx->volume);
if (ret != 0) {
loge("set_volume error!!!!\n");
return -1;
}
}
ret = aic_player_play(player);
ret = aic_player_play(ctx->player);
if (ret != 0) {
loge("aic_player_play error!!!!\n");
return -1;
@@ -430,61 +446,140 @@ static void hook_of_scheduler(struct rt_thread *from,struct rt_thread *to) {
}
#endif
static int parse_options(struct video_player_ctx *player_ctx,int cnt,char**options)
{
int argc = cnt;
char **argv = options;
struct video_player_ctx *ctx = player_ctx;
int opt;
if (!ctx || argc == 0 || !argv) {
loge("para error !!!");
return -1;
}
//set default alpha_value loop_time volume
ctx->alpha_value = 0;
ctx->loop_time = 1;
ctx->volume = 100;
ctx->player_end = 0;
optind = 0;
while (1) {
opt = getopt(argc, argv, "i:t:l:c:W:H:q:a:r:sh");
if (opt == -1) {
break;
}
switch (opt) {
case 'i':
read_file(optarg,&ctx->files);
break;
case 'l':
ctx->loop_time = atoi(optarg);
break;
case 't':
read_dir(optarg, &ctx->files);
break;
case 'a':
ctx->alpha_value = atoi(optarg);
printf("alpha_value:%d\n",ctx->alpha_value);
break;
case 'r':
ctx->rotation = (atoi(optarg) % 360) / 90;
break;
case 's':
ctx->seek_loop = 1;
break;
case 'h':
print_help(argv[0]);
return -1;
default:
break;
}
}
if (ctx->files.file_num == 0) {
print_help(argv[0]);
return -1;
}
return 0;
}
static int process_command(struct video_player_ctx *player_ctx,char cmd)
{
struct video_player_ctx *ctx = player_ctx;
int ret = 0;
if (cmd == 0x20) {// pause
ret = aic_player_pause(ctx->player);
} else if (cmd == '-') {
ctx->volume -= 5;
ret = set_volume(ctx,ctx->volume);
} else if (cmd == '+') {
ctx->volume += 5;
ret = set_volume(ctx,ctx->volume);
} else if (cmd == 'm') {
ret = aic_player_set_mute(ctx->player);
} else if (cmd == 'f') {
ret = do_seek(ctx,1);//+8s
} else if (cmd == 'b') {
ret = do_seek(ctx,0);//-8s
} else if (cmd == 'z') {
ret = aic_player_seek(ctx->player,0);
} else if (cmd == 'r') {
ret = do_rotation(ctx);
}
return ret;
}
static int power_on_flag = 0;
static void player_demo_test(int argc, char **argv)
{
int ret = 0;
int i = 0;
int j = 0;
char ch;
int file_path_len;
int opt;
int loop_time = 1;
struct file_list files;
struct aic_player *player = NULL;
int volume = 100;
struct aic_capture_info capture_info;
char file_path[255] = {"/sdcard/video/capture.jpg"};
rt_device_t render_dev = RT_NULL;
struct aicfb_alpha_config alpha_bak = {0};
struct aicfb_alpha_config alpha = {0};
rt_device_t uart_dev = RT_NULL;
u32 rotation = MPP_ROTATION_0;
int seek_loop = 0;
struct video_player_ctx *ctx = NULL;
g_player_end = 0;
g_player_stop = 0;
ctx = mpp_alloc(sizeof(struct video_player_ctx));
if (!ctx) {
loge("mpp_alloc fail!!!");
return;
}
memset(ctx,0x00,sizeof(struct video_player_ctx));
g_video_player_ctx = ctx;
if (strcmp(PRJ_CHIP, "d13x") == 0) {
rt_device_t render_dev;
struct aicfb_layer_data layer = {0};
//get fb dev
render_dev = rt_device_find("aicfb");
if (render_dev == NULL) {
loge("rt_device_find aicfb failed!");
return;
}
if (!power_on_flag) {
rt_device_control(render_dev,AICFB_POWERON,0);
power_on_flag = 1;
}
layer.layer_id = AICFB_LAYER_TYPE_UI;
layer.enable = 0;
rt_device_control(render_dev,AICFB_UPDATE_LAYER_CONFIG,&layer);
// get serial dev
if (parse_options(ctx,argc,argv)) {
loge("parse_options fail!!!\n");
goto _EXIT_;
}
render_dev = rt_device_find("aicfb");
if (!render_dev) {
loge("rt_device_find aicfb failed!");
goto _EXIT_;
}
// get serial dev
uart_dev = rt_device_find(RT_CONSOLE_DEVICE_NAME);
if (uart_dev == NULL) {
loge("Failed to open %s\n", RT_CONSOLE_DEVICE_NAME);
return;
goto _EXIT_;
}
//default capture_info
capture_info.file_path = (s8 *)file_path;
capture_info.width = 1024;
capture_info.height = 600;
capture_info.quality = 90;
memset(&files,0x00,sizeof(struct file_list));
if (!power_on_flag) {
rt_device_control(render_dev,AICFB_POWERON,0);
power_on_flag = 1;
}
//stroe alpha
alpha_bak.layer_id = AICFB_LAYER_TYPE_UI;
rt_device_control(render_dev, AICFB_GET_ALPHA_CONFIG, &alpha_bak);
//set alpha
alpha.layer_id = AICFB_LAYER_TYPE_UI;
alpha.enable = 1;
alpha.mode = 1;
alpha.value = ctx->alpha_value;
rt_device_control(render_dev, AICFB_UPDATE_ALPHA_CONFIG, &alpha);
#ifdef _THREAD_TRACE_INFO_
memset(&thread_trace_infos,0x00,sizeof(struct thread_trace_info));
@@ -495,175 +590,68 @@ static void player_demo_test(int argc, char **argv)
rt_scheduler_sethook(hook_of_scheduler);
#endif
optind = 0;
while (1) {
opt = getopt(argc, argv, "i:t:l:c:W:H:q:r:sh");
if (opt == -1) {
break;
}
switch (opt) {
case 'i':
file_path_len = strlen(optarg);
printf("file_path_len:%d\n",file_path_len);
if (file_path_len > PLAYER_DEMO_FILE_PATH_MAX_LEN-1) {
loge("file_path_len too long \n");
goto _EXIT0_;
}
files.file_path[0] = (char *)mpp_alloc(file_path_len+1);
files.file_path[0][file_path_len] = '\0';
strcpy(files.file_path[0], optarg);
files.file_num = 1;
logd("file path: %s", files.file_path[0]);
break;
case 'l':
loop_time = atoi(optarg);
break;
case 't':
read_dir(optarg, &files);
break;
case 'c':
memset(file_path,0x00,sizeof(file_path));
strncpy(file_path, optarg,sizeof(file_path)-1);
logd("file path: %s", file_path);
break;
case 'W':
capture_info.width = atoi(optarg);
break;
case 'H':
capture_info.height = atoi(optarg);
break;
case 'q':
capture_info.quality = atoi(optarg);
break;
case 'r':
rotation = (atoi(optarg) % 360) / 90;
break;
case 's':
seek_loop = 1;
break;
case 'h':
print_help(argv[0]);
default:
goto _EXIT0_;
break;
}
}
if (files.file_num == 0) {
print_help(argv[0]);
loge("files.file_num ==0 !!!\n");
goto _EXIT0_;
}
player = aic_player_create(NULL);
if (player == NULL) {
ctx->player = aic_player_create(NULL);
if (ctx->player == NULL) {
loge("aic_player_create fail!!!\n");
goto _EXIT0_;
goto _EXIT_;
}
aic_player_set_event_callback(player,player,event_handle);
g_sync_flag = AIC_PLAYER_PREPARE_SYNC;
aic_player_set_event_callback(ctx->player,ctx,event_handle);
for(i = 0;i < loop_time; i++) {
for(j = 0; j < files.file_num; j++) {
aic_player_set_uri(player,files.file_path[j]);
if (g_sync_flag == AIC_PLAYER_PREPARE_ASYNC) {
ret = aic_player_prepare_async(player);
} else {
ret = aic_player_prepare_sync(player);
}
if (ret) {
for(i = 0;i < ctx->loop_time; i++) {
for(j = 0; j < ctx->files.file_num; j++) {
logd("loop:%d,index:%d,path:%s\n",i,j,ctx->files.file_path[j]);
ctx->player_end = 0;
if (aic_player_set_uri(ctx->player,ctx->files.file_path[j])) {
loge("aic_player_prepare error!!!!\n");
g_player_end = 1;
goto _NEXT_FILE_;
aic_player_stop(ctx->player);
continue;
}
if (g_sync_flag == AIC_PLAYER_PREPARE_SYNC) {
if (start_play(player,volume) != 0) {
g_player_end = 1;
goto _NEXT_FILE_;
}
if (aic_player_prepare_sync(ctx->player)) {
loge("aic_player_prepare error!!!!\n");
aic_player_stop(ctx->player);
continue;
}
if (rotation)
do_rotation_common(player, rotation);
if (start_play(ctx) != 0) {
loge("start_play error!!!!\n");
aic_player_stop(ctx->player);
continue;
}
while(1)
{
_NEXT_FILE_:
if (g_player_stop == 1) {
if (ctx->player_stop == 1) {
logd("Stop player!\n");
aic_player_stop(player);
goto _EXIT0_;
aic_player_stop(ctx->player);
goto _EXIT_;
}
if (g_player_end == 1) {
logd("play file:%s end!!!!\n",files.file_path[j]);
if(seek_loop == 1) {
aic_player_seek(player,0);
g_player_end = 0;
if (ctx->player_end == 1) {
logd("play file:%s end!!!!\n",ctx->files.file_path[j]);
if(ctx->seek_loop == 1) {
aic_player_seek(ctx->player,0);
ctx->player_end = 0;
} else {
aic_player_stop(player);
g_player_end = 0;
aic_player_stop(ctx->player);
ctx->player_end = 0;
break;
}
}
if (g_sync_flag == AIC_PLAYER_PREPARE_ASYNC && g_demuxer_detected_flag == 1) {
g_demuxer_detected_flag = 0;
if (start_play(player, volume) != 0) {
g_player_end = 1;
goto _NEXT_FILE_;
}
}
if (rt_device_read(uart_dev, -1, &ch, 1) == 1) {
if (ch == 0x20) {// pause
logd("*********enter pause ***************\n");
aic_player_pause(player);
} else if (ch == 'd') {//stop cur, star next
logd("*********enter down ***************\n");
aic_player_stop(player);
break;
} else if (ch == 'u') {//stop cur, star pre
logd("*********enter up j:%d***************\n",j);
aic_player_stop(player);
if (ch == 'u') {// up
j -= 2;
j = (j < -1)?(-1):(j);
aic_player_stop(ctx->player);
break;
} else if (ch == '-') {
logd("*********enter volume--**************\n");
volume -= 5;
set_volume(player,volume);
} else if (ch == '+') {
logd("*********enter volume++***************\n");
volume += 5;
set_volume(player,volume);
} else if (ch == 'm') {
logd("*********enter/exit mute***************\n");
aic_player_set_mute(player);
} else if (ch == 'c') {
logd("*********capture***************\n");
if (aic_player_capture(player,&capture_info) == 0) {
logd("*********aic_player_capture ok***************\n");
} else {
loge("*********aic_player_capture fail ***************\n");
}
} else if (ch == 'f') {
logd("*********forward***************\n");
do_seek(player,1);//+8s
} else if (ch == 'b') {
logd("*********back***************\n");
do_seek(player,0);//-8s
} else if (ch == 'z') {//seek to start
if (aic_player_seek(player,0) != 0) {
loge("aic_player_seek error!!!!\n");
} else {
logd("aic_player_seek ok\n");
}
} else if (ch == 'r') {
do_rotation(player);
} else if (ch == 'e') {
aic_player_stop(player);
goto _EXIT0_;
} else if (ch == 'd') {// down
aic_player_stop(ctx->player);
break;
} else if (ch == 'e') {// end
aic_player_stop(ctx->player);
goto _EXIT_;
}
process_command(ctx,ch);
} else {
show_cpu_usage();
usleep(100*1000);
@@ -672,16 +660,26 @@ static void player_demo_test(int argc, char **argv)
}
}
_EXIT0_:
if (player)
aic_player_destroy(player);
_EXIT_:
if (ctx->player) {
aic_player_destroy(ctx->player);
ctx->player = NULL;
}
for(i = 0; i <files.file_num ;i++) {
if (files.file_path[i]) {
mpp_free(files.file_path[i]);
for(i = 0; i <ctx->files.file_num ;i++) {
if (ctx->files.file_path[i]) {
mpp_free(ctx->files.file_path[i]);
ctx->files.file_path[i] = NULL;
}
}
if (render_dev) {
//restore alpha
rt_device_control(render_dev, AICFB_UPDATE_ALPHA_CONFIG, &alpha_bak);
}
mpp_free(ctx);
g_video_player_ctx = ctx = NULL;
logd("player_demo exit\n");
return;
}