ssize_t DevPty::handle_read(struct anvil_read_msg *msg, anvil_msginfo_t *msg_info, size_t nbyte, off_t offset) { //anvil_syslog(0, "Ptm::handle_read() n=%d a=%d\n", nbyte, get_pts()->chars_avail()); size_t avail = get_pts()->chars_avail(); if (avail) { size_t amount_to_read = std::min(nbyte, avail); msg_poke(msg_info->pid, msg_info->tid, get_pts()->get_chars_ptr(), amount_to_read, 0); get_pts()->erase_chars(amount_to_read); msg_reply(msg_info->pid, msg_info->tid, amount_to_read, NULL, 0); //anvil_syslog(0, "Ptm::handle_read() got %d chars\n", amount_to_read); msg_send(m_master_pid, ANVIL_POLL_READY, (void *)(uintptr_t)12345, 4); } else { // Reply with no chars msg_reply(msg_info->pid, msg_info->tid, 0, NULL, 0); // Queue the process until there are chars // m_output_waiter = *msg_info; // m_output_waiter_size = msg->nbyte; // anvil_syslog(0, "Ptm::handle_read() got no chars\n"); } return 0; }
ssize_t DevPty::handle_write(struct anvil_write_msg *msg, anvil_msginfo_t *msg_info, size_t nbyte, off_t offset) { //anvil_syslog(0, "Ptm::handle_write()\n"); // Put the bytes in the ring buffer uint8_t buf[WRITE_BUF_SIZE+1]; size_t still_to_write = nbyte; size_t total_written = 0; while (still_to_write) { size_t peek_amount = std::min(still_to_write, (size_t)WRITE_BUF_SIZE); if (peek_amount <= 0) { break; } msg_peek(msg_info->pid, msg_info->tid, buf, peek_amount, total_written + sizeof(struct anvil_write_msg)); still_to_write -= peek_amount; total_written += peek_amount; for (int i=0; i<peek_amount; ++i) { //anvil_syslog(0, "Ptm %c (%02x)\n", isprint(buf[i])?buf[i]:'-', buf[i]); get_pts()->push_char(buf[i]); } } msg_reply(msg_info->pid, msg_info->tid, total_written, NULL, 0); return total_written; }
static int srt_read_header(AVFormatContext *s) { SRTContext *srt = s->priv_data; AVBPrint buf; AVStream *st = avformat_new_stream(s, NULL); int res = 0; FFTextReader tr; ff_text_init_avio(s, &tr, s->pb); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, 1000); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_SUBRIP; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); while (!ff_text_eof(&tr)) { ff_subtitles_read_text_chunk(&tr, &buf); if (buf.len) { int64_t pos = ff_text_pos(&tr); int64_t pts; int duration; const char *ptr = buf.str; int32_t x1 = -1, y1 = -1, x2 = -1, y2 = -1; AVPacket *sub; pts = get_pts(&ptr, &duration, &x1, &y1, &x2, &y2); if (pts != AV_NOPTS_VALUE) { int len = buf.len - (ptr - buf.str); if (len <= 0) continue; sub = ff_subtitles_queue_insert(&srt->q, ptr, len, 0); if (!sub) { res = AVERROR(ENOMEM); goto end; } sub->pos = pos; sub->pts = pts; sub->duration = duration; if (x1 != -1) { uint8_t *p = av_packet_new_side_data(sub, AV_PKT_DATA_SUBTITLE_POSITION, 16); if (p) { AV_WL32(p, x1); AV_WL32(p + 4, y1); AV_WL32(p + 8, x2); AV_WL32(p + 12, y2); } } } } } ff_subtitles_queue_finalize(&srt->q); end: av_bprint_finalize(&buf, NULL); return res; }
char* parsePTStoString(uint8_t *ptsin){ //uint64_t ptsticks = (((ptsin[0] & 0x0E) >> 1) <<32)| ((ptsin[1]) << 24) | ((ptsin[2] & 0xFE) << 16) | ((ptsin[3]) << 8) | ((ptsin[4]) & 0xFE); uint64_t ptsticks = get_pts(ptsin); uint64_t ptstotalseconds = ptsticks / 90; uint32_t pts_ms = ptstotalseconds % 1000; uint32_t pts_s = ((ptstotalseconds - pts_ms) / 1000) % 60; uint32_t pts_m = ((ptstotalseconds - pts_ms - (pts_s*1000)) / 1000 / 60) % 60; uint32_t pts_h = ((ptstotalseconds - pts_ms - (pts_s*1000) - (pts_m*60*1000)) / 1000 / 60 / 60); if ((pts_ms % 10) > 4){ pts_ms = pts_ms + (10-pts_ms%10); } else { pts_ms = pts_ms - (pts_ms%10); } pts_ms=pts_ms/10; if (pts_ms == 100){ pts_s++; pts_ms = 0; if (pts_s >= 60){ pts_m++; pts_s=0; if (pts_m >= 60){ pts_h++; pts_m=0; } } } char* outstr = malloc(100 * sizeof(char)); snprintf(outstr,100,"%02d:%02d:%02d.%02d",pts_h,pts_m,pts_s,pts_ms); #ifdef DEBUG_PTS printf("debug: %X %X %X %X %X : %u : %d %d %d %d\n",ptsin[0],ptsin[1],ptsin[2],ptsin[3],ptsin[4],ptstotalseconds,pts_ms,pts_s,pts_m,pts_h); printf("outstr: %s\n",outstr); #endif return outstr; }
static int microdvd_read_header(AVFormatContext *s) { AVRational pts_info = (AVRational){ 2997, 125 }; /* default: 23.976 fps */ MicroDVDContext *microdvd = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); int i = 0; char line[MAX_LINESIZE]; if (!st) return AVERROR(ENOMEM); while (!url_feof(s->pb)) { AVPacket *sub; int64_t pos = avio_tell(s->pb); int len = ff_get_line(s->pb, line, sizeof(line)); if (!len) break; if (i < 3) { int frame; double fps; char c; i++; if ((sscanf(line, "{%d}{}%6lf", &frame, &fps) == 2 || sscanf(line, "{%d}{%*d}%6lf", &frame, &fps) == 2) && frame <= 1 && fps > 3 && fps < 100) pts_info = av_d2q(fps, 100000); if (!st->codec->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) { st->codec->extradata = av_strdup(line + 11); if (!st->codec->extradata) return AVERROR(ENOMEM); st->codec->extradata_size = strlen(st->codec->extradata) + 1; continue; } } sub = ff_subtitles_queue_insert(µdvd->q, line, len, 0); if (!sub) return AVERROR(ENOMEM); sub->pos = pos; sub->pts = get_pts(sub->data); sub->duration = get_duration(sub->data); } ff_subtitles_queue_finalize(µdvd->q); avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_MICRODVD; return 0; }
static int text_read_packet(AVFormatContext *s, AVPacket *pkt) { char buffer[2048], *ptr = buffer, *ptr2, *prt3; char data[1024] = {0}; int64_t pos = avio_tell(s->pb); int res = AVERROR_EOF; do { ptr2 = ptr; ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr); } while(is_eol(*ptr2) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1); do { prt3 = ptr; ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr); } while(is_eol(*prt3) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1); if (buffer[0]) { int64_t pts; int duration; const char *end = ptr; ptr = buffer; pts = get_pts(&ptr, &duration, data); if (pts != AV_NOPTS_VALUE && !(res = av_new_packet(pkt, strlen(data)))) { memcpy(pkt->data, data, strlen(data)); memset(data, 0, 1024); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = pkt->dts = pts; pkt->duration = duration; } } return res; }
static int srt_read_packet(AVFormatContext *s, AVPacket *pkt) { char buffer[2048], *ptr = buffer, *ptr2; int64_t pos = avio_tell(s->pb); int res = AVERROR_EOF; do { ptr2 = ptr; ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr); } while (!is_eol(*ptr2) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1); if (buffer[0] && !(res = av_new_packet(pkt, ptr-buffer))) { memcpy(pkt->data, buffer, pkt->size); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = pkt->dts = get_pts(pkt->data); } return res; }
static int read_packet(AVFormatContext *s, AVPacket *pkt) { ASSContext *ass = s->priv_data; uint8_t *p, *end; if(ass->event_index >= ass->event_count) return AVERROR(EIO); p= ass->event[ ass->event_index ]; end= strchr(p, '\n'); av_new_packet(pkt, end ? end-p+1 : strlen(p)); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos= p - ass->event_buffer + s->streams[0]->codec->extradata_size; pkt->pts= pkt->dts= get_pts(p); memcpy(pkt->data, p, pkt->size); ass->event_index++; return 0; }
static int read_seek2(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) { ASSContext *ass = s->priv_data; if (flags & AVSEEK_FLAG_BYTE) { return AVERROR(ENOSYS); } else if (flags & AVSEEK_FLAG_FRAME) { if (ts < 0 || ts >= ass->event_count) return AVERROR(ERANGE); ass->event_index = ts; } else { int i, idx = -1; int64_t min_ts_diff = INT64_MAX; if (stream_index == -1) { AVRational time_base = s->streams[0]->time_base; ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base); min_ts = av_rescale_rnd(min_ts, time_base.den, time_base.num * (int64_t)AV_TIME_BASE, AV_ROUND_UP); max_ts = av_rescale_rnd(max_ts, time_base.den, time_base.num * (int64_t)AV_TIME_BASE, AV_ROUND_DOWN); } /* TODO: ass->event[] is sorted by pts so we could do a binary search */ for (i=0; i<ass->event_count; i++) { int64_t pts = get_pts(ass->event[i]); int64_t ts_diff = FFABS(pts - ts); if (pts >= min_ts && pts <= max_ts && ts_diff < min_ts_diff) { min_ts_diff = ts_diff; idx = i; } } if (idx < 0) return AVERROR(ERANGE); ass->event_index = idx; } return 0; }
static int srt_read_packet(AVFormatContext *s, AVPacket *pkt) { char buffer[2048], *ptr = buffer, *ptr2; int64_t pos = avio_tell(s->pb); int res = AVERROR_EOF; do { ptr2 = ptr; ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr); } while (!is_eol(*ptr2) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1); if (buffer[0]) { int64_t pts; int duration; const char *end = ptr; int32_t x1 = -1, y1 = -1, x2 = -1, y2 = -1; ptr = buffer; pts = get_pts(&ptr, &duration, &x1, &y1, &x2, &y2); if (pts != AV_NOPTS_VALUE && !(res = av_new_packet(pkt, end - ptr))) { memcpy(pkt->data, ptr, pkt->size); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = pkt->dts = pts; pkt->duration = duration; if (x1 != -1) { uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SUBTITLE_POSITION, 16); if (p) { AV_WL32(p, x1); AV_WL32(p + 4, y1); AV_WL32(p + 8, x2); AV_WL32(p + 12, y2); } } } } return res; }
static int stl_read_header(AVFormatContext *s) { STLContext *stl = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, 100); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_STL; while (!avio_feof(s->pb)) { char line[4096]; char *p = line; const int64_t pos = avio_tell(s->pb); int len = ff_get_line(s->pb, line, sizeof(line)); int64_t pts_start; int duration; if (!len) break; line[strcspn(line, "\r\n")] = 0; pts_start = get_pts(&p , &duration); if (pts_start != AV_NOPTS_VALUE) { AVPacket *sub; sub = ff_subtitles_queue_insert(&stl->q, p, strlen(p), 0); if (!sub) return AVERROR(ENOMEM); sub->pos = pos; sub->pts = pts_start; sub->duration = duration; } } ff_subtitles_queue_finalize(&stl->q); return 0; }
int vid_event_wait_next(eventq_type_t * type, void **info) { event_queue_t *ret = NULL; pthread_mutex_lock(&videvents_mutex); /* NB pts are clocked at 90kHz */ while(ret == NULL) { unsigned int pts = get_pts(); /*Anything less than 1 (NTSC) frame should count as now */ unsigned int max_pts = pts + (PTS_HZ/30) -1; /*Assume anything less than 30 seconds behind us counts as now*/ unsigned int seek_pts = pts - PTS_HZ*30; /*And anything more than 40 seconds ahead we don't really need to worry about*/ unsigned int max_seek_pts = pts + PTS_HZ*40; event_queue_t *pCurrent = pNextEvent; event_queue_t *pStart; PRINTF("VEQ: Looking for a worthwhile elem: %p\n",pCurrent); if(pCurrent != NULL) { /*Find first event after seek_pts and before max_seek_pts */ pStart = pCurrent; /*First move to an element before seek_pts, if it exists */ while(pCurrent->pts >= seek_pts) { pCurrent = pCurrent->pPrev; /*The smallest element is the best we can get. Even if it * is greater than seek_pts, there's not going to be another * one that is less. */ if(pCurrent->pPrev->pts > pCurrent->pts) break; /*We went all the way around, probably only one item */ if(pCurrent == pStart) break; } pStart = pCurrent; /* Now move forward to the first element after this that is * >= seek_pts */ while(pCurrent->pts < seek_pts) { pCurrent = pCurrent->pNext; /*Numbers can't get any bigger if we're about to wrap * around */ if(pCurrent->pNext->pts < pCurrent->pts) break; /*We went all the way around, probably only one item */ if(pCurrent == pStart) break; } /*Check if the element we've found is between seek_pts and * max_seek_pts */ if(seek_pts > max_seek_pts) { /* PTS is about to/has wrapped around, maths is a bit different */ if(pCurrent->pts < seek_pts && pCurrent->pts > max_seek_pts) pCurrent = NULL; } else { if(pCurrent->pts < seek_pts || pCurrent->pts > max_seek_pts) pCurrent = NULL; } } /*Check if the element is before 1 frame from now, if that's the * case then dispatch the event */ PRINTF("VEQ: Found elem: %p\n",pCurrent); if(pCurrent != NULL && (pCurrent->pts <= max_pts ||(seek_pts > max_pts && pCurrent->pts >= seek_pts))) { ret = pCurrent; PRINTF("VEQ: returning %p\n",ret); } else { int to_wait; struct timespec abstime; /*Never wait any more than 10 seconds*/ int max_wait; if(pts_discontinuity_count > 0) { pts_discontinuity_count--; max_wait = VID_EVENT_DISCON_MAX_WAIT; } else max_wait = VID_EVENT_MAX_WAIT; if(pCurrent != NULL) { if(pCurrent->pts > pts) to_wait = pCurrent->pts - pts; else /* Bitwise not of pts is the same as 0xFFFFFFFF - pts */ to_wait = (~pts) + pCurrent->pts; /* Exponentially approach the pts we're after*/ to_wait = (to_wait*8)/10; if(to_wait > max_wait) to_wait = max_wait; } else to_wait = max_wait; clock_gettime(CLOCK_REALTIME,&abstime); abstime.tv_nsec += ((to_wait%PTS_HZ) *(1000000000/PTS_HZ)); while(abstime.tv_nsec >= 1000000000) { abstime.tv_sec++; abstime.tv_nsec -= 1000000000; } abstime.tv_sec += to_wait/PTS_HZ; PRINTF("VEQ: Waiting for %d pts clocks, until sec %lu\n",to_wait,(unsigned long)abstime.tv_sec); pthread_cond_timedwait(&videvents_cond,&videvents_mutex,&abstime); PRINTF("VEQ: I'm awake now...\n"); } if(ret != NULL) { PRINTF("Dispatching event for pts %x at pts %x (seek %x, seek_max %x)\n",ret->pts,pts,seek_pts,max_seek_pts); } } int retval; if(ret == NULL) { /* Shouldn't happen... */ retval = -1; } else { *type = ret->type; *info = ret->info; if(ret->pNext == ret) { /*1 item in the queue*/ pNextEvent = NULL; } else { if(pNextEvent == ret) pNextEvent = ret->pNext; ret->pPrev->pNext = ret->pNext; ret->pNext->pPrev = ret->pPrev; } free(ret); retval = 0; } pthread_mutex_unlock(&videvents_mutex); return retval; }
static void* reader_thread(void * /*arg*/) { int fds[2]; pipe(fds); fcntl(fds[0], F_SETFD, FD_CLOEXEC); fcntl(fds[0], F_SETFL, O_NONBLOCK); fcntl(fds[1], F_SETFD, FD_CLOEXEC); fcntl(fds[1], F_SETFL, O_NONBLOCK); flagFd = fds[1]; uint8_t tmp[16]; /* actually 6 should be enough */ int count; int len; uint16_t packlen; uint8_t* buf; bool bad_startcode = false; set_threadname("dvbsub:reader"); dmx = new cDemux(0); #if HAVE_TRIPLEDRAGON dmx->Open(DMX_PES_CHANNEL, NULL, 16*1024); #else dmx->Open(DMX_PES_CHANNEL, NULL, 64*1024); #endif while (reader_running) { if(dvbsub_stopped /*dvbsub_paused*/) { sub_debug.print(Debug::VERBOSE, "%s stopped\n", __FUNCTION__); dmx->Stop(); pthread_mutex_lock(&packetMutex); pthread_cond_broadcast(&packetCond); pthread_mutex_unlock(&packetMutex); pthread_mutex_lock(&readerMutex ); int ret = pthread_cond_wait(&readerCond, &readerMutex); pthread_mutex_unlock(&readerMutex); if (ret) { sub_debug.print(Debug::VERBOSE, "pthread_cond_timedwait fails with %d\n", ret); } if(!reader_running) break; dvbsub_stopped = 0; sub_debug.print(Debug::VERBOSE, "%s (re)started with pid 0x%x\n", __FUNCTION__, dvbsub_pid); } if(pid_change_req) { pid_change_req = 0; clear_queue(); dmx->Stop(); dmx->pesFilter(dvbsub_pid); dmx->Start(); sub_debug.print(Debug::VERBOSE, "%s changed to pid 0x%x\n", __FUNCTION__, dvbsub_pid); } struct pollfd pfds[2]; pfds[0].fd = fds[1]; pfds[0].events = POLLIN; char _tmp[64]; #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE if (isEplayer) { poll(pfds, 1, -1); while (0 > read(pfds[0].fd, _tmp, sizeof(tmp))); continue; } #endif pfds[1].fd = dmx->getFD(); pfds[1].events = POLLIN; switch (poll(pfds, 2, -1)) { case 0: case -1: if (pfds[0].revents & POLLIN) while (0 > read(pfds[0].fd, _tmp, sizeof(tmp))); continue; default: if (pfds[0].revents & POLLIN) while (0 > read(pfds[0].fd, _tmp, sizeof(tmp))); if (!(pfds[1].revents & POLLIN)) continue; } len = dmx->Read(tmp, 6, 0); if(len <= 0) continue; if(!memcmp(tmp, "\x00\x00\x01\xbe", 4)) { // padding stream packlen = getbits(tmp, 4*8, 16) + 6; count = 6; buf = (uint8_t*) malloc(packlen); // actually, we're doing slightly too much here ... memmove(buf, tmp, 6); /* read rest of the packet */ while((count < packlen) && !dvbsub_stopped) { len = dmx->Read(buf+count, packlen-count, 1000); if (len < 0) { break; } else { count += len; } } free(buf); buf = NULL; continue; } if(memcmp(tmp, "\x00\x00\x01\xbd", 4)) { if (!bad_startcode) { sub_debug.print(Debug::VERBOSE, "[subtitles] bad start code: %02x%02x%02x%02x\n", tmp[0], tmp[1], tmp[2], tmp[3]); bad_startcode = true; } continue; } bad_startcode = false; count = 6; packlen = getbits(tmp, 4*8, 16) + 6; buf = (uint8_t*) malloc(packlen); memmove(buf, tmp, 6); /* read rest of the packet */ while((count < packlen) && !dvbsub_stopped) { len = dmx->Read(buf+count, packlen-count, 1000); if (len < 0) { break; } else { count += len; } } #if 0 for(int i = 6; i < packlen - 4; i++) { if(!memcmp(&buf[i], "\x00\x00\x01\xbd", 4)) { int plen = getbits(&buf[i], 4*8, 16) + 6; sub_debug.print(Debug::VERBOSE, "[subtitles] ******************* PES header at %d ?! *******************\n", i); sub_debug.print(Debug::VERBOSE, "[subtitles] start code: %02x%02x%02x%02x len %d\n", buf[i+0], buf[i+1], buf[i+2], buf[i+3], plen); free(buf); continue; } } #endif if(!dvbsub_stopped /*!dvbsub_paused*/) { sub_debug.print(Debug::VERBOSE, "[subtitles] *** new packet, len %d buf 0x%x pts-stc diff %lld ***\n", count, buf, get_pts_stc_delta(get_pts(buf))); /* Packet now in memory */ pthread_mutex_lock(&packetMutex); packet_queue.push(buf); /* TODO: allocation exception */ // wake up dvb thread pthread_cond_broadcast(&packetCond); pthread_mutex_unlock(&packetMutex); } else { free(buf); buf=NULL; } } dmx->Stop(); delete dmx; dmx = NULL; close(fds[0]); close(fds[1]); flagFd = -1; sub_debug.print(Debug::VERBOSE, "%s shutdown\n", __FUNCTION__); pthread_exit(NULL); }
static int microdvd_read_header(AVFormatContext *s) { AVRational pts_info = (AVRational){ 2997, 125 }; /* default: 23.976 fps */ MicroDVDContext *microdvd = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); int i = 0; char line[MAX_LINESIZE]; if (!st) return AVERROR(ENOMEM); while (!url_feof(s->pb)) { char *p = line; AVPacket *sub; int64_t pos = avio_tell(s->pb); int len = ff_get_line(s->pb, line, sizeof(line)); if (!len) break; line[strcspn(line, "\r\n")] = 0; if (i++ < 3) { int frame; double fps; char c; if ((sscanf(line, "{%d}{}%6lf", &frame, &fps) == 2 || sscanf(line, "{%d}{%*d}%6lf", &frame, &fps) == 2) && frame <= 1 && fps > 3 && fps < 100) pts_info = av_d2q(fps, 100000); if (!st->codec->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) { st->codec->extradata = av_strdup(line + 11); if (!st->codec->extradata) return AVERROR(ENOMEM); st->codec->extradata_size = strlen(st->codec->extradata) + 1; continue; } } #define SKIP_FRAME_ID \ p = strchr(p, '}'); \ if (!p) { \ av_log(s, AV_LOG_WARNING, "Invalid event \"%s\"" \ " at line %d\n", line, i); \ continue; \ } \ p++ SKIP_FRAME_ID; SKIP_FRAME_ID; if (!*p) continue; sub = ff_subtitles_queue_insert(µdvd->q, p, strlen(p), 0); if (!sub) return AVERROR(ENOMEM); sub->pos = pos; sub->pts = get_pts(line); sub->duration = get_duration(line); } ff_subtitles_queue_finalize(µdvd->q); avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_MICRODVD; return 0; }
void remove_nodes(Bface_list& flist, ARRAY<Wvec>& blist, double min_dist, ARRAY<OctreeNode*>& t) { // if (flist.num() != blist.num()) { // return; // } assert(flist.num() == blist.num()); Wpt_list pts = get_pts(flist, blist); ARRAY< ARRAY<int> > N; ARRAY<bool> to_remove; for (int i = 0; i < pts.num(); i++) { N += ARRAY<int>(); to_remove += false; } for (int i = 0; i < pts.num(); i++) { for (int j = 0; j < t[i]->neibors().num(); j++) { int index = t[i]->neibors()[j]->get_term_index(); if (index < pts.num()) { if (pts[i].dist(pts[index]) < min_dist) { N[i] += index; N[index] += i; } } else { //cerr << "Sps Warning, index > pts.num()" << endl; } } } priority_queue< Priority, vector<Priority> > queue; ARRAY<int> versions; for (int i = 0; i < pts.num(); i++) { if (!to_remove[i] && !N[i].empty()) { Priority p; p._priority = center(pts, N[i]).dist(pts[i]); p._index = i; p._version = 0; queue.push(p); } versions += 0; } while (!queue.empty()) { Priority p = queue.top(); queue.pop(); int r = p._index; if (p._version == versions[r]) { to_remove[r] = true; for (int i = 0; i < N[r].num(); i++) { N[N[r][i]] -= r; versions[N[r][i]]++; if (!N[N[r][i]].empty()) { Priority q; q._priority = center(pts, N[N[r][i]]).dist(pts[N[r][i]]); q._index = N[r][i]; q._version = versions[N[r][i]]; queue.push(q); } } } } versions.clear(); Bface_list ftemp(flist); ARRAY<Wvec> btemp(blist); flist.clear(); blist.clear(); for (int i = 0; i < ftemp.num(); i++) if (!to_remove[i]) { flist += ftemp[i]; blist += btemp[i]; } }
static int read_header(AVFormatContext *s) { int i, len, header_remaining; ASSContext *ass = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; int allocated[2]= {0}; uint8_t *p, **dst[2]= {0}; int pos[2]= {0}; st = avformat_new_stream(s, NULL); if (!st) return -1; avpriv_set_pts_info(st, 64, 1, 100); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id= AV_CODEC_ID_SSA; header_remaining= INT_MAX; dst[0] = &st->codec->extradata; dst[1] = &ass->event_buffer; while(!pb->eof_reached) { uint8_t line[MAX_LINESIZE]; len = ff_get_line(pb, line, sizeof(line)); if(!memcmp(line, "[Events]", 8)) header_remaining= 2; else if(line[0]=='[') header_remaining= INT_MAX; i= header_remaining==0; if(i && get_pts(line) == AV_NOPTS_VALUE) continue; p = av_fast_realloc(*(dst[i]), &allocated[i], pos[i]+MAX_LINESIZE); if(!p) goto fail; *(dst[i])= p; memcpy(p + pos[i], line, len+1); pos[i] += len; if(i) ass->event_count++; else header_remaining--; } st->codec->extradata_size= pos[0]; if(ass->event_count >= UINT_MAX / sizeof(*ass->event)) goto fail; ass->event= av_malloc(ass->event_count * sizeof(*ass->event)); p= ass->event_buffer; for(i=0; i<ass->event_count; i++) { ass->event[i]= p; while(*p && *p != '\n') p++; p++; } qsort(ass->event, ass->event_count, sizeof(*ass->event), (void*)event_cmp); return 0; fail: read_close(s); return -1; }
static int event_cmp(uint8_t **a, uint8_t **b) { return get_pts(*a) - get_pts(*b); }
static int dhav_read_packet(AVFormatContext *s, AVPacket *pkt) { DHAVContext *dhav = s->priv_data; int64_t start; int ret; start = avio_tell(s->pb); while ((ret = read_chunk(s)) == 0) ; if (ret < 0) return ret; if (dhav->type == 0xfd && dhav->video_stream_index == -1) { AVStream *st = avformat_new_stream(s, NULL); DHAVStream *dst; if (!st) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; switch (dhav->video_codec) { case 0x1: st->codecpar->codec_id = AV_CODEC_ID_MPEG4; break; case 0x3: st->codecpar->codec_id = AV_CODEC_ID_MJPEG; break; case 0x2: case 0x4: case 0x8: st->codecpar->codec_id = AV_CODEC_ID_H264; break; case 0xc: st->codecpar->codec_id = AV_CODEC_ID_HEVC; break; default: avpriv_request_sample(s, "Unknown video codec %X\n", dhav->video_codec); } st->codecpar->width = dhav->width; st->codecpar->height = dhav->height; st->avg_frame_rate.num = dhav->frame_rate; st->avg_frame_rate.den = 1; st->priv_data = dst = av_mallocz(sizeof(DHAVStream)); if (!st->priv_data) return AVERROR(ENOMEM); dst->last_timestamp = AV_NOPTS_VALUE; dhav->video_stream_index = st->index; avpriv_set_pts_info(st, 64, 1, 1000); } else if (dhav->type == 0xf0 && dhav->audio_stream_index == -1) { AVStream *st = avformat_new_stream(s, NULL); DHAVStream *dst; if (!st) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; switch (dhav->audio_codec) { case 0x07: st->codecpar->codec_id = AV_CODEC_ID_PCM_S8; break; case 0x0c: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; break; case 0x10: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; break; case 0x0a: st->codecpar->codec_id = AV_CODEC_ID_PCM_MULAW; break; case 0x16: st->codecpar->codec_id = AV_CODEC_ID_PCM_MULAW; break; case 0x0e: st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW; break; case 0x1a: st->codecpar->codec_id = AV_CODEC_ID_AAC; break; case 0x1f: st->codecpar->codec_id = AV_CODEC_ID_MP2; break; case 0x21: st->codecpar->codec_id = AV_CODEC_ID_MP3; break; case 0x0d: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_MS; break; default: avpriv_request_sample(s, "Unknown audio codec %X\n", dhav->audio_codec); } st->codecpar->channels = dhav->audio_channels; st->codecpar->sample_rate = dhav->sample_rate; st->priv_data = dst = av_mallocz(sizeof(DHAVStream)); if (!st->priv_data) return AVERROR(ENOMEM); dst->last_timestamp = AV_NOPTS_VALUE; dhav->audio_stream_index = st->index; avpriv_set_pts_info(st, 64, 1, 1000); } ret = av_get_packet(s->pb, pkt, ret); if (ret < 0) return ret; pkt->stream_index = dhav->type == 0xf0 ? dhav->audio_stream_index : dhav->video_stream_index; if (dhav->type != 0xfc) pkt->flags |= AV_PKT_FLAG_KEY; if (pkt->stream_index >= 0) pkt->pts = get_pts(s, s->streams[pkt->stream_index]->priv_data); pkt->duration = 1; pkt->pos = start; if (avio_rl32(s->pb) != MKTAG('d','h','a','v')) return AVERROR_INVALIDDATA; avio_skip(s->pb, 4); return ret; }
static void* dvbsub_thread(void* /*arg*/) { struct timespec restartWait; struct timeval now; sub_debug.print(Debug::VERBOSE, "%s started\n", __FUNCTION__); if (!dvbSubtitleConverter) dvbSubtitleConverter = new cDvbSubtitleConverter; int timeout = 1000000; while(dvbsub_running) { uint8_t* packet; int64_t pts; int dataoffset; int packlen; gettimeofday(&now, NULL); int ret = 0; now.tv_usec += (timeout == 0) ? 1000000 : timeout; // add the timeout while (now.tv_usec >= 1000000) { // take care of an overflow now.tv_sec++; now.tv_usec -= 1000000; } restartWait.tv_sec = now.tv_sec; // seconds restartWait.tv_nsec = now.tv_usec * 1000; // nano seconds pthread_mutex_lock( &packetMutex ); ret = pthread_cond_timedwait( &packetCond, &packetMutex, &restartWait ); pthread_mutex_unlock( &packetMutex ); timeout = dvbSubtitleConverter->Action(); if(packet_queue.size() == 0) { continue; } #if 1 sub_debug.print(Debug::VERBOSE, "PES: Wakeup, queue size %d\n\n", packet_queue.size()); #endif if(dvbsub_stopped /*dvbsub_paused*/) { clear_queue(); continue; } pthread_mutex_lock(&packetMutex); packet = packet_queue.pop(); pthread_mutex_unlock(&packetMutex); if (!packet) { sub_debug.print(Debug::VERBOSE, "Error no packet found\n"); continue; } packlen = (packet[4] << 8 | packet[5]) + 6; pts = get_pts(packet); dataoffset = packet[8] + 8 + 1; if (packet[dataoffset] != 0x20) { #if 1 sub_debug.print(Debug::VERBOSE, "Not a dvb subtitle packet, discard it (len %d)\n", packlen); for(int i = 0; i < packlen; i++) printf("%02X ", packet[i]); printf("\n"); #endif goto next_round; } #if 1 sub_debug.print(Debug::VERBOSE, "PES packet: len %d data len %d PTS=%Ld (%02d:%02d:%02d.%d) diff %lld\n", packlen, packlen - (dataoffset + 2), pts, (int)(pts/324000000), (int)((pts/5400000)%60), (int)((pts/90000)%60), (int)(pts%90000), get_pts_stc_delta(pts)); #endif if (packlen <= dataoffset + 3) { sub_debug.print(Debug::INFO, "Packet too short, discard\n"); goto next_round; } if (packet[dataoffset + 2] == 0x0f) { dvbSubtitleConverter->Convert(&packet[dataoffset + 2], packlen - (dataoffset + 2), pts); } else { sub_debug.print(Debug::INFO, "End_of_PES is missing\n"); } timeout = dvbSubtitleConverter->Action(); next_round: free(packet); } delete dvbSubtitleConverter; sub_debug.print(Debug::VERBOSE, "%s shutdown\n", __FUNCTION__); pthread_exit(NULL); }
static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt) { MicroDVDContext *microdvd = s->priv_data; char buffer[MAX_LINESIZE]; int64_t pos = avio_tell(s->pb); int i, len = 0, res = AVERROR_EOF; // last packet has its duration set but couldn't be raised earlier if (microdvd->last_pkt_ready) { *pkt = microdvd->last_pkt; microdvd->last_pkt_ready = 0; return 0; } for (i=0; i<FF_ARRAY_ELEMS(microdvd->lines); i++) { if (microdvd->lines[i][0]) { strcpy(buffer, microdvd->lines[i]); pos = microdvd->pos[i]; len = strlen(buffer); microdvd->lines[i][0] = 0; break; } } if (!len) len = ff_get_line(s->pb, buffer, sizeof(buffer)); if (microdvd->last_pkt.duration == -1 && !buffer[0]) { // if the previous subtitle line had no duration, last until the end of // the presentation microdvd->last_pkt.duration = 0; *pkt = microdvd->last_pkt; pkt->duration = -1; res = 0; } else if (buffer[0] && !(res = av_new_packet(pkt, len))) { memcpy(pkt->data, buffer, len); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = pkt->dts = get_pts(buffer); if (pkt->pts != AV_NOPTS_VALUE) { pkt->duration = get_duration(buffer); if (microdvd->last_pkt.duration == -1) { // previous packet wasn't raised because it was lacking the // duration info, so set its duration with the new packet pts // and raise it AVPacket tmp_pkt; tmp_pkt = microdvd->last_pkt; tmp_pkt.duration = pkt->pts - tmp_pkt.pts; microdvd->last_pkt = *pkt; microdvd->last_pkt_ready = pkt->duration != -1; *pkt = tmp_pkt; } else if (pkt->duration == -1) { // no packet without duration queued, and current one is // lacking the duration info, we need to parse another subtitle // event. microdvd->last_pkt = *pkt; res = AVERROR(EAGAIN); } } } return res; }
static int read_header(AVFormatContext *s, AVFormatParameters *ap) { int i, header_remaining; ASSContext *ass = s->priv_data; ByteIOContext *pb = s->pb; AVStream *st; int allocated[2]={0}; uint8_t *p, **dst[2]={0}; int pos[2]={0}; st = av_new_stream(s, 0); if (!st) return -1; av_set_pts_info(st, 64, 1, 100); st->codec->codec_type = CODEC_TYPE_SUBTITLE; st->codec->codec_id= CODEC_ID_SSA; header_remaining= INT_MAX; dst[0] = &st->codec->extradata; dst[1] = &ass->event_buffer; while(!url_feof(pb)){ uint8_t line[MAX_LINESIZE]; get_line(pb, line, sizeof(line)); if(!memcmp(line, "[Events]", 8)) header_remaining= 2; else if(line[0]=='[') header_remaining= INT_MAX; i= header_remaining==0; if(i && get_pts(line, NULL) == AV_NOPTS_VALUE) continue; p = av_fast_realloc(*(dst[i]), &allocated[i], pos[i]+MAX_LINESIZE); if(!p) goto fail; *(dst[i])= p; memcpy(p + pos[i], line, strlen(line)+1); pos[i] += strlen(line); if(i) ass->event_count++; else { header_remaining--; #if 0 if (!header_remaining) { /* write the header into extrada section */ int len = url_ftell(pb); st->codec->extradata = av_mallocz(len + 1); st->codec->extradata_size = len; url_fseek(pb, 0, SEEK_SET); get_buffer(pb, st->codec->extradata, len); } #endif } } st->codec->extradata_size= pos[0]; if(ass->event_count >= UINT_MAX / sizeof(*ass->event)) goto fail; ass->event= av_malloc(ass->event_count * sizeof(*ass->event)); p= ass->event_buffer; for(i=0; i<ass->event_count; i++){ ass->event[i].text= p; ass->event[i].start_time= get_pts(p, &ass->event[i].end_time); while(*p && *p != '\n') p++; p++; } qsort(ass->event, ass->event_count, sizeof(*ass->event), event_cmp); return 0; fail: read_close(s); return -1; }
static int event_cmp(const void *_a, const void *_b) { const uint8_t *const *a = _a, *const *b = _b; return get_pts(*a) - get_pts(*b); }