00001
00002
00003
00004
00005
00006
00007
00008 #ifndef VIDEOFILE_H_
00009 #define VIDEOFILE_H_
00010
00011 extern "C" {
00012 #include <libavformat/avformat.h>
00013 #include <libswscale/swscale.h>
00014 }
00015
00016 #include <QObject>
00017 #include <QThread>
00018 #include <QMutex>
00019 #include <QWaitCondition>
00020 #include <QTimer>
00021
00025 #define VIDEO_PICTURE_QUEUE_SIZE 4
00026
00030 #define SEEK_STEP 0.05
00031
00048 class VideoPicture {
00049 friend class VideoFile;
00050 AVFrame *rgb;
00051 int width, height;
00052 bool allocated;
00053 double pts;
00054 enum PixelFormat pixelformat;
00055 public:
00056
00057 VideoPicture() :
00058 rgb(NULL), width(0), height(0), allocated(false), pts(0.0) {
00059 }
00060
00061 ~VideoPicture();
00066 VideoPicture& operator=(VideoPicture const &original);
00078 bool allocate(int w, int h, enum PixelFormat format = PIX_FMT_RGB24);
00094 inline char *getBuffer() const {
00095 return (allocated ? (char*) rgb->data[0] : NULL);
00096 }
00102 inline int getWidth() const {
00103 return width;
00104 }
00110 inline int getHeight() const {
00111 return height;
00112 }
00118 inline bool isAllocated() const {
00119 return (allocated && (rgb != NULL));
00120 }
00124 void saveToPPM(QString filename = "videoPicture.ppm") const;
00141 enum PixelFormat getFormat() const {
00142 return pixelformat;
00143 }
00144 };
00145
00146 class ParsingThread;
00147 class DecodingThread;
00148
00196 class VideoFile: public QObject {
00197 Q_OBJECT
00198
00199 friend class ParsingThread;
00200 friend class DecodingThread;
00201
00202 public:
00203
00208 typedef enum {
00209 SPEED_QUARTER = 0, SPEED_THIRD, SPEED_HALF, SPEED_NORMAL, SPEED_DOUBLE, SPEED_TRIPLE
00210 } PlaySpeed;
00243 VideoFile(QObject *parent = 0, bool generatePowerOfTwo = false,
00244 int swsConversionQuality = SWS_POINT, enum PixelFormat avFormat = PIX_FMT_RGB24,
00245 int destinationWidth = 0, int destinationHeight = 0);
00251 ~VideoFile();
00273 const VideoPicture *getPictureAtIndex(int index) const;
00279 inline bool isOpen() const {
00280 return (pFormatCtx != NULL);
00281 }
00287 inline bool isRunning() const {
00288 return !quit;
00289 }
00295 inline bool isPaused() const {
00296 return pause_video;
00297 }
00305 inline bool isLoop() const {
00306 return loop_video;
00307 }
00313 inline const char *getFileName() const {
00314 return filename.toUtf8().data();
00315 }
00321 inline QString getCodecName() const {
00322 return codecname;
00323 }
00331 inline int getFrameWidth() const {
00332 return targetWidth;
00333 }
00341 inline int getFrameHeight() const {
00342 return targetHeight;
00343 }
00349 inline int getStreamFrameWidth() const {
00350 if (video_st)
00351 return video_st->codec->width;
00352 else
00353 return targetWidth;
00354 }
00360 inline int getStreamFrameHeight() const {
00361 if (video_st)
00362 return video_st->codec->height;
00363 else
00364 return targetWidth;
00365 }
00371 float getStreamAspectRatio() const;
00380 inline float getFrameRate() const {
00381
00382 if (video_st && video_st->r_frame_rate.den > 0)
00383 return ((float) (video_st->r_frame_rate.num )/ (float) video_st->r_frame_rate.den);
00384 else
00385 return 0;
00386 }
00392 double getDuration() const;
00398 int64_t getBegin() const;
00404 int64_t getEnd() const;
00410 int64_t getCurrentFrameTime() const;
00416 inline int64_t getMarkIn() const {
00417 return mark_in;
00418 }
00424 void setMarkIn(int64_t t);
00430 inline int64_t getMarkOut() const {
00431 return mark_out;
00432 }
00438 void setMarkOut(int64_t t);
00446 void seekToPosition(int64_t t);
00454 void seekBySeconds(double ss);
00462 void seekByFrames(int64_t ss);
00469 QString getTimeFromFrame(int64_t t) const;
00476 int64_t getFrameFromTime(QString t) const;
00480 static void displayFormatsCodecsInformation();
00481
00482 signals:
00488 void frameReady(int id);
00494 void running(bool run);
00500 void paused(bool p);
00504 void markingChanged();
00511 void info(QString msg);
00518 void error(QString msg);
00519
00520 public slots:
00531 bool open(QString file, int64_t markIn = 0, int64_t markOut = 0);
00544 void start();
00558 void stop();
00567 void play(bool startorstop);
00579 void pause(bool pause);
00583 inline void resetMarkIn() {
00584 setMarkIn(getBegin());
00585 }
00589 inline void resetMarkOut() {
00590 setMarkOut(getEnd());
00591 }
00595 inline void setMarkIn() {
00596 setMarkIn(getCurrentFrameTime());
00597 }
00601 inline void setMarkOut() {
00602 setMarkOut(getCurrentFrameTime());
00603 }
00611 void setLoop(bool loop) {
00612 loop_video = loop;
00613 }
00631 void setPlaySpeed(int playspeed);
00636 inline void seekBackward() {
00637 seekByFrames(-SEEK_STEP * getEnd());
00638 }
00643 inline void seekForward() {
00644 seekByFrames(SEEK_STEP * getEnd());
00645 }
00650 inline void seekBegin() {
00651 seekToPosition(getBegin());
00652 }
00667 void setOptionAllowDirtySeek(bool dirty);
00675 void setOptionRestartToMarkIn(bool on) {
00676 restart_where_stopped = !on;
00677 }
00686 void setOptionRevertToBlackWhenStop(bool black);
00687
00688 protected slots:
00692 void video_refresh_timer();
00696 void thread_terminated();
00697
00698 protected:
00699
00704 class PacketQueue {
00705 AVPacketList *first_pkt, *last_pkt;
00706 static AVPacket *flush_pkt;
00707 int nb_packets;
00708 int size;
00709 QMutex *mutex;
00710 QWaitCondition *cond;
00711
00712 public:
00713
00714 PacketQueue();
00715 ~PacketQueue();
00716
00717 bool get(AVPacket *pkt, bool block);
00718 bool put(AVPacket *pkt);
00719 void flush();
00720 bool isFlush(AVPacket *pkt);
00721 bool isFull();
00722
00723 };
00724
00725
00726 double get_clock();
00727 void reset();
00728 void parse_decode_update(int64_t t);
00729 void fill_first_frame(bool);
00730 int stream_component_open(AVFormatContext *);
00731 double synchronize_video(AVFrame *src_frame, double pts);
00732 void queue_picture(AVFrame *pFrame, double pts);
00733 static int roundPowerOfTwo(int v);
00734
00735
00736 QString filename;
00737 QString codecname;
00738 QString logmessage;
00739
00740
00741 AVFormatContext *pFormatCtx;
00742 AVStream *video_st;
00743 SwsContext *img_convert_ctx;
00744 int videoStream;
00745 PacketQueue videoq;
00746
00747
00748 bool seek_req, seek_backward, seek_any;
00749 int64_t seek_pos;
00750 int64_t mark_in;
00751 int64_t mark_out;
00752 int64_t mark_stop;
00753
00754
00755 double frame_timer;
00756 double frame_last_pts;
00757 double frame_last_delay;
00758 double video_clock;
00759 double video_current_pts;
00760 int64_t video_current_pts_time;
00761
00762 QTimer *ptimer;
00763 int64_t last_time, last_virtual_time;
00764 double play_speed;
00765
00766
00767 VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
00768 int pictq_size, pictq_rindex, pictq_windex;
00769 QMutex *pictq_mutex;
00770 QWaitCondition *pictq_cond;
00771 int conversionAlgorithm;
00772 int targetWidth, targetHeight;
00773 enum PixelFormat targetFormat;
00774 bool powerOfTwo;
00775 VideoPicture firstPicture, blackPicture;
00776 VideoPicture *resetPicture;
00777
00778
00779 ParsingThread *parse_tid;
00780 DecodingThread *decod_tid;
00781 bool quit;
00782 bool loop_video;
00783 bool pause_video;
00784 bool pause_video_last;
00785 bool restart_where_stopped;
00786
00787
00788 static bool ffmpegregistered;
00789
00790 };
00791
00792 #endif