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