ultimatepp/bazaar/Media/MediaFile.h
koldo 8a16fa8788 Media: Update.
git-svn-id: svn://ultimatepp.org/upp/trunk@3785 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2011-08-25 21:18:55 +00:00

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