mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-17 06:06:00 -06:00
268 lines
8.2 KiB
C++
268 lines
8.2 KiB
C++
#ifndef _Media_mediafile_h_
|
|
#define _Media_mediafile_h_
|
|
|
|
#include <SDL/SDLCtrl.h>
|
|
#include <Media/ffmpeg_base.h>
|
|
#include "mt.h"
|
|
|
|
/* SDL audio buffer size, in samples. Should be small to have precise
|
|
A/V sync as SDL does not have hardware buffer fullness info. */
|
|
#define SDL_AUDIO_BUFFER_SIZE 1024
|
|
|
|
#define MAX_VIDEOQ_SIZE (5 * 256 * 1024)
|
|
#define MAX_AUDIOQ_SIZE (5 * 16 * 1024)
|
|
#define MAX_SUBTITLEQ_SIZE (5 * 16 * 1024)
|
|
|
|
#define VIDEO_PICTURE_QUEUE_SIZE 2
|
|
#define SUBPICTURE_QUEUE_SIZE 4
|
|
|
|
// we use about AUDIO_DIFF_AVG_NB A-V differences to make the average
|
|
#define AUDIO_DIFF_AVG_NB 20
|
|
|
|
// NOTE: the size must be big enough to compensate the hardware audio buffersize size
|
|
#define SAMPLE_ARRAY_SIZE (2*65536)
|
|
|
|
/* maximum audio speed change to get correct sync */
|
|
#define SAMPLE_CORRECTION_PERCENT_MAX 10
|
|
|
|
/* no AV sync correction is done if below the AV sync threshold */
|
|
#define AV_SYNC_THRESHOLD 0.01
|
|
/* no AV correction is done if too big error */
|
|
#define AV_NOSYNC_THRESHOLD 10.0
|
|
|
|
#define FF_ALLOC_EVENT (SDL_USEREVENT)
|
|
#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
|
|
#define FF_QUIT_EVENT (SDL_USEREVENT + 2)
|
|
|
|
enum {
|
|
AV_SYNC_AUDIO_MASTER, /* default choice */
|
|
AV_SYNC_VIDEO_MASTER,
|
|
AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
|
|
};
|
|
|
|
struct VideoPicture {
|
|
double pts; // presentation time stamp for this picture
|
|
double target_clock; // GetUSec() time at which this should be displayed ideally
|
|
int64_t pos; // byte position in file
|
|
SDL_Overlay *overlay;
|
|
SDL_Surface *surface;
|
|
int width, height; // source height & width
|
|
bool allocated;
|
|
enum PixelFormat pix_fmt;
|
|
};
|
|
|
|
struct SubPicture {
|
|
double pts; // presentation time stamp for this picture
|
|
AVSubtitle sub;
|
|
};
|
|
|
|
class PacketQueue {
|
|
public:
|
|
PacketQueue();
|
|
void SetMaxSize(int _maxSize) {maxSize = _maxSize;};
|
|
void Init();
|
|
void Init(AVPacket &pkt, AVPacket *flush_pkt);
|
|
int Put(AVPacket *pkt, AVPacket *flush_pkt);
|
|
int Get(AVPacket *pkt, bool decodeEnd);
|
|
void Flush();
|
|
void End();
|
|
void Abort();
|
|
inline bool IsAbort() {return abort_request;};
|
|
bool IsFull() {return size > maxSize;};
|
|
|
|
private:
|
|
AVPacketList *first_pkt, *last_pkt;
|
|
int nb_packets;
|
|
int size;
|
|
int maxSize;
|
|
bool abort_request;
|
|
Mutex mutex;
|
|
ConditionVariable cond;
|
|
};
|
|
|
|
void sdl_audio_callback(void *data, Uint8 *stream, int len);
|
|
|
|
class MediaFile {
|
|
typedef MediaFile CLASSNAME;
|
|
public:
|
|
friend int decoderInterrupt_cb();
|
|
friend void sdl_audio_callback(void *data, Uint8 *stream, int len);
|
|
|
|
MediaFile();
|
|
~MediaFile();
|
|
|
|
inline bool IsOpened() {return fileData;};
|
|
|
|
inline String GetFileName() {return !fileData ? "" : fileData->filename;};
|
|
inline double GetDuration() {return !fileData ? -1 : double(fileData->duration) / AV_TIME_BASE;};
|
|
inline int64 GetDurationTimeBase() {return !fileData ? -1 : fileData->duration;};
|
|
inline int GetNumStreams() {return !fileData ? -1 : fileData->nb_streams;};
|
|
|
|
int GetNumVideo() {return numVideoStreams;};
|
|
int GetNumAudio() {return numAudioStreams;};
|
|
|
|
inline double GetSecond() {return second;};
|
|
void SetSecond(double second);
|
|
|
|
void EnableAudio(bool v = true) {audio_disable = !v;};
|
|
void EnableVideo(bool v = true) {video_disable = !v;};
|
|
|
|
inline void SetVideo(int id) {if(id < GetNumStreams() && id >= -1) idVideo = id;};
|
|
inline void SetAudio(int id) {if(id < GetNumStreams() && id >= -1) idAudio = id;};
|
|
inline void SetSubtitle(int id) {if(id < GetNumStreams() && id >= -1) idSubtitle = id;};
|
|
inline int GetVideo() {return idVideo;};
|
|
inline int GetAudio() {return idAudio;};
|
|
inline int GetSubtitle() {return idSubtitle;};
|
|
|
|
inline MediaFile& ShowAudio(bool show = true) {showAudio = show; return *this;};
|
|
inline MediaFile& SetShowAudioFPS(double fps) {showAudioFps = fps; return *this;};
|
|
|
|
inline MediaFile& SetAudioFactor(double f) {audioFactor = int(f*1000); return *this;};
|
|
|
|
struct StreamData {
|
|
int id;
|
|
String codec;
|
|
String lang;
|
|
uint32 bitrate;
|
|
String tags; // Tags in metadata
|
|
};
|
|
struct VideoData : public StreamData {
|
|
String pixFmt;
|
|
Size size;
|
|
Size par; // Pixel aspect ratio
|
|
Size dar; // Display aspect ratio
|
|
Size frameRate, tbr, tbn, tbc;
|
|
};
|
|
struct AudioData : public StreamData {
|
|
int channels;
|
|
String bits;
|
|
uint32 sampleRate;
|
|
};
|
|
Array<AudioData> audioData;
|
|
int GetAudioId();
|
|
void SetAudioId(int id);
|
|
|
|
Array<VideoData> videoData;
|
|
int GetVideoId();
|
|
void SetVideoId(int id);
|
|
|
|
inline MediaFile& SetRGB(bool v) {rgb = v; return *this;};
|
|
|
|
protected:
|
|
void Reset();
|
|
void stream_seek(int64_t pos, int64_t rel, bool seek_by_bytes);
|
|
bool StreamOpen(int streamId);
|
|
void StreamClose(int streamId);
|
|
int audio_decode_frame(double *pts_ptr);
|
|
void update_sample_display(short *samples, int samples_size);
|
|
int synchronize_audio(short *samples, int samples_size1, double pts);
|
|
int GetAudioOutputBufferSize();
|
|
double get_audio_clock();
|
|
double get_video_clock();
|
|
double get_master_clock();
|
|
double get_external_clock();
|
|
bool queue_picture(AVFrame *src_frame, double pts);
|
|
void stream_pause();
|
|
void DecoderThread();//void *arg);
|
|
void VideoThread();//(void *arg);
|
|
void SubtitleThread();//(void *arg);
|
|
bool BeginDecoder();
|
|
|
|
AVFormatContext *fileData;
|
|
PacketQueue videoq, audioq, subtitleq;
|
|
AtomicVar requestAbort,
|
|
decodeThEnd, decodeThEnded,
|
|
audioThEnd, videoThEnd, subtitleThEnd;
|
|
int threadCount;
|
|
int numVideoStreams, numAudioStreams;
|
|
double second, lastSecond;
|
|
int idVideo, idAudio, idSubtitle;
|
|
String tags;
|
|
bool audio_disable, video_disable;
|
|
bool seek_by_bytes;
|
|
int64_t start_time;
|
|
bool seek_req;
|
|
int seek_flags;
|
|
int64_t seek_pos;
|
|
int64_t seek_rel;
|
|
int paused, last_paused;
|
|
AVPacket flush_pkt;
|
|
|
|
VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
|
|
int pictq_size, pictq_rindex, pictq_windex;
|
|
Mutex pictq_mutex;
|
|
ConditionVariable pictq_cond;
|
|
|
|
SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
|
|
int subpq_size, subpq_rindex, subpq_windex;
|
|
Mutex subpq_mutex;
|
|
ConditionVariable subpq_cond;
|
|
|
|
AVStream *audioStream, *videoStream, *subtitleStream;
|
|
|
|
AVAudioConvert *reformat_ctx;
|
|
|
|
Thread video_tid, decoderThreadId, /*refresh_tid,*/ subtitle_tid;
|
|
|
|
int subtitle_stream_changed;
|
|
int debug, debug_mv, workaround_bugs;
|
|
int lowres;
|
|
bool fast;
|
|
int genpts;
|
|
int idct;
|
|
enum AVDiscard skip_frame, skip_idct, skip_loop_filter;
|
|
int decoder_reorder_pts;
|
|
|
|
int64_t audio_callback_time;
|
|
|
|
// Samples output by the codec. we reserve more space for avsync compensation
|
|
DECLARE_ALIGNED(16,uint8_t,audio_buf1)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
|
|
DECLARE_ALIGNED(16,uint8_t,audio_buf2)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
|
|
uint8_t *audio_buf;
|
|
unsigned int audio_buf_size; // In bytes
|
|
int audio_buf_index; // In bytes
|
|
|
|
bool showAudio; // if true, display audio samples in graphs
|
|
double showAudioFps;
|
|
double lastAudioShow;
|
|
|
|
int16_t sample_array[SAMPLE_ARRAY_SIZE];
|
|
int sample_array_index;
|
|
|
|
double audio_clock;
|
|
double audio_diff_cum; // used for AV difference average computation
|
|
double audio_diff_avg_coef;
|
|
double audio_diff_threshold;
|
|
int audio_diff_avg_count;
|
|
int audio_hw_buf_size;
|
|
|
|
enum SampleFormat audio_src_fmt;
|
|
|
|
AVPacket audio_pkt, audio_pkt_temp;
|
|
|
|
double video_current_pts; //Current displayed pts (different from video_clock if frame fifos are used)
|
|
int64_t video_current_pts_time; //Time (GetUSec) at which we updated video_current_pts - used to have running video pts
|
|
int64_t video_current_pos; //Current displayed file pos
|
|
|
|
int av_sync_type;
|
|
TimeStop externalClock;
|
|
double video_clock; // pts of last decoded frame / predicted pts of next decoded frame
|
|
|
|
double frame_timer;
|
|
bool step; // Jump to next frame
|
|
|
|
String strError;
|
|
String GetError() {return strError;};
|
|
void SetError(String str);
|
|
void ResetError() {strError = "";};
|
|
|
|
AtomicVar rgb; // Is the image YUV or RGB
|
|
bool forceAspect; // Force aspect ratio
|
|
Rect imgRect; // Image size
|
|
Mutex mtx;
|
|
|
|
AtomicVar audioFactor;
|
|
};
|
|
|
|
|
|
#endif
|