00001 #include <stdlib.h>
00002 #include <pthread.h>
00003
00004 #include <qmap.h>
00005 #include <qptrlist.h>
00006 #include <qptrqueue.h>
00007 #include <qvaluelist.h>
00008 #include <qstringlist.h>
00009 #include <qdatetime.h>
00010
00011 #include "transcodedefs.h"
00012
00013 extern "C"
00014 {
00015
00016 #include "libavcodec/avcodec.h"
00017 #include "libavformat/avformat.h"
00018
00019
00020 #include "replex/ringbuffer.h"
00021 #include "replex/multiplex.h"
00022
00023
00024 #include "libmythmpeg2/mpeg2.h"
00025 }
00026
00027 enum MPFDisplayMask {
00028 MPF_IMPORTANT = 0x0001,
00029 MPF_GENERAL = 0x0002,
00030 MPF_PROCESS = 0x0004,
00031 MPF_FRAME = 0x0008,
00032 MPF_RPLXQUEUE = 0x0010,
00033 MPF_DECODE = 0x0020,
00034 };
00035
00036 enum MPFListType {
00037 MPF_TYPE_CUTLIST = 0,
00038 MPF_TYPE_SAVELIST,
00039 };
00040
00041 class MPEG2frame
00042 {
00043 public:
00044 MPEG2frame(int size)
00045 {
00046 pkt.data = (uint8_t *)malloc(size);
00047 pkt_memsize = size;
00048 }
00049 ~MPEG2frame()
00050 {
00051 free(pkt.data);
00052 }
00053 void ensure_size(int size)
00054 {
00055 if (pkt_memsize < size)
00056 {
00057 pkt.data = (uint8_t *)realloc(pkt.data, size);
00058 pkt_memsize = size;
00059 }
00060 }
00061 void set_pkt(AVPacket *newpkt)
00062 {
00063 ensure_size(newpkt->size);
00064 uint8_t *data = pkt.data;
00065 pkt = *newpkt;
00066 pkt.data = data;
00067 memcpy(pkt.data, newpkt->data, newpkt->size);
00068 }
00069
00070 AVPacket pkt;
00071 int pkt_memsize;
00072 bool isSequence;
00073 bool isGop;
00074 uint8_t *framePos;
00075 uint8_t *gopPos;
00076 mpeg2_sequence_t mpeg2_seq;
00077 mpeg2_gop_t mpeg2_gop;
00078 mpeg2_picture_t mpeg2_pic;
00079 };
00080
00081 typedef struct {
00082 int64_t newPTS;
00083 int64_t pos_pts;
00084 int framenum;
00085 bool type;
00086 } poq_idx_t;
00087
00088 class PTSOffsetQueue
00089 {
00090 public:
00091 PTSOffsetQueue(int vidid, QValueList<int> keys, int64_t initPTS);
00092 void SetNextPTS(int64_t newPTS, int64_t atPTS);
00093 void SetNextPos(int64_t newPTS, AVPacket &pkt);
00094 int64_t Get(int idx, AVPacket *pkt);
00095 int64_t UpdateOrigPTS(int idx, int64_t &origPTS, AVPacket &pkt);
00096 private:
00097 QMap<int, QValueList<poq_idx_t> > offset;
00098 QMap<int, QValueList<poq_idx_t> > orig;
00099 QValueList<int> keyList;
00100 int vid_id;
00101 };
00102
00103
00104 class MPEG2replex
00105 {
00106 public:
00107 MPEG2replex();
00108 ~MPEG2replex();
00109 void Start();
00110 int WaitBuffers();
00111 int done;
00112 QString outfile;
00113 int otype;
00114 ringbuffer vrbuf;
00115 ringbuffer extrbuf[N_AUDIO];
00116 ringbuffer index_vrbuf;
00117 ringbuffer index_extrbuf[N_AUDIO];
00118 int ext_count;
00119 int exttype[N_AUDIO];
00120 int exttypcnt[N_AUDIO];
00121
00122 pthread_mutex_t mutex;
00123 pthread_cond_t cond;
00124 audio_frame_t extframe[N_AUDIO];
00125 sequence_t seq_head;
00126
00127 private:
00128 multiplex_t *mplex;
00129 };
00130
00131 class MPEG2fixup
00132 {
00133 public:
00134 MPEG2fixup(const char *inf, const char *outf,
00135 QMap<long long, int> *deleteMap, const char *fmt, int norp,
00136 int fixPTS, int maxf, bool showprog, int otype,
00137 void (*update_func)(float) = NULL, int (*check_func)() = NULL);
00138 ~MPEG2fixup();
00139 int Start();
00140 void AddRangeList(QStringList cutlist, int type);
00141 void ShowRangeMap(QMap<long long, int> *mapPtr, QString msg);
00142 int BuildKeyframeIndex(QString &file, QMap<long long, long long> &posMap);
00143
00144
00145 static void dec2x33(int64_t *pts1, int64_t pts2);
00146 static void inc2x33(int64_t *pts1, int64_t pts2);
00147 static int64_t udiff2x33(int64_t pts1, int64_t pts2);
00148 static int64_t diff2x33(int64_t pts1, int64_t pts2);
00149 static int64_t add2x33(int64_t pts1, int64_t pts2);
00150 static int cmp2x33(int64_t pts1, int64_t pts2);
00151
00152 protected:
00153 static void *ReplexStart(void *data);
00154 MPEG2replex rx;
00155
00156 private:
00157 int FindMPEG2Header(uint8_t *buf, int size, uint8_t code);
00158 void InitReplex();
00159 void FrameInfo(MPEG2frame *f);
00160 int AddFrame(MPEG2frame *f);
00161 int InitAV(const char *inputfile, const char *type, int64_t offset);
00162 void ScanAudio();
00163 bool ProcessVideo(MPEG2frame *vf, mpeg2dec_t *dec);
00164 void WriteFrame(const char *filename, MPEG2frame *f);
00165 void WriteFrame(const char *filename, AVPacket *pkt);
00166 void WriteYUV(const char *filename, const mpeg2_info_t *info);
00167 void WriteData(const char *filename, uint8_t *data, int size);
00168 int BuildFrame(AVPacket *pkt, QString fname);
00169 MPEG2frame *GetPoolFrame(AVPacket *pkt);
00170 MPEG2frame *GetPoolFrame(MPEG2frame *f);
00171 int GetFrame(AVPacket *pkt);
00172 bool FindStart();
00173 void SetRepeat(MPEG2frame *vf, int nb_fields, bool topff);
00174 void SetRepeat(uint8_t *ptr, int size, int fields, bool topff);
00175 MPEG2frame *FindFrameNum(int frameNum);
00176 void RenumberFrames(int frame_pos, int delta);
00177 void StoreSecondary();
00178 int PlaybackSecondary();
00179 MPEG2frame *DecodeToFrame(int frameNum, int skip_reset);
00180 int ConvertToI(QPtrList<MPEG2frame> *orderedFrames, int headPos);
00181 int InsertFrame(int frameNum, int64_t deltaPTS,
00182 int64_t ptsIncrement, int64_t initPTS);
00183 void AddSequence(MPEG2frame *frame1, MPEG2frame *frame2);
00184 QPtrList<MPEG2frame> ReorderDTStoPTS(QPtrList<MPEG2frame> *dtsOrder);
00185 void InitialPTSFixup(MPEG2frame *curFrame, int64_t &origvPTS,
00186 int64_t &PTSdiscrep, int numframes, bool fix);
00187 void SetFrameNum(uint8_t *ptr, int num);
00188 int GetFrameNum(MPEG2frame *frame)
00189 {
00190 return frame->mpeg2_pic.temporal_reference;
00191 }
00192 int GetFrameTypeN(MPEG2frame *frame)
00193 {
00194 return frame->mpeg2_pic.flags & PIC_MASK_CODING_TYPE;
00195 }
00196 char GetFrameTypeT(MPEG2frame *frame)
00197 {
00198 int type = GetFrameTypeN(frame);
00199 return (type == 1 ? 'I' :
00200 (type == 2 ? 'P' : (type == 3 ? 'B' : 'X')));
00201 }
00202 int GetNbFields(MPEG2frame *frame)
00203 {
00204 return frame->mpeg2_pic.nb_fields;
00205 }
00206 int GetStreamType(int id)
00207 {
00208 return (inputFC->streams[id]->codec->codec_id == CODEC_ID_AC3) ?
00209 CODEC_ID_AC3 : CODEC_ID_MP2;
00210 }
00211 AVCodecContext *getCodecContext(int id)
00212 {
00213 return inputFC->streams[id]->codec;
00214 }
00215
00216 int (*check_abort)();
00217 void (*update_status)(float percent_done);
00218
00219 QPtrList<MPEG2frame> vSecondary;
00220 bool use_secondary;
00221
00222 QPtrList<MPEG2frame> vFrame;
00223 QMap<int, QPtrList<MPEG2frame> > aFrame;
00224 QPtrQueue<MPEG2frame> framePool;
00225 QPtrQueue<MPEG2frame> unreadFrames;
00226 QPtrListIterator<MPEG2frame> *displayFrame;
00227 mpeg2dec_t *header_decoder;
00228 mpeg2dec_t *img_decoder;
00229
00230 QMap<long long, int> delMap;
00231 QMap<long long, int> saveMap;
00232
00233 pthread_t thread;
00234
00235 AVFormatContext *inputFC;
00236 int vid_id;
00237 int ext_count;
00238 QMap <int, int> aud_map;
00239 int aud_stream_count;
00240 int64_t ptsIncrement;
00241 int64_t ptsOffset;
00242
00243 int discard;
00244
00245 int no_repeat, fix_PTS, maxframes;
00246 QString infile;
00247 const char *format;
00248
00249
00250 bool file_end;
00251 bool real_file_end;
00252
00253
00254 QDateTime statustime;
00255 bool showprogress;
00256 uint64_t filesize;
00257 int framenum;
00258 int status_update_time;
00259 uint64_t last_written_pos;
00260 };
00261
00262 #ifdef NO_MYTH
00263 #include <qdatetime.h>
00264 #include <iostream>
00265
00266 using namespace std;
00267
00268 extern int print_verbose_messages;
00269 #define VERBOSE(mask,args...) \
00270 do { \
00271 if ((print_verbose_messages & mask) != 0) \
00272 { \
00273 cout << args << endl; \
00274 } \
00275 } while (0)
00276 #define TRANSCODE_EXIT_OK 0
00277 #define TRANSCODE_EXIT_UNKNOWN_ERROR -10
00278 #define TRANSCODE_BUGGY_EXIT_WRITE_FRAME_ERROR -11
00279 #define TRANSCODE_BUGGY_EXIT_DEADLOCK -12
00280 #else
00281 #include "mythcontext.h"
00282 #include "exitcodes.h"
00283 #endif