00001
00002
00003
00004
00005
00006 #include <cstdlib>
00007 #include <cstdio>
00008
00009
00010 #include <fcntl.h>
00011 #include <unistd.h>
00012 #include <getopt.h>
00013 #include <stdint.h>
00014 #include <sys/stat.h>
00015
00016 #include "config.h"
00017 #include "mpeg2fix.h"
00018
00019 #include <QList>
00020 #include <QQueue>
00021 #include <QMap>
00022 #include <QFileInfo>
00023
00024 #include "mythlogging.h"
00025 #include "mthread.h"
00026
00027 #ifdef USING_MINGW
00028 #include <winsock2.h>
00029 #else
00030 #include <netinet/in.h>
00031 #endif
00032
00033 #ifndef O_LARGEFILE
00034 #define O_LARGEFILE 0
00035 #endif
00036
00037 #define ATTR_ALIGN(align) __attribute__ ((__aligned__ (align)))
00038
00039 static void *my_malloc(unsigned size, mpeg2_alloc_t reason)
00040 {
00041 (void)reason;
00042 char * buf;
00043
00044 if (size)
00045 {
00046 buf = (char *) malloc (size + 63 + sizeof (void **));
00047 if (buf)
00048 {
00049 char * align_buf;
00050 memset(buf, 0, size + 63 + sizeof (void **));
00051 align_buf = buf + 63 + sizeof (void **);
00052 align_buf -= (long)align_buf & 63;
00053 *(((void **)align_buf) - 1) = buf;
00054 return align_buf;
00055 }
00056 }
00057
00058 return NULL;
00059 }
00060
00061 static void my_av_print(void *ptr, int level, const char* fmt, va_list vl)
00062 {
00063 (void) ptr;
00064
00065 static QString full_line("");
00066 char str[256];
00067
00068 if (level > AV_LOG_INFO)
00069 return;
00070 vsprintf(str, fmt, vl);
00071
00072 full_line += QString(str);
00073 if (full_line.endsWith("\n"))
00074 {
00075 full_line.truncate(full_line.length() - 1);
00076 LOG(VB_GENERAL, LOG_INFO, full_line);
00077 full_line = QString("");
00078 }
00079 }
00080
00081 static QString PtsTime(int64_t pts)
00082 {
00083 bool is_neg = false;
00084 if (pts < 0)
00085 {
00086 pts = -pts;
00087 is_neg = true;
00088 }
00089 QString msg;
00090 return(msg.sprintf("%s%02d:%02d:%02d.%03d", (is_neg) ? "-" : "",
00091 (unsigned int)(pts / 90000.) / 3600,
00092 ((unsigned int)(pts / 90000.) % 3600) / 60,
00093 ((unsigned int)(pts / 90000.) % 3600) % 60,
00094 (((unsigned int)(pts / 90.) % 3600000) % 60000) % 1000));
00095 }
00096
00097 PTSOffsetQueue::PTSOffsetQueue(int vidid, QList<int> keys, int64_t initPTS)
00098 {
00099 QList<int>::iterator it;
00100 poq_idx_t idx;
00101 vid_id = vidid;
00102 keyList = keys;
00103 keyList.append(vid_id);
00104
00105 idx.newPTS = initPTS;
00106 idx.pos_pts = 0;
00107 idx.framenum = 0;
00108 idx.type = 0;
00109
00110 for (it = keyList.begin(); it != keyList.end(); ++it)
00111 offset[*it].push_back(idx);
00112 }
00113
00114 int64_t PTSOffsetQueue::Get(int idx, AVPacket *pkt)
00115 {
00116 QList<poq_idx_t>::iterator it;
00117 int64_t value = offset[idx].first().newPTS;
00118 bool done = false;
00119
00120 if (!pkt)
00121 return value;
00122
00123
00124
00125 while (offset[idx].count() > 1 && !done)
00126 {
00127 it = ++offset[idx].begin();
00128 if ((((*it).type == 0) && (pkt->pts >= (*it).pos_pts) ) ||
00129 (((*it).type == 1) &&
00130 ((pkt->pos >= (*it).pos_pts) || (pkt->duration > (*it).framenum))))
00131 {
00132 offset[idx].pop_front();
00133 value = offset[idx].first().newPTS;
00134 }
00135 else
00136 done = true;
00137 }
00138 return value;
00139 }
00140
00141 void PTSOffsetQueue::SetNextPTS(int64_t newPTS, int64_t atPTS)
00142 {
00143 QList<int>::iterator it;
00144 poq_idx_t idx;
00145
00146 idx.newPTS = newPTS;
00147 idx.pos_pts = atPTS;
00148 idx.type = 0;
00149 idx.framenum = 0;
00150
00151 for (it = keyList.begin(); it != keyList.end(); ++it)
00152 offset[*it].push_back(idx);
00153 }
00154
00155 void PTSOffsetQueue::SetNextPos(int64_t newPTS, AVPacket &pkt)
00156 {
00157 QList<int>::iterator it;
00158 int64_t delta = MPEG2fixup::diff2x33(newPTS, offset[vid_id].last().newPTS);
00159 poq_idx_t idx;
00160
00161 idx.pos_pts = pkt.pos;
00162 idx.framenum = pkt.duration;
00163 idx.type = 1;
00164
00165 LOG(VB_FRAME, LOG_INFO, QString("Offset %1 -> %2 (%3) at %4")
00166 .arg(PtsTime(offset[vid_id].last().newPTS))
00167 .arg(PtsTime(newPTS)).arg(PtsTime(delta)).arg(pkt.pos));
00168 for (it = keyList.begin(); it != keyList.end(); ++it)
00169 {
00170 idx.newPTS = newPTS;
00171 offset[*it].push_back(idx);
00172 idx.newPTS = delta;
00173 orig[*it].push_back(idx);
00174 }
00175 }
00176
00177 int64_t PTSOffsetQueue::UpdateOrigPTS(int idx, int64_t &origPTS, AVPacket &pkt)
00178 {
00179 int64_t delta = 0;
00180 QList<poq_idx_t> *dltaList = &orig[idx];
00181 while (dltaList->count() &&
00182 (pkt.pos >= dltaList->first().pos_pts ||
00183 pkt.duration > dltaList->first().framenum))
00184 {
00185 if (dltaList->first().newPTS >= 0)
00186 ptsinc((uint64_t *)&origPTS, 300 * dltaList->first().newPTS);
00187 else
00188 ptsdec((uint64_t *)&origPTS, -300 * dltaList->first().newPTS);
00189 delta += dltaList->first().newPTS;
00190 dltaList->pop_front();
00191 LOG(VB_PROCESS, LOG_INFO,
00192 QString("Moving PTS offset of stream %1 by %2")
00193 .arg(idx).arg(PtsTime(delta)));
00194 }
00195 return (delta);
00196 }
00197
00198 MPEG2fixup::MPEG2fixup(const QString &inf, const QString &outf,
00199 frm_dir_map_t *deleteMap,
00200 const char *fmt, int norp, int fixPTS, int maxf,
00201 bool showprog, int otype, void (*update_func)(float),
00202 int (*check_func)())
00203 {
00204 displayFrame = 0;
00205
00206 infile = inf;
00207 rx.outfile = outf;
00208 rx.done = 0;
00209 format = fmt;
00210 no_repeat = norp;
00211 fix_PTS = fixPTS;
00212 maxframes = maxf;
00213 rx.otype = otype;
00214
00215 real_file_end = file_end = false;
00216
00217 use_secondary = false;
00218 framenum = 0;
00219 discard = 0;
00220 if (deleteMap && deleteMap->count())
00221 {
00222 delMap = *deleteMap;
00223 if (delMap.contains(0))
00224 {
00225 discard = 1;
00226 delMap.remove(0);
00227 }
00228 if (delMap.begin().value() == MARK_CUT_END)
00229 discard = 1;
00230 use_secondary = true;
00231 }
00232
00233 ext_count = 0;
00234 vid_id = -1;
00235 mpeg2_malloc_hooks(my_malloc, NULL);
00236 header_decoder = mpeg2_init();
00237 img_decoder = mpeg2_init();
00238
00239 av_register_all();
00240 av_log_set_callback(my_av_print);
00241
00242 pthread_mutex_init(&rx.mutex, NULL);
00243 pthread_cond_init(&rx.cond, NULL);
00244
00245
00246 pthread_mutex_lock(&rx.mutex);
00247 pthread_create(&thread, NULL, ReplexStart, this);
00248 pthread_cond_wait(&rx.cond, &rx.mutex);
00249 pthread_mutex_unlock(&rx.mutex);
00250
00251
00252 showprogress = showprog;
00253 update_status = update_func;
00254 check_abort = check_func;
00255 if (showprogress || update_status)
00256 {
00257 if (update_status)
00258 {
00259 status_update_time = 20;
00260 update_status(0);
00261 }
00262 else
00263 status_update_time = 5;
00264 statustime = QDateTime::currentDateTime();
00265 statustime = statustime.addSecs(status_update_time);
00266
00267 const QFileInfo finfo(inf);
00268 filesize = finfo.size();
00269 }
00270 }
00271
00272 MPEG2fixup::~MPEG2fixup()
00273 {
00274 mpeg2_close(header_decoder);
00275 mpeg2_close(img_decoder);
00276
00277 if (inputFC)
00278 avformat_close_input(&inputFC);
00279
00280 MPEG2frame *tmpFrame;
00281
00282 while (vFrame.count())
00283 {
00284 tmpFrame = vFrame.takeFirst();
00285 delete tmpFrame;
00286 }
00287
00288 while (vSecondary.count())
00289 {
00290 tmpFrame = vSecondary.takeFirst();
00291 delete tmpFrame;
00292 }
00293
00294 for (FrameMap::Iterator it = aFrame.begin(); it != aFrame.end(); it++)
00295 {
00296 FrameList *af = (*it);
00297 while (af->count())
00298 {
00299 tmpFrame = af->takeFirst();
00300 delete tmpFrame;
00301 }
00302 delete af;
00303 }
00304
00305 while (framePool.count())
00306 delete framePool.dequeue();
00307 }
00308
00309
00310 #define MATCH_HEADER(ptr) (((ptr)[0] == 0x00) && ((ptr)[1] == 0x00) && ((ptr)[2] == 0x01))
00311
00312 static void SETBITS(unsigned char *ptr, long value, int num)
00313 {
00314 static int sb_pos;
00315 static unsigned char *sb_ptr = 0;
00316 uint32_t sb_long, mask;
00317 int offset, offset_r, offset_b;
00318
00319 if (ptr != 0)
00320 {
00321 sb_ptr = ptr;
00322 sb_pos = 0;
00323 }
00324
00325 offset = sb_pos >> 3;
00326 offset_r = sb_pos & 0x07;
00327 offset_b = 32 - offset_r;
00328 mask = ~(((1 << num) - 1) << (offset_b - num));
00329 sb_long = ntohl(*((uint32_t *) (sb_ptr + offset)));
00330 value = value << (offset_b - num);
00331 sb_long = (sb_long & mask) + value;
00332 *((uint32_t *)(sb_ptr + offset)) = htonl(sb_long);
00333 }
00334
00335 void MPEG2fixup::dec2x33(int64_t *pts1, int64_t pts2)
00336 {
00337 *pts1 = udiff2x33(*pts1, pts2);
00338 }
00339
00340 void MPEG2fixup::inc2x33(int64_t *pts1, int64_t pts2)
00341 {
00342 *pts1 = (*pts1 + pts2) % MAX_PTS;
00343 }
00344
00345 int64_t MPEG2fixup::udiff2x33(int64_t pts1, int64_t pts2)
00346 {
00347 int64_t diff;
00348
00349 diff = pts1 - pts2;
00350
00351 if (diff < 0){
00352 diff = MAX_PTS + diff;
00353 }
00354 return (diff % MAX_PTS);
00355 }
00356
00357 int64_t MPEG2fixup::diff2x33(int64_t pts1, int64_t pts2)
00358 {
00359 switch (cmp2x33(pts1, pts2))
00360 {
00361 case 0:
00362 return 0;
00363 break;
00364
00365 case 1:
00366 case -2:
00367 return (pts1 - pts2);
00368 break;
00369
00370 case 2:
00371 return (pts1 + MAX_PTS - pts2);
00372 break;
00373
00374 case -1:
00375 return (pts1 - (pts2 + MAX_PTS));
00376 break;
00377 }
00378
00379 return 0;
00380 }
00381
00382 int64_t MPEG2fixup::add2x33(int64_t pts1, int64_t pts2)
00383 {
00384 int64_t tmp = pts1 + pts2;
00385 if (tmp >= 0)
00386 return (pts1 + pts2) % MAX_PTS;
00387 return (tmp + MAX_PTS);
00388 }
00389
00390 int MPEG2fixup::cmp2x33(int64_t pts1, int64_t pts2)
00391 {
00392 int ret;
00393
00394 if (pts1 > pts2)
00395 {
00396 if ((uint64_t)(pts1 - pts2) > MAX_PTS/2)
00397 ret = -1;
00398 else
00399 ret = 1;
00400 }
00401 else if (pts1 == pts2)
00402 ret = 0;
00403 else
00404 {
00405 if ((uint64_t)(pts2 - pts1) > MAX_PTS/2)
00406 ret = 2;
00407 else
00408 ret = -2;
00409 }
00410 return ret;
00411 }
00412
00413 int MPEG2fixup::FindMPEG2Header(uint8_t *buf, int size, uint8_t code)
00414 {
00415 int i;
00416
00417 for (i = 0; i < size; i++)
00418 {
00419 if (MATCH_HEADER(buf + i) && buf[i + 3] == code)
00420 return i;
00421 }
00422
00423 return 0;
00424 }
00425
00426
00427
00428
00429
00430 static int fill_buffers(void *r, int finish)
00431 {
00432 MPEG2replex *rx = (MPEG2replex *)r;
00433
00434 if (finish)
00435 return 0;
00436
00437 return (rx->WaitBuffers());
00438 }
00439
00440 MPEG2replex::MPEG2replex() :
00441 done(0), otype(0),
00442 ext_count(0), mplex(0)
00443 {
00444 memset(&vrbuf, 0, sizeof(vrbuf));
00445 memset(extrbuf, 0, sizeof(extrbuf));
00446 memset(&index_vrbuf, 0, sizeof(index_vrbuf));
00447 memset(index_extrbuf, 0, sizeof(index_extrbuf));
00448 memset(exttype, 0, sizeof(exttype));
00449 memset(exttypcnt, 0, sizeof(exttypcnt));
00450 memset(extframe, 0, sizeof(extframe));
00451 memset(&seq_head, 0, sizeof(seq_head));
00452 }
00453
00454 MPEG2replex::~MPEG2replex()
00455 {
00456 if (vrbuf.size)
00457 ring_destroy(&vrbuf);
00458 if (index_vrbuf.size)
00459 ring_destroy(&index_vrbuf);
00460
00461 for (int i = 0; i < ext_count; i++)
00462 {
00463 if (extrbuf[i].size)
00464 ring_destroy(&extrbuf[i]);
00465 if (index_extrbuf[i].size)
00466 ring_destroy(&index_extrbuf[i]);
00467 }
00468 }
00469
00470 int MPEG2replex::WaitBuffers()
00471 {
00472 pthread_mutex_lock( &mutex );
00473 while (1)
00474 {
00475 int i, ok = 1;
00476
00477 if (ring_avail(&index_vrbuf) < sizeof(index_unit))
00478 ok = 0;
00479
00480 for (i = 0; i < ext_count; i++)
00481 if (ring_avail(&index_extrbuf[i]) < sizeof(index_unit))
00482 ok = 0;
00483
00484 if (ok || done)
00485 break;
00486
00487 pthread_cond_signal(&cond);
00488 pthread_cond_wait(&cond, &mutex);
00489 }
00490 pthread_mutex_unlock(&mutex);
00491
00492 if (done)
00493 {
00494 finish_mpg(mplex);
00495 pthread_exit(NULL);
00496 }
00497
00498 return 0;
00499 }
00500
00501 void *MPEG2fixup::ReplexStart(void *data)
00502 {
00503 MThread::ThreadSetup("MPEG2Replex");
00504 MPEG2fixup *m2f = (MPEG2fixup *) data;
00505 m2f->rx.Start();
00506 MThread::ThreadCleanup();
00507 return NULL;
00508 }
00509
00510 void MPEG2replex::Start()
00511 {
00512 int start = 1;
00513 multiplex_t mx;
00514
00515
00516
00517
00518 int ext_ok[N_AUDIO];
00519 int video_ok = 0;
00520
00521
00522
00523
00524
00525 int video_delay = 0, audio_delay = 0;
00526 int fd_out;
00527
00528 memset(&mx, 0, sizeof(mx));
00529 memset(ext_ok, 0, sizeof(ext_ok));
00530
00531 mx.priv = (void *)this;
00532
00533 fd_out = open(outfile.toLocal8Bit().constData(),
00534 O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
00535
00536
00537 pthread_mutex_lock(&mutex);
00538 pthread_cond_signal(&cond);
00539 pthread_cond_wait(&cond, &mutex);
00540 pthread_mutex_unlock(&mutex);
00541
00542 mplex = &mx;
00543
00544 init_multiplex(&mx, &seq_head, extframe, exttype, exttypcnt,
00545 video_delay, audio_delay, fd_out, fill_buffers,
00546 &vrbuf, &index_vrbuf, extrbuf, index_extrbuf, otype);
00547 setup_multiplex(&mx);
00548
00549 while (1)
00550 {
00551 check_times( &mx, &video_ok, ext_ok, &start);
00552 write_out_packs( &mx, video_ok, ext_ok);
00553 }
00554 }
00555
00556 #define INDEX_BUF (sizeof(index_unit) * 200)
00557 void MPEG2fixup::InitReplex()
00558 {
00559
00560
00561
00562
00563
00564 uint32_t memsize = vFrame.first()->mpeg2_seq.width *
00565 vFrame.first()->mpeg2_seq.height * 10;
00566 ring_init(&rx.vrbuf, memsize);
00567 ring_init(&rx.index_vrbuf, INDEX_BUF);
00568
00569 memset(rx.exttype, 0, sizeof(rx.exttype));
00570 memset(rx.exttypcnt, 0, sizeof(rx.exttypcnt));
00571 int mp2_count = 0, ac3_count = 0;
00572 for (FrameMap::Iterator it = aFrame.begin(); it != aFrame.end(); it++)
00573 {
00574 int i = aud_map[it.key()];
00575 AVDictionaryEntry *metatag =
00576 av_dict_get(inputFC->streams[it.key()]->metadata,
00577 "language", NULL, 0);
00578 char *lang = metatag ? metatag->value : (char *)"";
00579 ring_init(&rx.extrbuf[i], memsize / 5);
00580 ring_init(&rx.index_extrbuf[i], INDEX_BUF);
00581 rx.extframe[i].set = 1;
00582 rx.extframe[i].bit_rate = getCodecContext(it.key())->bit_rate;
00583 rx.extframe[i].framesize = (*it)->first()->pkt.size;
00584 strncpy(rx.extframe[i].language, lang, 4);
00585 switch(GetStreamType(it.key()))
00586 {
00587 case CODEC_ID_MP2:
00588 case CODEC_ID_MP3:
00589 rx.exttype[i] = 2;
00590 rx.exttypcnt[i] = mp2_count++;
00591 break;
00592 case CODEC_ID_AC3:
00593 rx.exttype[i] = 1;
00594 rx.exttypcnt[i] = ac3_count++;
00595 break;
00596 }
00597 }
00598
00599
00600 rx.seq_head.bit_rate = vFrame.first()->mpeg2_seq.byte_rate / 50;
00601 rx.seq_head.frame_rate = (vFrame.first()->mpeg2_seq.frame_period +
00602 26999999ULL) / vFrame.first()->mpeg2_seq.frame_period;
00603
00604 rx.ext_count = ext_count;
00605 }
00606
00607 void MPEG2fixup::FrameInfo(MPEG2frame *f)
00608 {
00609 QString msg = QString("Id:%1 %2 V:%3").arg(f->pkt.stream_index)
00610 .arg(PtsTime(f->pkt.pts))
00611 .arg(ring_free(&rx.index_vrbuf) / sizeof(index_unit));
00612
00613 if (ext_count)
00614 {
00615 msg += " EXT:";
00616 for (int i = 0; i < ext_count; i++)
00617 msg += QString(" %2")
00618 .arg(ring_free(&rx.index_extrbuf[i]) / sizeof(index_unit));
00619 }
00620 LOG(VB_RPLXQUEUE, LOG_INFO, msg);
00621 }
00622
00623 int MPEG2fixup::AddFrame(MPEG2frame *f)
00624 {
00625 index_unit iu;
00626 ringbuffer *rb = 0, *rbi = 0;
00627 int id = f->pkt.stream_index;
00628
00629 memset(&iu, 0, sizeof(index_unit));
00630 iu.frame_start = 1;
00631
00632 if (id == vid_id)
00633 {
00634 rb = &rx.vrbuf;
00635 rbi = &rx.index_vrbuf;
00636 iu.frame = GetFrameTypeN(f);
00637 iu.seq_header = f->isSequence;
00638 iu.gop = f->isGop;
00639
00640 iu.gop_off = f->gopPos - f->pkt.data;
00641 iu.frame_off = f->framePos - f->pkt.data;
00642 iu.dts = f->pkt.dts * 300;
00643 }
00644 else if (GetStreamType(id) == CODEC_ID_MP2 ||
00645 GetStreamType(id) == CODEC_ID_MP3 ||
00646 GetStreamType(id) == CODEC_ID_AC3)
00647 {
00648 rb = &rx.extrbuf[aud_map[id]];
00649 rbi = &rx.index_extrbuf[aud_map[id]];
00650 iu.framesize = f->pkt.size;
00651 }
00652
00653 if (!rb || !rbi)
00654 {
00655 LOG(VB_GENERAL, LOG_ERR, "Ringbuffer pointers empty. No stream found");
00656 return 1;
00657 }
00658
00659 iu.active = 1;
00660 iu.length = f->pkt.size;
00661 iu.pts = f->pkt.pts * 300;
00662 pthread_mutex_lock( &rx.mutex );
00663
00664 FrameInfo(f);
00665 while (ring_free(rb) < (unsigned int)f->pkt.size ||
00666 ring_free(rbi) < sizeof(index_unit))
00667 {
00668 int i, ok = 1;
00669
00670 if (rbi != &rx.index_vrbuf &&
00671 ring_avail(&rx.index_vrbuf) < sizeof(index_unit))
00672 ok = 0;
00673
00674 for (i = 0; i < ext_count; i++)
00675 if (rbi != &rx.index_extrbuf[i] &&
00676 ring_avail(&rx.index_extrbuf[i]) < sizeof(index_unit))
00677 ok = 0;
00678
00679 if (!ok && ring_free(rb) < (unsigned int)f->pkt.size &&
00680 ring_free(rbi) >= sizeof(index_unit))
00681 {
00682
00683 unsigned int inc_size = 10 * (unsigned int)f->pkt.size;
00684 LOG(VB_GENERAL, LOG_NOTICE,
00685 QString("Increasing ringbuffer size by %1 to avoid deadlock")
00686 .arg(inc_size));
00687
00688 if (!ring_reinit(rb, rb->size + inc_size))
00689 ok = 1;
00690 }
00691 if (!ok)
00692 {
00693 pthread_mutex_unlock( &rx.mutex );
00694
00695 LOG(VB_GENERAL, LOG_ERR,
00696 "Deadlock detected. One buffer is full when "
00697 "the other is empty! Aborting");
00698 return 1;
00699 }
00700
00701 pthread_cond_signal(&rx.cond);
00702 pthread_cond_wait(&rx.cond, &rx.mutex);
00703
00704 FrameInfo(f);
00705 }
00706
00707 if (ring_write(rb, f->pkt.data, f->pkt.size)<0){
00708 pthread_mutex_unlock( &rx.mutex );
00709 LOG(VB_GENERAL, LOG_ERR,
00710 QString("Ring buffer overflow %1").arg(rb->size));
00711 return 1;
00712 }
00713
00714 if (ring_write(rbi, (uint8_t *)&iu, sizeof(index_unit))<0){
00715 pthread_mutex_unlock( &rx.mutex );
00716 LOG(VB_GENERAL, LOG_ERR,
00717 QString("Ring buffer overflow %1").arg(rbi->size));
00718 return 1;
00719 }
00720 pthread_mutex_unlock(&rx.mutex);
00721 last_written_pos = f->pkt.pos;
00722 return 0;
00723 }
00724
00725 bool MPEG2fixup::InitAV(QString inputfile, const char *type, int64_t offset)
00726 {
00727 int ret;
00728 QByteArray ifarray = inputfile.toLocal8Bit();
00729 const char *ifname = ifarray.constData();
00730
00731 AVInputFormat *fmt = NULL;
00732
00733 if (type)
00734 fmt = av_find_input_format(type);
00735
00736
00737 LOG(VB_GENERAL, LOG_INFO, QString("Opening %1").arg(inputfile));
00738
00739 inputFC = NULL;
00740
00741 ret = avformat_open_input(&inputFC, ifname, fmt, NULL);
00742 if (ret)
00743 {
00744 LOG(VB_GENERAL, LOG_ERR,
00745 QString("Couldn't open input file, error #%1").arg(ret));
00746 return false;
00747 }
00748
00749 mkvfile = !strcmp(inputFC->iformat->name, "mkv") ? 1 : 0;
00750
00751 if (offset)
00752 av_seek_frame(inputFC, vid_id, offset, AVSEEK_FLAG_BYTE);
00753
00754
00755 ret = avformat_find_stream_info(inputFC, NULL);
00756 if (ret < 0)
00757 {
00758 LOG(VB_GENERAL, LOG_ERR,
00759 QString("Couldn't get stream info, error #%1").arg(ret));
00760 avformat_close_input(&inputFC);
00761 inputFC = NULL;
00762 return false;
00763 }
00764
00765
00766 if (VERBOSE_LEVEL_CHECK(VB_GENERAL, LOG_INFO))
00767 av_dump_format(inputFC, 0, ifname, 0);
00768
00769 for (unsigned int i = 0; i < inputFC->nb_streams; i++)
00770 {
00771 switch (inputFC->streams[i]->codec->codec_type)
00772 {
00773 case AVMEDIA_TYPE_VIDEO:
00774 if (vid_id == -1)
00775 vid_id = i;
00776 break;
00777
00778 case AVMEDIA_TYPE_AUDIO:
00779 if (inputFC->streams[i]->codec->channels == 0)
00780 {
00781 LOG(VB_GENERAL, LOG_ERR,
00782 QString("Skipping invalid audio stream: %1").arg(i));
00783 break;
00784 }
00785 if (inputFC->streams[i]->codec->codec_id == CODEC_ID_AC3 ||
00786 inputFC->streams[i]->codec->codec_id == CODEC_ID_MP3 ||
00787 inputFC->streams[i]->codec->codec_id == CODEC_ID_MP2)
00788 {
00789 aud_map[i] = ext_count++;
00790 aFrame[i] = new FrameList();
00791 }
00792 else
00793 LOG(VB_GENERAL, LOG_ERR,
00794 QString("Skipping unsupported audio stream: %1")
00795 .arg(inputFC->streams[i]->codec->codec_id));
00796 break;
00797 default:
00798 LOG(VB_GENERAL, LOG_ERR,
00799 QString("Skipping unsupported codec %1 on stream %2")
00800 .arg(inputFC->streams[i]->codec->codec_type).arg(i));
00801 break;
00802 }
00803 }
00804
00805 return true;
00806 }
00807
00808 void MPEG2fixup::SetFrameNum(uint8_t *ptr, int num)
00809 {
00810 SETBITS(ptr + 4, num, 10);
00811 }
00812
00813 void MPEG2fixup::AddSequence(MPEG2frame *frame1, MPEG2frame *frame2)
00814 {
00815 if (frame1->isSequence || !frame2->isSequence)
00816 return;
00817
00818 int head_size = (frame2->framePos - frame2->pkt.data);
00819
00820 frame1->ensure_size(frame1->pkt.size + head_size);
00821 memmove(frame1->pkt.data + head_size, frame1->pkt.data, frame1->pkt.size);
00822 memcpy(frame1->pkt.data, frame2->pkt.data, head_size);
00823 frame1->pkt.size += head_size;
00824 ProcessVideo(frame1, header_decoder);
00825 #if 0
00826 if (VERBOSE_LEVEL_CHECK(VB_PROCESS, LOG_ANY))
00827 {
00828 static int count = 0;
00829 QString filename = QString("hdr%1.yuv").arg(count++);
00830 WriteFrame(filename, &frame1->pkt);
00831 }
00832 #endif
00833 }
00834
00835 int MPEG2fixup::ProcessVideo(MPEG2frame *vf, mpeg2dec_t *dec)
00836 {
00837 int state = -1;
00838 int last_pos = 0;
00839 mpeg2_info_t *info;
00840
00841 if (dec == header_decoder)
00842 {
00843 mpeg2_reset(dec, 0);
00844 vf->isSequence = 0;
00845 vf->isGop = 0;
00846 }
00847
00848 info = (mpeg2_info_t *)mpeg2_info(dec);
00849
00850 mpeg2_buffer(dec, vf->pkt.data, vf->pkt.data + vf->pkt.size);
00851
00852 while (state != STATE_PICTURE)
00853 {
00854 state = mpeg2_parse(dec);
00855
00856 if (dec == header_decoder)
00857 {
00858 switch (state)
00859 {
00860
00861 case STATE_SEQUENCE:
00862 case STATE_SEQUENCE_MODIFIED:
00863 case STATE_SEQUENCE_REPEATED:
00864 memcpy(&vf->mpeg2_seq, info->sequence,
00865 sizeof(mpeg2_sequence_t));
00866 vf->isSequence = 1;
00867 break;
00868
00869 case STATE_GOP:
00870 memcpy(&vf->mpeg2_gop, info->gop, sizeof(mpeg2_gop_t));
00871 vf->isGop = 1;
00872 vf->gopPos = vf->pkt.data + last_pos;
00873
00874 break;
00875
00876 case STATE_PICTURE:
00877 memcpy(&vf->mpeg2_pic, info->current_picture,
00878 sizeof(mpeg2_picture_t));
00879 vf->framePos = vf->pkt.data + last_pos;
00880 break;
00881
00882 case STATE_BUFFER:
00883 LOG(VB_GENERAL, LOG_WARNING,
00884 "Warning: partial frame found!");
00885 return 1;
00886 }
00887 }
00888 else if (state == STATE_BUFFER)
00889 {
00890 WriteData("abort.dat", vf->pkt.data, vf->pkt.size);
00891 LOG(VB_GENERAL, LOG_ERR,
00892 QString("Failed to decode frame. Position was: %1")
00893 .arg(last_pos));
00894 return -1;
00895 }
00896 last_pos = (vf->pkt.size - mpeg2_getpos(dec)) - 4;
00897 }
00898
00899 if (dec != header_decoder)
00900 {
00901 while (state != STATE_BUFFER)
00902 state = mpeg2_parse(dec);
00903 if (info->display_picture)
00904 {
00905
00906
00907
00908
00909
00910 uint8_t tmp[8] = {0x00, 0x00, 0x01, 0xb2, 0xff, 0xff, 0xff, 0xff};
00911 mpeg2_buffer(dec, tmp, tmp + 8);
00912 mpeg2_parse(dec);
00913 }
00914 }
00915
00916 if (VERBOSE_LEVEL_CHECK(VB_DECODE, LOG_INFO))
00917 {
00918 QString msg = QString("");
00919 #if 0
00920 msg += QString("unused:%1 ") .arg(vf->pkt.size - mpeg2_getpos(dec));
00921 #endif
00922
00923 if (vf->isSequence)
00924 msg += QString("%1x%2 P:%3 ").arg(info->sequence->width)
00925 .arg(info->sequence->height).arg(info->sequence->frame_period);
00926
00927 if (info->gop)
00928 {
00929 QString gop;
00930 gop.sprintf("%02d:%02d:%02d:%03d ",
00931 info->gop->hours, info->gop->minutes,
00932 info->gop->seconds, info->gop->pictures);
00933 msg += gop;
00934 }
00935 if (info->current_picture) {
00936 int ct = info->current_picture->flags & PIC_MASK_CODING_TYPE;
00937 char coding_type = (ct == PIC_FLAG_CODING_TYPE_I) ? 'I' :
00938 ((ct == PIC_FLAG_CODING_TYPE_P) ? 'P' :
00939 ((ct == PIC_FLAG_CODING_TYPE_B) ? 'B' :
00940 ((ct == PIC_FLAG_CODING_TYPE_D) ?'D' : 'X')));
00941 char top_bottom = (info->current_picture->flags &
00942 PIC_FLAG_TOP_FIELD_FIRST) ? 'T' : 'B';
00943 char progressive = (info->current_picture->flags &
00944 PIC_FLAG_PROGRESSIVE_FRAME) ? 'P' : '_';
00945 msg += QString("#%1 fl:%2%3%4%5%6 ")
00946 .arg(info->current_picture->temporal_reference)
00947 .arg(info->current_picture->nb_fields)
00948 .arg(coding_type)
00949 .arg(top_bottom)
00950 .arg(progressive)
00951 .arg(info->current_picture->flags >> 4, 0, 16);
00952 }
00953 msg += QString("pos: %1").arg(vf->pkt.pos);
00954 LOG(VB_DECODE, LOG_INFO, msg);
00955 }
00956
00957 return 0;
00958 }
00959
00960 void MPEG2fixup::WriteFrame(QString filename, MPEG2frame *f)
00961 {
00962 MPEG2frame *tmpFrame = GetPoolFrame(f);
00963 if (tmpFrame == NULL)
00964 return;
00965 if (!tmpFrame->isSequence)
00966 {
00967 for (FrameList::Iterator it = vFrame.begin(); it != vFrame.end(); it++)
00968 {
00969 if ((*it)->isSequence)
00970 {
00971 AddSequence(tmpFrame, *it);
00972 break;
00973 }
00974 }
00975 }
00976 WriteFrame(filename, &tmpFrame->pkt);
00977 framePool.enqueue(tmpFrame);
00978 }
00979
00980 void MPEG2fixup::WriteFrame(QString filename, AVPacket *pkt)
00981 {
00982 MPEG2frame *tmpFrame = GetPoolFrame(pkt);
00983 if (tmpFrame == NULL)
00984 return;
00985
00986 QString fname = filename + ".enc";
00987 WriteData(fname, pkt->data, pkt->size);
00988
00989 mpeg2dec_t *tmp_decoder = mpeg2_init();
00990 mpeg2_info_t *info = (mpeg2_info_t *)mpeg2_info(tmp_decoder);
00991
00992 while (!info->display_picture)
00993 {
00994 if (ProcessVideo(tmpFrame, tmp_decoder))
00995 {
00996 delete tmpFrame;
00997 return;
00998 }
00999 }
01000
01001 WriteYUV(filename, info);
01002 framePool.enqueue(tmpFrame);
01003 mpeg2_close(tmp_decoder);
01004 }
01005
01006 void MPEG2fixup::WriteYUV(QString filename, const mpeg2_info_t *info)
01007 {
01008 int fh = open(filename.toLocal8Bit().constData(),
01009 O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
01010 if (fh == -1) {
01011 LOG(VB_GENERAL, LOG_ERR,
01012 QString("Couldn't open file %1: ").arg(filename) + ENO);
01013 return;
01014 }
01015
01016 int ret = write(fh, info->display_fbuf->buf[0],
01017 info->sequence->width * info->sequence->height);
01018 if (ret < 0)
01019 {
01020 LOG(VB_GENERAL, LOG_ERR, QString("write failed %1: ").arg(filename) +
01021 ENO);
01022 goto closefd;
01023 }
01024 ret = write(fh, info->display_fbuf->buf[1],
01025 info->sequence->chroma_width * info->sequence->chroma_height);
01026 if (ret < 0)
01027 {
01028 LOG(VB_GENERAL, LOG_ERR, QString("write failed %1: ").arg(filename) +
01029 ENO);
01030 goto closefd;
01031 }
01032 ret = write(fh, info->display_fbuf->buf[2],
01033 info->sequence->chroma_width * info->sequence->chroma_height);
01034 if (ret < 0)
01035 {
01036 LOG(VB_GENERAL, LOG_ERR, QString("write failed %1: ").arg(filename) +
01037 ENO);
01038 goto closefd;
01039 }
01040 closefd:
01041 close(fh);
01042 }
01043
01044 void MPEG2fixup::WriteData(QString filename, uint8_t *data, int size)
01045 {
01046 int fh = open(filename.toLocal8Bit().constData(),
01047 O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
01048 if (fh == -1) {
01049 LOG(VB_GENERAL, LOG_ERR,
01050 QString("Couldn't open file %1: ").arg(filename) + ENO);
01051 return;
01052 }
01053
01054 int ret = write(fh, data, size);
01055 if (ret < 0)
01056 LOG(VB_GENERAL, LOG_ERR, QString("write failed %1").arg(filename) +
01057 ENO);
01058 close(fh);
01059 }
01060
01061 extern "C" {
01062 #include "helper.h"
01063 }
01064
01065 int MPEG2fixup::BuildFrame(AVPacket *pkt, QString fname)
01066 {
01067 const mpeg2_info_t *info;
01068 int outbuf_size;
01069 uint16_t intra_matrix[64] ATTR_ALIGN(16);
01070 AVFrame *picture;
01071 AVCodecContext *c = NULL;
01072 AVCodec *out_codec;
01073
01074 info = mpeg2_info(img_decoder);
01075 if (!info->display_fbuf)
01076 return 1;
01077
01078 outbuf_size = info->sequence->width * info->sequence->height * 2;
01079
01080 if (!fname.isEmpty())
01081 {
01082 QString tmpstr = fname + ".yuv";
01083 WriteYUV(tmpstr, info);
01084 }
01085
01086 picture = avcodec_alloc_frame();
01087
01088 pkt->data = (uint8_t *)av_malloc(outbuf_size);
01089
01090 picture->data[0] = info->display_fbuf->buf[0];
01091 picture->data[1] = info->display_fbuf->buf[1];
01092 picture->data[2] = info->display_fbuf->buf[2];
01093
01094 picture->linesize[0] = info->sequence->width;
01095 picture->linesize[1] = info->sequence->chroma_width;
01096 picture->linesize[2] = info->sequence->chroma_width;
01097
01098 picture->opaque = info->display_fbuf->id;
01099
01100 copy_quant_matrix(img_decoder, intra_matrix);
01101
01102 if (info->display_picture->nb_fields % 2)
01103 picture->top_field_first = !(info->display_picture->flags &
01104 PIC_FLAG_TOP_FIELD_FIRST);
01105 else
01106 picture->top_field_first = !!(info->display_picture->flags &
01107 PIC_FLAG_TOP_FIELD_FIRST);
01108
01109 picture->interlaced_frame = !(info->display_picture->flags &
01110 PIC_FLAG_PROGRESSIVE_FRAME);
01111
01112 out_codec = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO);
01113
01114 if (!out_codec)
01115 {
01116 free(picture);
01117 LOG(VB_GENERAL, LOG_ERR, "Couldn't find MPEG2 encoder");
01118 return 1;
01119 }
01120
01121 c = avcodec_alloc_context3(NULL);
01122
01123
01124
01125
01126 c->dsp_mask = 0xffff;
01127
01128
01129
01130
01131
01132 if (picture->interlaced_frame)
01133 c->flags |= CODEC_FLAG_INTERLACED_DCT;
01134
01135 c->bit_rate = info->sequence->byte_rate << 3;
01136 c->bit_rate_tolerance = c->bit_rate >> 2;
01137 c->width = info->sequence->width;
01138 c->height = info->sequence->height;
01139 av_reduce(&c->time_base.num, &c->time_base.den,
01140 info->sequence->frame_period, 27000000LL, 100000);
01141 c->pix_fmt = PIX_FMT_YUV420P;
01142 c->max_b_frames = 0;
01143 c->has_b_frames = 0;
01144 c->rc_buffer_aggressivity = 1;
01145
01146
01147 c->rc_buffer_size = 0;
01148 c->gop_size = 0;
01149
01150
01151 if (intra_matrix[0] == 0x08)
01152 c->intra_matrix = intra_matrix;
01153
01154 c->qmin = c->qmax = 2;
01155
01156 picture->pts = AV_NOPTS_VALUE;
01157 picture->key_frame = 1;
01158 picture->pict_type = AV_PICTURE_TYPE_NONE;
01159 picture->type = 0;
01160 picture->quality = 0;
01161
01162 if (avcodec_open2(c, out_codec, NULL) < 0)
01163 {
01164 free(picture);
01165 LOG(VB_GENERAL, LOG_ERR, "could not open codec");
01166 return 1;
01167 }
01168
01169 int got_packet = 0;
01170
01171 int ret = avcodec_encode_video2(c, pkt, picture, &got_packet);
01172
01173 if (ret < 0 || !got_packet)
01174 {
01175 free(picture);
01176 LOG(VB_GENERAL, LOG_ERR,
01177 QString("avcodec_encode_video failed (%1)").arg(pkt->size));
01178 return 1;
01179 }
01180
01181 if (!fname.isEmpty())
01182 {
01183 QString ename = fname + ".enc";
01184 WriteData(ename, pkt->data, pkt->size);
01185
01186 QString yname = fname + ".enc.yuv";
01187 WriteFrame(yname, pkt);
01188 }
01189 int delta = FindMPEG2Header(pkt->data, pkt->size, 0x00);
01190
01191 pkt->size -= delta;
01192 memmove(pkt->data, pkt->data + delta, pkt->size);
01193 SetRepeat(pkt->data, pkt->size, info->display_picture->nb_fields,
01194 !!(info->display_picture->flags & PIC_FLAG_TOP_FIELD_FIRST));
01195
01196 avcodec_close(c);
01197 av_freep(&c);
01198 av_freep(&picture);
01199
01200 return 0;
01201 }
01202
01203 #define MAX_FRAMES 2000
01204 MPEG2frame *MPEG2fixup::GetPoolFrame(AVPacket *pkt)
01205 {
01206 MPEG2frame *f;
01207 static int frame_count = 0;
01208
01209 if (framePool.isEmpty())
01210 {
01211 if (frame_count >= MAX_FRAMES)
01212 {
01213 LOG(VB_GENERAL, LOG_ERR, "No more queue slots!");
01214 return NULL;
01215 }
01216 f = new MPEG2frame(pkt->size);
01217 frame_count++;
01218 }
01219 else
01220 f = framePool.dequeue();
01221
01222 f->set_pkt(pkt);
01223
01224 return f;
01225 }
01226
01227 MPEG2frame *MPEG2fixup::GetPoolFrame(MPEG2frame *f)
01228 {
01229 MPEG2frame *tmpFrame = GetPoolFrame(&f->pkt);
01230 if (!tmpFrame)
01231 return tmpFrame;
01232
01233 tmpFrame->isSequence = f->isSequence;
01234 tmpFrame->isGop = f->isGop;
01235 tmpFrame->mpeg2_seq = f->mpeg2_seq;
01236 tmpFrame->mpeg2_gop = f->mpeg2_gop;
01237 tmpFrame->mpeg2_pic = f->mpeg2_pic;
01238 return tmpFrame;
01239 }
01240
01241 int MPEG2fixup::GetFrame(AVPacket *pkt)
01242 {
01243 int ret;
01244
01245 while (true)
01246 {
01247 bool done = false;
01248 if (unreadFrames.count())
01249 {
01250 vFrame.append(unreadFrames.dequeue());
01251 if (real_file_end && !unreadFrames.count())
01252 file_end = true;
01253 return file_end;
01254 }
01255
01256 while (!done)
01257 {
01258 pkt->pts = AV_NOPTS_VALUE;
01259 pkt->dts = AV_NOPTS_VALUE;
01260 ret = av_read_frame(inputFC, pkt);
01261
01262 if (ret < 0)
01263 {
01264
01265 if (ret == -EAGAIN)
01266 continue;
01267
01268
01269 if (vFrame.isEmpty())
01270 {
01271 LOG(VB_GENERAL, LOG_ERR,
01272 "Found end of file without finding any frames");
01273 return 1;
01274 }
01275
01276 MPEG2frame *tmpFrame = GetPoolFrame(&vFrame.last()->pkt);
01277 if (tmpFrame == NULL)
01278 return 1;
01279
01280 vFrame.append(tmpFrame);
01281 real_file_end = true;
01282 file_end = true;
01283 return 1;
01284 }
01285
01286 if (pkt->stream_index == vid_id ||
01287 aFrame.contains(pkt->stream_index))
01288 done = true;
01289 else
01290 av_free_packet(pkt);
01291 }
01292 pkt->duration = framenum++;
01293 if ((showprogress || update_status) &&
01294 QDateTime::currentDateTime() > statustime)
01295 {
01296 float percent_done = 100.0 * pkt->pos / filesize;
01297 if (update_status)
01298 update_status(percent_done);
01299 if (showprogress)
01300 LOG(VB_GENERAL, LOG_INFO, QString("%1% complete")
01301 .arg(percent_done, 0, 'f', 1));
01302 if (check_abort && check_abort())
01303 return REENCODE_STOPPED;
01304 statustime = QDateTime::currentDateTime();
01305 statustime = statustime.addSecs(status_update_time);
01306 }
01307
01308 #ifdef DEBUG_AUDIO
01309 LOG(VB_DECODE, LOG_INFO, QString("Stream: %1 PTS: %2 DTS: %3 pos: %4")
01310 .arg(pkt->stream_index)
01311 .arg((pkt->pts == AV_NOPTS_VALUE) ? "NONE" : PtsTime(pkt->pts))
01312 .arg((pkt->dts == AV_NOPTS_VALUE) ? "NONE" : PtsTime(pkt->dts))
01313 .arg(pkt->pos));
01314 #endif
01315
01316 MPEG2frame *tmpFrame = GetPoolFrame(pkt);
01317 if (tmpFrame == NULL)
01318 return 1;
01319
01320 switch (inputFC->streams[pkt->stream_index]->codec->codec_type)
01321 {
01322 case AVMEDIA_TYPE_VIDEO:
01323 vFrame.append(tmpFrame);
01324 av_free_packet(pkt);
01325
01326 if (!ProcessVideo(vFrame.last(), header_decoder))
01327 return 0;
01328 framePool.enqueue(vFrame.takeLast());
01329 break;
01330
01331 case AVMEDIA_TYPE_AUDIO:
01332 aFrame[pkt->stream_index]->append(tmpFrame);
01333 av_free_packet(pkt);
01334 return 0;
01335
01336 default:
01337 framePool.enqueue(tmpFrame);
01338 av_free_packet(pkt);
01339 return 1;
01340 }
01341 }
01342 }
01343
01344 bool MPEG2fixup::FindStart()
01345 {
01346 AVPacket pkt;
01347 QMap <int, bool> found;
01348
01349 av_init_packet(&pkt);
01350
01351 do
01352 {
01353 if (GetFrame(&pkt))
01354 return false;
01355
01356 if (vid_id == pkt.stream_index)
01357 {
01358 while (!vFrame.isEmpty())
01359 {
01360 if (vFrame.first()->isSequence)
01361 {
01362 if (pkt.pos != vFrame.first()->pkt.pos)
01363 break;
01364
01365 if ((uint64_t)pkt.pts != AV_NOPTS_VALUE ||
01366 (uint64_t)pkt.dts != AV_NOPTS_VALUE)
01367 {
01368 if ((uint64_t)pkt.pts == AV_NOPTS_VALUE)
01369 vFrame.first()->pkt.pts = pkt.dts;
01370
01371 LOG(VB_PROCESS, LOG_INFO,
01372 "Found 1st valid video frame");
01373 break;
01374 }
01375 }
01376
01377 LOG(VB_PROCESS, LOG_INFO, "Dropping V packet");
01378
01379 framePool.enqueue(vFrame.takeFirst());
01380 }
01381 }
01382
01383 if (vFrame.isEmpty())
01384 continue;
01385
01386 for (FrameMap::Iterator it = aFrame.begin(); it != aFrame.end(); it++)
01387 {
01388 if (found.contains(it.key()))
01389 continue;
01390
01391 FrameList *af = (*it);
01392
01393 while (!af->isEmpty())
01394 {
01395 int64_t delta = diff2x33(af->first()->pkt.pts,
01396 vFrame.first()->pkt.pts);
01397 if (delta < -180000 || delta > 180000)
01398 {
01399
01400
01401 MPEG2frame *foundframe = NULL;
01402 for (FrameList::Iterator it2 = vFrame.begin();
01403 it2 != vFrame.end(); it2++)
01404 {
01405 MPEG2frame *currFrame = (*it2);
01406 if (currFrame->isSequence)
01407 {
01408 int64_t dlta1 = diff2x33(af->first()->pkt.pts,
01409 currFrame->pkt.pts);
01410 if (dlta1 >= -180000 && dlta1 <= 180000)
01411 {
01412 foundframe = currFrame;
01413 delta = dlta1;
01414 break;
01415 }
01416 }
01417 }
01418
01419 while (foundframe && vFrame.first() != foundframe)
01420 {
01421 framePool.enqueue(vFrame.takeFirst());
01422 }
01423 }
01424
01425 if (delta < -180000 || delta > 180000)
01426 {
01427 LOG(VB_PROCESS, LOG_INFO,
01428 QString("Dropping A packet from stream %1")
01429 .arg(it.key()));
01430 LOG(VB_PROCESS, LOG_INFO, QString(" A:%1 V:%2")
01431 .arg(PtsTime(af->first()->pkt.pts))
01432 .arg(PtsTime(vFrame.first()->pkt.pts)));
01433 framePool.enqueue(af->takeFirst());
01434 continue;
01435 }
01436
01437 if (delta < 0 && af->count() > 1)
01438 {
01439 if (cmp2x33(af->at(1)->pkt.pts,
01440 vFrame.first()->pkt.pts) > 0)
01441 {
01442 LOG(VB_PROCESS, LOG_INFO,
01443 QString("Found useful audio frame from stream %1")
01444 .arg(it.key()));
01445 found[it.key()] = 1;
01446 break;
01447 }
01448 else
01449 {
01450 LOG(VB_PROCESS, LOG_INFO,
01451 QString("Dropping A packet from stream %1")
01452 .arg(it.key()));
01453 framePool.enqueue(af->takeFirst());
01454 continue;
01455 }
01456 }
01457 else if (delta >= 0)
01458 {
01459 LOG(VB_PROCESS, LOG_INFO,
01460 QString("Found useful audio frame from stream %1")
01461 .arg(it.key()));
01462 found[it.key()] = 1;
01463 break;
01464 }
01465
01466 if (af->count() == 1)
01467 break;
01468 }
01469 }
01470 } while (found.count() != aFrame.count());
01471
01472 return true;
01473 }
01474
01475 void MPEG2fixup::SetRepeat(MPEG2frame *vf, int fields, bool topff)
01476 {
01477 vf->mpeg2_pic.nb_fields = 2;
01478 SetRepeat(vf->framePos, vf->pkt.data + vf->pkt.size - vf->framePos,
01479 fields, topff);
01480 }
01481
01482 void MPEG2fixup::SetRepeat(uint8_t *ptr, int size, int fields, bool topff)
01483 {
01484 uint8_t *end = ptr + size;
01485 uint8_t setmask = 0x00;
01486 uint8_t clrmask = 0xff;
01487 if (topff)
01488 setmask |= 0x80;
01489 else
01490 clrmask &= 0x7f;
01491
01492 if (fields == 2)
01493 clrmask &= 0xfd;
01494 else
01495 setmask |= 0x02;
01496
01497 while (ptr < end)
01498 {
01499 if (MATCH_HEADER(ptr) && ptr[3] == 0xB5 && (ptr[4] & 0xF0) == 0x80)
01500 {
01501
01502
01503 ptr[7] |= setmask;
01504 ptr[7] &= clrmask;
01505 return;
01506 }
01507
01508 ptr++;
01509 }
01510 }
01511
01512 MPEG2frame *MPEG2fixup::FindFrameNum(int frameNum)
01513 {
01514 for (FrameList::Iterator it = vFrame.begin(); it != vFrame.end(); it++)
01515 {
01516 if (GetFrameNum((*it)) == frameNum)
01517 return (*it);
01518 }
01519
01520 return NULL;
01521 }
01522
01523 void MPEG2fixup::RenumberFrames(int start_pos, int delta)
01524 {
01525 int maxPos = vFrame.count();
01526
01527 for (int pos = start_pos; pos < maxPos; pos++)
01528 {
01529 MPEG2frame *frame = vFrame.at(pos);
01530 SetFrameNum(frame->framePos, GetFrameNum(frame) + delta);
01531 frame->mpeg2_pic.temporal_reference += delta;
01532 }
01533 }
01534
01535 void MPEG2fixup::StoreSecondary()
01536 {
01537 while (vSecondary.count())
01538 {
01539 framePool.enqueue(vSecondary.takeFirst());
01540 }
01541
01542 while (vFrame.count() > 1)
01543 {
01544 if (use_secondary && GetFrameTypeT(vFrame.first()) != 'B')
01545 vSecondary.append(vFrame.takeFirst());
01546 else
01547 framePool.enqueue(vFrame.takeFirst());
01548 }
01549 }
01550
01551 int MPEG2fixup::PlaybackSecondary()
01552 {
01553 int frame_num = 0;
01554 mpeg2_reset(img_decoder, 1);
01555 for (FrameList::Iterator it = vSecondary.begin(); it != vSecondary.end();
01556 it++)
01557 {
01558 SetFrameNum((*it)->framePos, frame_num++);
01559 if (ProcessVideo((*it), img_decoder) < 0)
01560 return 1;
01561 }
01562 return 0;
01563 }
01564
01565 MPEG2frame *MPEG2fixup::DecodeToFrame(int frameNum, int skip_reset)
01566 {
01567 MPEG2frame *spare = NULL;
01568 int found = 0;
01569 bool skip_first = false;
01570 const mpeg2_info_t * info = mpeg2_info(img_decoder);
01571 int maxPos = vFrame.count() - 1;
01572
01573 if (vFrame.at(displayFrame)->isSequence)
01574 {
01575 skip_first = true;
01576 if (!skip_reset && (displayFrame != maxPos || displayFrame == 0))
01577 mpeg2_reset(img_decoder, 1);
01578 }
01579
01580 spare = FindFrameNum(frameNum);
01581 if (!spare)
01582 return NULL;
01583
01584 int framePos = vFrame.indexOf(spare);
01585
01586 for (int curPos = displayFrame; displayFrame != maxPos;
01587 curPos++, displayFrame++)
01588 {
01589 if (ProcessVideo(vFrame.at(displayFrame), img_decoder) < 0)
01590 return NULL;
01591
01592 if (!skip_first && curPos >= framePos && info->display_picture &&
01593 (int)info->display_picture->temporal_reference >= frameNum)
01594 {
01595 found = 1;
01596 displayFrame++;
01597 break;
01598 }
01599
01600 skip_first = false;
01601 }
01602
01603 if (!found)
01604 {
01605 int tmpFrameNum = frameNum;
01606 MPEG2frame *tmpFrame = GetPoolFrame(&spare->pkt);
01607 if (tmpFrame == NULL)
01608 return NULL;
01609
01610 tmpFrame->framePos = tmpFrame->pkt.data +
01611 (spare->framePos - spare->pkt.data);
01612
01613 while (!info->display_picture ||
01614 (int)info->display_picture->temporal_reference < frameNum)
01615 {
01616 SetFrameNum(tmpFrame->framePos, ++tmpFrameNum);
01617 if (ProcessVideo(tmpFrame, img_decoder) < 0)
01618 return NULL;
01619 }
01620
01621 framePool.enqueue(tmpFrame);
01622 }
01623
01624 if ((int)info->display_picture->temporal_reference > frameNum)
01625 {
01626
01627
01628
01629 displayFrame = 0;
01630 LOG(VB_GENERAL, LOG_NOTICE,
01631 QString("Frame %1 > %2. Corruption likely at pos: %3")
01632 .arg(info->display_picture->temporal_reference)
01633 .arg(frameNum).arg(spare->pkt.pos));
01634 }
01635
01636 return spare;
01637 }
01638
01639 int MPEG2fixup::ConvertToI(FrameList *orderedFrames, int headPos)
01640 {
01641 MPEG2frame *spare = NULL;
01642 AVPacket pkt;
01643 #ifdef SPEW_FILES
01644 static int ins_count = 0;
01645 #endif
01646
01647
01648 if (headPos == 0)
01649 if (PlaybackSecondary())
01650 return 1;
01651
01652 for (FrameList::Iterator it = orderedFrames->begin();
01653 it != orderedFrames->end(); it++)
01654 {
01655 int i = GetFrameNum((*it));
01656 if ((spare = DecodeToFrame(i, headPos == 0)) == NULL)
01657 return 1;
01658
01659 if (GetFrameTypeT(spare) == 'I')
01660 continue;
01661
01662 pkt = spare->pkt;
01663
01664
01665 {
01666 QString fname;
01667
01668 #ifdef SPEW_FILES
01669 if (VERBOSE_LEVEL_CHECK(VB_PROCESS, LOG_ANY))
01670 fname = QString("cnv%1").arg(ins_count++);
01671 #endif
01672
01673 if (BuildFrame(&pkt, fname))
01674 return 1;
01675
01676 LOG(VB_GENERAL, LOG_INFO,
01677 QString("Converting frame #%1 from %2 to I %3")
01678 .arg(i).arg(GetFrameTypeT(spare)).arg(fname));
01679 }
01680
01681 spare->set_pkt(&pkt);
01682 av_free(pkt.data);
01683 SetFrameNum(spare->pkt.data, GetFrameNum(spare));
01684 ProcessVideo(spare, header_decoder);
01685 }
01686
01687
01688 vFrame.move(headPos, headPos + orderedFrames->count() - 1);
01689 return 0;
01690 }
01691
01692 int MPEG2fixup::InsertFrame(int frameNum, int64_t deltaPTS,
01693 int64_t ptsIncrement, int64_t initPTS)
01694 {
01695 MPEG2frame *spare = NULL;
01696 AVPacket pkt;
01697 int increment = 0;
01698 int index = 0;
01699 #ifdef SPEW_FILES
01700 static int ins_count = 0;
01701 #endif
01702
01703 if ((spare = DecodeToFrame(frameNum, 0)) == NULL)
01704 return -1;
01705
01706 pkt = spare->pkt;
01707
01708
01709 {
01710 QString fname;
01711 #if SPEW_FILES
01712 fname = (VERBOSE_LEVEL_CHECK(VB_PROCESS, LOG_ANY) ?
01713 (QString("ins%1").arg(ins_count++)) : QString());
01714 #endif
01715
01716 if (BuildFrame(&pkt, fname))
01717 return -1;
01718
01719 LOG(VB_GENERAL, LOG_INFO,
01720 QString("Inserting %1 I-Frames after #%2 %3")
01721 .arg((int)(deltaPTS / ptsIncrement))
01722 .arg(GetFrameNum(spare)).arg(fname));
01723 }
01724
01725 inc2x33(&pkt.pts, ptsIncrement * GetNbFields(spare) / 2 + initPTS);
01726
01727 index = vFrame.indexOf(spare);
01728 while (index < vFrame.count() - 1 &&
01729 GetFrameTypeT(vFrame.at(index)) == 'B')
01730 spare = vFrame.at(index++);
01731
01732 index = vFrame.indexOf(spare);
01733
01734 while (deltaPTS > 0)
01735 {
01736 MPEG2frame *tmpFrame;
01737 index++;
01738 increment++;
01739 pkt.dts = pkt.pts;
01740 SetFrameNum(pkt.data, ++frameNum);
01741 tmpFrame = GetPoolFrame(&pkt);
01742 if (tmpFrame == NULL)
01743 return -1;
01744 vFrame.insert(index, tmpFrame);
01745 ProcessVideo(tmpFrame, header_decoder);
01746
01747 inc2x33(&pkt.pts, ptsIncrement);
01748 deltaPTS -= ptsIncrement;
01749 }
01750
01751 av_free(pkt.data);
01752
01753
01754 RenumberFrames(index, increment);
01755
01756 return increment;
01757 }
01758
01759 void MPEG2fixup::AddRangeList(QStringList rangelist, int type)
01760 {
01761 QStringList::iterator i;
01762 frm_dir_map_t *mapPtr;
01763
01764 if (type == MPF_TYPE_CUTLIST)
01765 {
01766 mapPtr = &delMap;
01767 discard = 0;
01768 }
01769 else
01770 mapPtr = &saveMap;
01771
01772 mapPtr->clear();
01773
01774 for (i = rangelist.begin(); i != rangelist.end(); ++i)
01775 {
01776 QStringList tmp = (*i).split(" - ");
01777 if (tmp.size() < 2)
01778 continue;
01779
01780 bool ok[2] = { false, false };
01781
01782 long long start = tmp[0].toLongLong(&ok[0]);
01783 long long end = tmp[1].toLongLong(&ok[1]);
01784
01785 if (ok[0] && ok[1])
01786 {
01787 if (start == 0)
01788 {
01789 if (type == MPF_TYPE_CUTLIST)
01790 discard = 1;
01791 }
01792 else
01793 mapPtr->insert(start - 1, MARK_CUT_START);
01794
01795 mapPtr->insert(end, MARK_CUT_END);
01796 }
01797 }
01798
01799 if (rangelist.count())
01800 use_secondary = true;
01801 }
01802
01803 void MPEG2fixup::ShowRangeMap(frm_dir_map_t *mapPtr, QString msg)
01804 {
01805 if (mapPtr->count())
01806 {
01807 int64_t start = 0;
01808 frm_dir_map_t::iterator it = mapPtr->begin();
01809 for (; it != mapPtr->end(); ++it)
01810 if (*it == 0)
01811 msg += QString("\n\t\t%1 - %2").arg(start).arg(it.key());
01812 else
01813 start = it.key();
01814 LOG(VB_PROCESS, LOG_INFO, msg);
01815 }
01816 }
01817
01818 FrameList MPEG2fixup::ReorderDTStoPTS(FrameList *dtsOrder, int pos)
01819 {
01820 FrameList Lreorder;
01821 int maxPos = dtsOrder->count() - 1;
01822
01823 if (pos >= maxPos)
01824 return Lreorder;
01825
01826 MPEG2frame *frame = dtsOrder->at(pos);
01827
01828 for (pos++; pos < maxPos && GetFrameTypeT(dtsOrder->at(pos)) == 'B'; pos++)
01829 Lreorder.append(dtsOrder->at(pos));
01830
01831 Lreorder.append(frame);
01832 return Lreorder;
01833 }
01834
01835 void MPEG2fixup::InitialPTSFixup(MPEG2frame *curFrame, int64_t &origvPTS,
01836 int64_t &PTSdiscrep, int numframes, bool fix)
01837 {
01838 int64_t tmpPTS = diff2x33(curFrame->pkt.pts,
01839 origvPTS / 300);
01840
01841 if ((uint64_t)curFrame->pkt.pts == AV_NOPTS_VALUE)
01842 {
01843 LOG(VB_PROCESS, LOG_INFO,
01844 QString("Found frame %1 with missing PTS at %2")
01845 .arg(GetFrameNum(curFrame))
01846 .arg(PtsTime(origvPTS / 300)));
01847 if (fix)
01848 curFrame->pkt.pts = origvPTS / 300;
01849 else
01850 PTSdiscrep = AV_NOPTS_VALUE;
01851 }
01852 else if (tmpPTS < -ptsIncrement ||
01853 tmpPTS > ptsIncrement*numframes)
01854 {
01855 if (tmpPTS != PTSdiscrep)
01856 {
01857 PTSdiscrep = tmpPTS;
01858 LOG(VB_PROCESS, LOG_INFO,
01859 QString("Found invalid PTS (off by %1) at %2")
01860 .arg(PtsTime(tmpPTS))
01861 .arg(PtsTime(origvPTS / 300)));
01862 }
01863 if (fix)
01864 curFrame->pkt.pts = origvPTS / 300;
01865 }
01866 else
01867 {
01868 origvPTS = curFrame->pkt.pts * 300;
01869 }
01870 ptsinc((uint64_t *)&origvPTS,
01871 (uint64_t)(150 * ptsIncrement * GetNbFields(curFrame)));
01872 }
01873
01874 void MPEG2fixup::dumpList(FrameList *list)
01875 {
01876 LOG(VB_GENERAL, LOG_INFO, "=========================================");
01877 LOG(VB_GENERAL, LOG_INFO, QString("List contains %1 items")
01878 .arg(list->count()));
01879
01880 for (FrameList::Iterator it = list->begin(); it != list->end(); it++)
01881 {
01882 MPEG2frame *curFrame = (*it);
01883
01884 LOG(VB_GENERAL, LOG_INFO,
01885 QString("VID: %1 #:%2 nb: %3 pts: %4 dts: %5 pos: %6")
01886 .arg(GetFrameTypeT(curFrame))
01887 .arg(GetFrameNum(curFrame))
01888 .arg(GetNbFields(curFrame))
01889 .arg(PtsTime(curFrame->pkt.pts))
01890 .arg(PtsTime(curFrame->pkt.dts))
01891 .arg(curFrame->pkt.pos));
01892 }
01893 LOG(VB_GENERAL, LOG_INFO, "=========================================");
01894 }
01895
01896 int MPEG2fixup::Start()
01897 {
01898
01899
01900 int64_t expectedvPTS, expectedPTS[N_AUDIO];
01901 int64_t expectedDTS = 0, lastPTS = 0, initPTS = 0, deltaPTS = 0;
01902 int64_t origvPTS = 0, origaPTS[N_AUDIO];
01903 int64_t cutStartPTS = 0, cutEndPTS = 0;
01904 uint64_t frame_count = 0;
01905 int new_discard_state = 0;
01906 int ret;
01907 QMap<int, int> af_dlta_cnt, cutState;
01908
01909 AVPacket pkt, lastRealvPkt;
01910
01911 if (!InitAV(infile, format, 0))
01912 return GENERIC_EXIT_NOT_OK;
01913
01914 if (!FindStart())
01915 return GENERIC_EXIT_NOT_OK;
01916
01917 av_init_packet(&pkt);
01918
01919 ptsIncrement = vFrame.first()->mpeg2_seq.frame_period / 300;
01920
01921 initPTS = vFrame.first()->pkt.pts;
01922
01923 LOG(VB_GENERAL, LOG_INFO, QString("#%1 PTS:%2 Delta: 0.0ms queue: %3")
01924 .arg(vid_id).arg(PtsTime(vFrame.first()->pkt.pts))
01925 .arg(vFrame.count()));
01926
01927 for (FrameMap::Iterator it = aFrame.begin(); it != aFrame.end(); it++)
01928 {
01929 FrameList *af = (*it);
01930 deltaPTS = diff2x33(vFrame.first()->pkt.pts, af->first()->pkt.pts);
01931 LOG(VB_GENERAL, LOG_INFO,
01932 QString("#%1 PTS:%2 Delta: %3ms queue: %4")
01933 .arg(it.key()) .arg(PtsTime(af->first()->pkt.pts))
01934 .arg(1000.0*deltaPTS / 90000.0).arg(af->count()));
01935
01936 if (cmp2x33(af->first()->pkt.pts, initPTS) < 0)
01937 initPTS = af->first()->pkt.pts;
01938 }
01939
01940 initPTS -= 16200;
01941
01942 PTSOffsetQueue poq(vid_id, aFrame.keys(), initPTS);
01943
01944 LOG(VB_PROCESS, LOG_INFO,
01945 QString("ptsIncrement: %1 Frame #: %2 PTS-adjust: %3")
01946 .arg(ptsIncrement).arg(GetFrameNum(vFrame.first()))
01947 .arg(PtsTime(initPTS)));
01948
01949
01950 origvPTS = 300 * udiff2x33(vFrame.first()->pkt.pts,
01951 ptsIncrement * GetFrameNum(vFrame.first()));
01952 expectedvPTS = 300 * (udiff2x33(vFrame.first()->pkt.pts, initPTS) -
01953 (ptsIncrement * GetFrameNum(vFrame.first())));
01954 expectedDTS = expectedvPTS - 300 * ptsIncrement;
01955
01956 if (discard)
01957 {
01958 cutStartPTS = origvPTS / 300;
01959 }
01960
01961 for (FrameMap::Iterator it = aFrame.begin(); it != aFrame.end(); it++)
01962 {
01963 FrameList *af = (*it);
01964 origaPTS[it.key()] = af->first()->pkt.pts * 300;
01965 expectedPTS[it.key()] = udiff2x33(af->first()->pkt.pts, initPTS);
01966 af_dlta_cnt[it.key()] = 0;
01967 cutState[it.key()] = !!(discard);
01968 }
01969
01970 ShowRangeMap(&delMap, "Cutlist:");
01971 ShowRangeMap(&saveMap, "Same Range:");
01972
01973 InitReplex();
01974
01975 while (!file_end)
01976 {
01977
01978 if ((ret = GetFrame(&pkt)) < 0)
01979 return ret;
01980
01981 if (vFrame.count() && (file_end || vFrame.last()->isSequence))
01982 {
01983 displayFrame = 0;
01984
01985
01986
01987
01988 MPEG2frame *seqFrame = vFrame.first();
01989
01990 if (!seqFrame->isSequence)
01991 {
01992 LOG(VB_GENERAL, LOG_WARNING,
01993 QString("Problem: Frame %1 (type %2) doesn't contain "
01994 "sequence header!")
01995 .arg(frame_count) .arg(GetFrameTypeT(seqFrame)));
01996 }
01997
01998 if (ptsIncrement != seqFrame->mpeg2_seq.frame_period / 300)
01999 {
02000 LOG(VB_GENERAL, LOG_WARNING,
02001 QString("WARNING - Unsupported FPS change from %1 to %2")
02002 .arg(90000.0 / ptsIncrement, 0, 'f', 2)
02003 .arg(27000000.0 / seqFrame->mpeg2_seq.frame_period,
02004 0, 'f', 2));
02005 }
02006
02007 for (int frame_pos = 0; frame_pos < vFrame.count() - 1;)
02008 {
02009 bool ptsorder_eq_dtsorder = false;
02010 int64_t dtsExtra = 0, PTSdiscrep = 0;
02011 FrameList Lreorder;
02012 MPEG2frame *markedFrame = NULL, *markedFrameP = NULL;
02013
02014 if (expectedvPTS != expectedDTS + ptsIncrement * 300)
02015 {
02016 LOG(VB_GENERAL, LOG_ERR,
02017 QString("expectedPTS != expectedDTS + ptsIncrement"));
02018 LOG(VB_GENERAL, LOG_ERR, QString("%1 != %2 + %3")
02019 .arg(PtsTime(expectedvPTS / 300))
02020 .arg(PtsTime(expectedDTS / 300))
02021 .arg(PtsTime(ptsIncrement)));
02022 LOG(VB_GENERAL, LOG_ERR, QString("%1 != %2 + %3")
02023 .arg(expectedvPTS)
02024 .arg(expectedDTS)
02025 .arg(ptsIncrement));
02026 return GENERIC_EXIT_NOT_OK;
02027 }
02028
02029
02030 Lreorder = ReorderDTStoPTS(&vFrame, frame_pos);
02031
02032
02033 for (FrameList::Iterator it2 = Lreorder.begin();
02034 it2 != Lreorder.end(); it2++)
02035 {
02036 MPEG2frame *curFrame = (*it2);
02037 poq.UpdateOrigPTS(vid_id, origvPTS, curFrame->pkt);
02038 InitialPTSFixup(curFrame, origvPTS, PTSdiscrep,
02039 maxframes, true);
02040 }
02041
02042
02043
02044
02045
02046 if (PTSdiscrep && !file_end)
02047 {
02048 int pos = vFrame.count();
02049 int count = Lreorder.count();
02050 while (vFrame.count() - frame_pos - count < 20 && !file_end)
02051 if ((ret = GetFrame(&pkt)) < 0)
02052 return ret;
02053
02054 if (!file_end)
02055 {
02056 int64_t tmp_origvPTS = origvPTS;
02057 int numframes = (maxframes > 1) ? maxframes - 1 : 1;
02058 bool done = false;
02059 while (!done &&
02060 (frame_pos + count + 1) < vFrame.count())
02061 {
02062 FrameList tmpReorder;
02063 tmpReorder = ReorderDTStoPTS(&vFrame,
02064 frame_pos + count);
02065 for (FrameList::Iterator it2 = tmpReorder.begin();
02066 it2 != tmpReorder.end(); it2++)
02067 {
02068 MPEG2frame *curFrame = (*it2);
02069 int64_t tmpPTSdiscrep = 0;
02070 InitialPTSFixup(curFrame, tmp_origvPTS,
02071 tmpPTSdiscrep, numframes, false);
02072 if (!tmpPTSdiscrep)
02073 {
02074
02075 done = true;
02076 PTSdiscrep = 0;
02077 break;
02078 }
02079 if (tmpPTSdiscrep != (int64_t)AV_NOPTS_VALUE &&
02080 tmpPTSdiscrep != PTSdiscrep)
02081 PTSdiscrep = tmpPTSdiscrep;
02082 }
02083 count += tmpReorder.count();
02084 }
02085 }
02086
02087
02088 while (vFrame.count() > pos)
02089 {
02090 unreadFrames.enqueue(vFrame.takeAt(pos));
02091 }
02092 file_end = false;
02093 }
02094
02095
02096 for (int curIndex = 0; curIndex < Lreorder.count(); curIndex++)
02097 {
02098 MPEG2frame *curFrame = Lreorder.at(curIndex);
02099 if (saveMap.count())
02100 {
02101 if (saveMap.begin().key() <= frame_count)
02102 saveMap.remove(saveMap.begin().key());
02103 if (saveMap.count() && saveMap.begin().value() == 0)
02104 {
02105 LOG(VB_GENERAL, LOG_INFO,
02106 QString("Saving frame #%1") .arg(frame_count));
02107
02108 if (GetFrameTypeT(curFrame) != 'I' &&
02109 ConvertToI(&Lreorder, frame_pos))
02110 {
02111 return GENERIC_EXIT_WRITE_FRAME_ERROR;
02112 }
02113
02114 WriteFrame(QString("save%1.yuv").arg(frame_count),
02115 curFrame);
02116 }
02117 }
02118
02119 if (delMap.count() && delMap.begin().key() <= frame_count)
02120 {
02121 new_discard_state = delMap.begin().value();
02122 LOG(VB_GENERAL, LOG_INFO,
02123 QString("Del map found %1 at %2 (%3)")
02124 .arg(new_discard_state) .arg(frame_count)
02125 .arg(delMap.begin().key()));
02126
02127 delMap.remove(delMap.begin().key());
02128 markedFrameP = curFrame;
02129
02130 if (!new_discard_state)
02131 {
02132 cutEndPTS = markedFrameP->pkt.pts;
02133 poq.SetNextPTS(
02134 diff2x33(cutEndPTS, expectedvPTS / 300),
02135 cutEndPTS);
02136 }
02137 else
02138 {
02139 cutStartPTS =
02140 add2x33(markedFrameP->pkt.pts,
02141 ptsIncrement *
02142 GetNbFields(markedFrameP) / 2);
02143 for (FrameMap::Iterator it3 = aFrame.begin();
02144 it3 != aFrame.end(); it3++)
02145 {
02146 cutState[it3.key()] = 1;
02147 }
02148 }
02149
02150
02151
02152
02153 if ((GetFrameTypeT(curFrame) == 'B') ||
02154 (!new_discard_state &&
02155 (GetFrameTypeT(curFrame) == 'P')))
02156 {
02157 if (ConvertToI(&Lreorder, frame_pos))
02158 return GENERIC_EXIT_WRITE_FRAME_ERROR;
02159 ptsorder_eq_dtsorder = true;
02160 }
02161 else if (!new_discard_state &&
02162 GetFrameTypeT(curFrame) == 'I')
02163 {
02164 vFrame.move(frame_pos, frame_pos + curIndex);
02165 ptsorder_eq_dtsorder = true;
02166 }
02167
02168
02169 markedFrame = vFrame.at(frame_pos + curIndex);
02170
02171 if (!new_discard_state)
02172 {
02173 AddSequence(markedFrame, seqFrame);
02174 RenumberFrames(frame_pos + curIndex,
02175 - GetFrameNum(markedFrame));
02176 }
02177 }
02178
02179 frame_count++;
02180 }
02181
02182 if (!Lreorder.isEmpty())
02183 lastRealvPkt = Lreorder.last()->pkt;
02184
02185 if (markedFrame || !discard)
02186 {
02187
02188 for (FrameList::Iterator it2 = Lreorder.begin();
02189 it2 != Lreorder.end(); it2++)
02190 {
02191 MPEG2frame *curFrame = (*it2);
02192 if (markedFrameP && discard)
02193 {
02194 if (curFrame != markedFrameP)
02195 continue;
02196
02197 markedFrameP = NULL;
02198 }
02199
02200 dec2x33(&curFrame->pkt.pts,
02201 poq.Get(vid_id, &curFrame->pkt));
02202 deltaPTS = diff2x33(curFrame->pkt.pts,
02203 expectedvPTS / 300);
02204
02205 if (deltaPTS < -2 || deltaPTS > 2)
02206 {
02207 LOG(VB_PROCESS, LOG_INFO,
02208 QString("PTS discrepancy: %1 != %2 on "
02209 "%3-Type (%4)")
02210 .arg(curFrame->pkt.pts)
02211 .arg(expectedvPTS / 300)
02212 .arg(GetFrameTypeT(curFrame))
02213 .arg(GetFrameNum(curFrame)));
02214 }
02215
02216
02217 if (no_repeat)
02218 SetRepeat(curFrame, 2, 0);
02219
02220
02221 if (fix_PTS)
02222 curFrame->pkt.pts = expectedvPTS / 300;
02223
02224 if (deltaPTS > ptsIncrement*maxframes)
02225 {
02226 LOG(VB_GENERAL, LOG_NOTICE,
02227 QString("Need to insert %1 frames > max "
02228 "allowed: %2. Assuming bad PTS")
02229 .arg((int)(deltaPTS / ptsIncrement))
02230 .arg(maxframes));
02231 curFrame->pkt.pts = expectedvPTS / 300;
02232 deltaPTS = 0;
02233 }
02234
02235 lastPTS = expectedvPTS;
02236 expectedvPTS += 150 * ptsIncrement *
02237 GetNbFields(curFrame);
02238
02239 if (curFrame == markedFrameP && new_discard_state)
02240 break;
02241 }
02242
02243
02244
02245 if (ptsorder_eq_dtsorder)
02246 dtsExtra = 0;
02247 else
02248 dtsExtra = 150 * ptsIncrement *
02249 (GetNbFields(vFrame.at(frame_pos)) - 2);
02250
02251 if (!markedFrame && deltaPTS > (4 * ptsIncrement / 5))
02252 {
02253
02254
02255
02256
02257
02258 vFrame.at(frame_pos)->pkt.pts = lastPTS / 300;
02259 int ret = InsertFrame(GetFrameNum(vFrame.at(frame_pos)),
02260 deltaPTS, ptsIncrement, 0);
02261
02262 if (ret < 0)
02263 return GENERIC_EXIT_WRITE_FRAME_ERROR;
02264
02265 for (int index = frame_pos + Lreorder.count();
02266 ret && index < vFrame.count(); index++, --ret)
02267 {
02268 lastPTS = expectedvPTS;
02269 expectedvPTS += 150 * ptsIncrement *
02270 GetNbFields(vFrame.at(index));
02271 Lreorder.append(vFrame.at(index));
02272 }
02273 }
02274
02275
02276
02277
02278 for (int i = 0; i < Lreorder.count(); i++, frame_pos++)
02279 {
02280 MPEG2frame *curFrame = vFrame.at(frame_pos);
02281 if (discard)
02282 {
02283 if (curFrame != markedFrame)
02284 continue;
02285
02286 discard = false;
02287 markedFrame = NULL;
02288 }
02289
02290 curFrame->pkt.dts = (expectedDTS / 300);
02291 #if 0
02292 if (GetFrameTypeT(curFrame) == 'B')
02293 curFrame->pkt.pts = (expectedDTS / 300);
02294 #endif
02295 expectedDTS += 150 * ptsIncrement *
02296 ((!ptsorder_eq_dtsorder && i == 0) ? 2 :
02297 GetNbFields(curFrame));
02298 LOG(VB_FRAME, LOG_INFO,
02299 QString("VID: %1 #:%2 nb: %3 pts: %4 dts: %5 "
02300 "pos: %6")
02301 .arg(GetFrameTypeT(curFrame))
02302 .arg(GetFrameNum(curFrame))
02303 .arg(GetNbFields(curFrame))
02304 .arg(PtsTime(curFrame->pkt.pts))
02305 .arg(PtsTime(curFrame->pkt.dts))
02306 .arg(curFrame->pkt.pos));
02307 if (AddFrame(curFrame))
02308 return GENERIC_EXIT_DEADLOCK;
02309
02310 if (curFrame == markedFrame)
02311 {
02312 markedFrame = NULL;
02313 discard = true;
02314 }
02315 }
02316
02317 expectedDTS += dtsExtra;
02318 }
02319 else
02320 {
02321 frame_pos += Lreorder.count();
02322 }
02323 if (PTSdiscrep)
02324 poq.SetNextPos(add2x33(poq.Get(vid_id, &lastRealvPkt),
02325 PTSdiscrep), lastRealvPkt);
02326 }
02327
02328 if (discard)
02329 cutEndPTS = lastRealvPkt.pts;
02330
02331 if (file_end)
02332 use_secondary = false;
02333 if (vFrame.count() > 1 || file_end)
02334 StoreSecondary();
02335 }
02336
02337 for (FrameMap::Iterator it = aFrame.begin(); it != aFrame.end(); it++)
02338 {
02339 FrameList *af = (*it);
02340 AVCodecContext *CC = getCodecContext(it.key());
02341 bool backwardsPTS = false;
02342
02343 while (af->count())
02344 {
02345
02346
02347 if (CC->sample_rate == 0 || CC->frame_size == 0)
02348 break;
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361 int64_t nextPTS, tmpPTS;
02362 int64_t incPTS =
02363 90000LL * (int64_t)CC->frame_size / CC->sample_rate;
02364
02365 if (poq.UpdateOrigPTS(it.key(), origaPTS[it.key()],
02366 af->first()->pkt) < 0)
02367 {
02368 backwardsPTS = true;
02369 af_dlta_cnt[it.key()] = 0;
02370 }
02371
02372 tmpPTS = diff2x33(af->first()->pkt.pts,
02373 origaPTS[it.key()] / 300);
02374
02375 if (tmpPTS < -incPTS)
02376 {
02377 #ifdef DEBUG_AUDIO
02378 LOG(VB_PROCESS, LOG_INFO,
02379 QString("Aud discard: PTS %1 < %2")
02380 .arg(PtsTime(af->first()->pkt.pts))
02381 .arg(PtsTime(origaPTS[it.key()] / 300)));
02382 #endif
02383 framePool.enqueue(af->takeFirst());
02384 af_dlta_cnt[it.key()] = 0;
02385 continue;
02386 }
02387
02388 if (tmpPTS > incPTS * maxframes)
02389 {
02390 LOG(VB_PROCESS, LOG_INFO,
02391 QString("Found invalid audio PTS (off by %1) at %2")
02392 .arg(PtsTime(tmpPTS))
02393 .arg(PtsTime(origaPTS[it.key()] / 300)));
02394 if (backwardsPTS && tmpPTS < 90000LL)
02395 {
02396
02397 LOG(VB_PROCESS, LOG_INFO,
02398 "Fixing missing audio frames");
02399 ptsinc((uint64_t *)&origaPTS[it.key()], 300 * tmpPTS);
02400 backwardsPTS = false;
02401 }
02402 else if (tmpPTS < 90000LL * 4)
02403 {
02404 if (af_dlta_cnt[it.key()] >= 20)
02405 {
02406
02407
02408
02409
02410 ptsinc((uint64_t *)&origaPTS[it.key()],
02411 300 * tmpPTS);
02412 af_dlta_cnt[it.key()] = 0;
02413 }
02414 else
02415 af_dlta_cnt[it.key()]++;
02416 }
02417 af->first()->pkt.pts = origaPTS[it.key()] / 300;
02418 }
02419 else if (tmpPTS > incPTS)
02420 {
02421 incPTS += incPTS;
02422 backwardsPTS = false;
02423 af_dlta_cnt[it.key()] = 0;
02424 }
02425 else
02426 {
02427 backwardsPTS = false;
02428 af_dlta_cnt[it.key()] = 0;
02429 }
02430
02431 nextPTS = add2x33(af->first()->pkt.pts,
02432 90000LL * (int64_t)CC->frame_size / CC->sample_rate);
02433
02434 if ((cutState[it.key()] == 1 &&
02435 cmp2x33(nextPTS, cutStartPTS) > 0) ||
02436 (cutState[it.key()] == 2 &&
02437 cmp2x33(af->first()->pkt.pts, cutEndPTS) < 0))
02438 {
02439 #ifdef DEBUG_AUDIO
02440 LOG(VB_PROCESS, LOG_INFO,
02441 QString("Aud in cutpoint: %1 > %2 && %3 < %4")
02442 .arg(PtsTime(nextPTS)).arg(PtsTime(cutStartPTS))
02443 .arg(PtsTime(af->first()->pkt.pts))
02444 .arg(PtsTime(cutEndPTS)));
02445 #endif
02446 framePool.enqueue(af->takeFirst());
02447 cutState[it.key()] = 2;
02448 ptsinc((uint64_t *)&origaPTS[it.key()], incPTS * 300);
02449 continue;
02450 }
02451
02452 int64_t deltaPTS = poq.Get(it.key(), &af->first()->pkt);
02453
02454 if (udiff2x33(nextPTS, deltaPTS) * 300 > expectedDTS &&
02455 cutState[it.key()] != 1)
02456 {
02457 #ifdef DEBUG_AUDIO
02458 LOG(VB_PROCESS, LOG_INFO, QString("Aud not ready: %1 > %2")
02459 .arg(PtsTime(udiff2x33(nextPTS, deltaPTS)))
02460 .arg(PtsTime(expectedDTS / 300)));
02461 #endif
02462 break;
02463 }
02464
02465 if (cutState[it.key()] == 2)
02466 cutState[it.key()] = 0;
02467
02468 ptsinc((uint64_t *)&origaPTS[it.key()], incPTS * 300);
02469
02470 dec2x33(&af->first()->pkt.pts, deltaPTS);
02471
02472 #if 0
02473 expectedPTS[it.key()] = udiff2x33(nextPTS, initPTS);
02474 write_audio(lApkt_tail->pkt, initPTS);
02475 #endif
02476 LOG(VB_FRAME, LOG_INFO, QString("AUD #%1: pts: %2 pos: %3")
02477 .arg(it.key())
02478 .arg(PtsTime(af->first()->pkt.pts))
02479 .arg(af->first()->pkt.pos));
02480 if (AddFrame(af->first()))
02481 return GENERIC_EXIT_DEADLOCK;
02482 framePool.enqueue(af->takeFirst());
02483 }
02484 }
02485 }
02486
02487 rx.done = 1;
02488 pthread_mutex_lock( &rx.mutex );
02489 pthread_cond_signal(&rx.cond);
02490 pthread_mutex_unlock( &rx.mutex );
02491 pthread_join(thread, NULL);
02492
02493 avformat_close_input(&inputFC);
02494 inputFC = NULL;
02495 return REENCODE_OK;
02496 }
02497
02498 #ifdef NO_MYTH
02499 int verboseMask = VB_GENERAL;
02500
02501 void usage(char *s)
02502 {
02503 fprintf(stderr, "%s usage:\n", s);
02504 fprintf(stderr, "\t--infile <file> -i <file> : Input mpg file\n");
02505 fprintf(stderr, "\t--outfile <file> -o <file> : Output mpg file\n");
02506 fprintf(stderr, "\t--dbg_lvl # -d # : Debug level\n");
02507 fprintf(stderr, "\t--maxframes # -m # : Max frames to insert at once (default=10)\n");
02508 fprintf(stderr, "\t--cutlist \"start - end\" -c : Apply a cutlist. Specify on e'-c' per cut\n");
02509 fprintf(stderr, "\t--no3to2 -t : Remove 3:2 pullup\n");
02510 fprintf(stderr, "\t--fixup -f : make PTS continuous\n");
02511 fprintf(stderr, "\t--ostream <dvd|ps> -e : Output stream type (defaults to ps)\n");
02512 fprintf(stderr, "\t--showprogress -p : show progress\n");
02513 fprintf(stderr, "\t--help -h : This screen\n");
02514 exit(0);
02515 }
02516
02517 int main(int argc, char **argv)
02518 {
02519 QStringList cutlist;
02520 QStringList savelist;
02521 char *infile = NULL, *outfile = NULL, *format = NULL;
02522 int no_repeat = 0, fix_PTS = 0, max_frames = 20, otype = REPLEX_MPEG2;
02523 bool showprogress = 0;
02524 const struct option long_options[] =
02525 {
02526 {"infile", required_argument, NULL, 'i'},
02527
02528 {"outfile", required_argument, NULL, 'o'},
02529 {"format", required_argument, NULL, 'r'},
02530 {"dbg_lvl", required_argument, NULL, 'd'},
02531 {"cutlist", required_argument, NULL, 'c'},
02532 {"saveframe", required_argument, NULL, 's'},
02533 {"ostream", required_argument, NULL, 'e'},
02534 {"no3to2", no_argument, NULL, 't'},
02535 {"fixup", no_argument, NULL, 'f'},
02536 {"showprogress", no_argument, NULL, 'p'},
02537 {"help", no_argument , NULL, 'h'},
02538 {0, 0, 0, 0}
02539 };
02540
02541 while (1)
02542 {
02543 int option_index = 0;
02544 char c;
02545 c = getopt_long (argc, argv, "i:o:d:r:m:c:s:e:tfph",
02546 long_options, &option_index);
02547
02548 if (c == -1)
02549 break;
02550
02551 switch (c)
02552 {
02553
02554 case 'i':
02555 infile = optarg;
02556 break;
02557
02558 case 'o':
02559 outfile = optarg;
02560 break;
02561
02562 case 'r':
02563 format = optarg;
02564 break;
02565
02566 case 'e':
02567 if (strlen(optarg) == 3 && strncmp(optarg, "dvd", 3) == 0)
02568 otype = REPLEX_DVD;
02569 break;
02570
02571 case 'd':
02572 verboseMask = atoi(optarg);
02573 break;
02574
02575 case 'm':
02576 max_frames = atoi(optarg);
02577 break;
02578
02579 case 'c':
02580 cutlist.append(optarg);
02581 break;
02582
02583 case 't':
02584 no_repeat = 1;
02585
02586 case 'f':
02587 fix_PTS = 1;
02588 break;
02589
02590 case 's':
02591 savelist.append(optarg);
02592 break;
02593
02594 case 'p':
02595 showprogress = true;
02596 break;
02597
02598 case 'h':
02599
02600 case '?':
02601
02602 default:
02603 usage(argv[0]);
02604 }
02605 }
02606
02607 if (infile == NULL || outfile == NULL)
02608 usage(argv[0]);
02609
02610 MPEG2fixup m2f(infile, outfile, NULL, format,
02611 no_repeat, fix_PTS, max_frames,
02612 showprogress, otype);
02613
02614 if (cutlist.count())
02615 m2f.AddRangeList(cutlist, MPF_TYPE_CUTLIST);
02616 if (savelist.count())
02617 m2f.AddRangeList(savelist, MPF_TYPE_SAVELIST);
02618 return m2f.Start();
02619 }
02620 #endif
02621
02622 int MPEG2fixup::BuildKeyframeIndex(QString &file,
02623 frm_pos_map_t &posMap)
02624 {
02625 LOG(VB_GENERAL, LOG_INFO, "Generating Keyframe Index");
02626
02627 AVPacket pkt;
02628 int count = 0;
02629
02630
02631 if (!InitAV(file, NULL, 0))
02632 return GENERIC_EXIT_NOT_OK;
02633
02634 if (mkvfile)
02635 {
02636 LOG(VB_GENERAL, LOG_INFO, "Seek tables are not required for MKV");
02637 return GENERIC_EXIT_NOT_OK;
02638 }
02639
02640 av_init_packet(&pkt);
02641
02642 while (av_read_frame(inputFC, &pkt) >= 0)
02643 {
02644 if (pkt.stream_index == vid_id)
02645 {
02646 if (pkt.flags & AV_PKT_FLAG_KEY)
02647 posMap[count] = pkt.pos;
02648 count++;
02649 }
02650 av_free_packet(&pkt);
02651 }
02652
02653
02654 avformat_close_input(&inputFC);
02655 inputFC = NULL;
02656
02657 LOG(VB_GENERAL, LOG_NOTICE, "Transcode Completed");
02658
02659 return REENCODE_OK;
02660 }
02661
02662
02663
02664