mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 10:28:54 +00:00
V1.0.5
This commit is contained in:
@@ -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
12
packages/artinchip/mpp/middle_media/base/CMakeLists.txt
Executable file → Normal 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"
|
||||
)
|
||||
|
||||
145
packages/artinchip/mpp/middle_media/base/comm/aic_tag.c
Normal file
145
packages/artinchip/mpp/middle_media/base/comm/aic_tag.c
Normal 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;
|
||||
}
|
||||
99
packages/artinchip/mpp/middle_media/base/comm/aic_tag.h
Normal file
99
packages/artinchip/mpp/middle_media/base/comm/aic_tag.h
Normal 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 */
|
||||
@@ -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;
|
||||
|
||||
40
packages/artinchip/mpp/middle_media/base/include/aic_stream.h
Executable file → Normal file
40
packages/artinchip/mpp/middle_media/base/include/aic_stream.h
Executable file → Normal 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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
992
packages/artinchip/mpp/middle_media/base/parser/avi/avi.c
Normal file
992
packages/artinchip/mpp/middle_media/base/parser/avi/avi.c
Normal 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;
|
||||
}
|
||||
101
packages/artinchip/mpp/middle_media/base/parser/avi/avi.h
Normal file
101
packages/artinchip/mpp/middle_media/base/parser/avi/avi.h
Normal 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__ */
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
136
packages/artinchip/mpp/middle_media/base/stream/aic_stream.c
Executable file → Normal file
136
packages/artinchip/mpp/middle_media/base/stream/aic_stream.c
Executable file → Normal 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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user