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