struct obex_mime_type_driver *obex_mime_type_driver_find(const uint8_t *target, unsigned int target_size, const char *mimetype, const uint8_t *who, unsigned int who_size) { struct obex_mime_type_driver *driver; driver = find_driver(target, target_size, mimetype, who, who_size); if (driver == NULL) { if (who != NULL) { /* Fallback to non-who specific */ driver = find_driver(target, target_size, mimetype, NULL, 0); if (driver != NULL) return driver; } if (mimetype != NULL) /* Fallback to target default */ driver = find_driver(target, target_size, NULL, NULL, 0); if (driver == NULL) /* Fallback to general default */ driver = find_driver(NULL, 0, NULL, NULL, 0); } return driver; }
CRYSTAX_LOCAL int open(const char *path, int oflag, va_list &vl) { DBG("path=%s, oflag=%d (%s)", path, oflag, mode_s(oflag)); driver_t *driver = find_driver(path); if (!driver) return -1; DBG("use driver %s (%s)", driver->name(), driver->info()); int extfd = driver->open(path, oflag, vl); DBG("extfd=%d", extfd); if (extfd == -1) return -1; int fd = alloc_fd(path, extfd, driver); if (fd < 0) { ERR("can't alloc fd, return -1"); driver->close(extfd); errno = EMFILE; return -1; } DBG("return fd=%d", fd); return fd; }
CRYSTAX_LOCAL int symlink(const char *src, const char *dst) { DBG("src=%s, dst=%s", src, dst); driver_t *driver = find_driver(src); driver_t *driver2 = find_driver(dst); if (driver != driver2) { ERR("symlink across sources not supported yet"); errno = EXDEV; return -1; } return driver->symlink(src, dst); }
static struct snobj *handle_create_port(struct snobj *arg) { const char *driver_name; const struct driver *driver; struct port *port; struct snobj *r; struct snobj *err; driver_name = snobj_eval_str(arg, "driver"); if (!driver_name) return snobj_err(EINVAL, "Missing 'driver' field in arg"); driver = find_driver(driver_name); if (!driver) return snobj_err(ENOENT, "No port driver '%s' found", driver_name); port = create_port(snobj_eval_str(arg, "name"), driver, snobj_eval(arg, "arg"), &err); if (!port) return err; printf("Port %s created at %p\n", port->name, port); r = snobj_map(); snobj_map_set(r, "name", snobj_str(port->name)); return r; }
CRYSTAX_LOCAL int lstat(const char *path, struct stat *st) { DBG("path=%s, st=%p", path, st); driver_t *driver = find_driver(path); if (!driver) return -1; return driver->lstat(path, st); }
CRYSTAX_LOCAL int rmdir(const char *path) { DBG("path=%s", path); driver_t *driver = find_driver(path); if (!driver) return -1; return driver->rmdir(path); }
CRYSTAX_LOCAL int readlink(const char *path, char *buf, size_t bufsize) { DBG("path=%s, buf=%p, bufsize=%lu", path, buf, (unsigned long)bufsize); driver_t *driver = find_driver(path); if (!driver) return -1; return driver->readlink(path, buf, bufsize); }
CRYSTAX_LOCAL int chown(const char *path, uid_t uid, gid_t gid) { DBG("path=%s, uid=%u, gid=%u", path, (unsigned)uid, (unsigned)gid); driver_t *driver = find_driver(path); if (!driver) return -1; return driver->chown(path, uid, gid); }
/* * pccard_add_driver - Add a new driver to the list of * drivers available for allocation. */ void pccard_add_driver(struct pccard_drv *dp) { /* * If already loaded, then reject the driver. */ if (find_driver(dp->name)) { printf("Driver %s already loaded\n", dp->name); return; } printf("pccard driver %s added\n", dp->name); dp->next = drivers; drivers = dp; }
int audio_init_best_codec(struct dec_audio *d_audio, char *audio_decoders) { assert(!d_audio->ad_driver); audio_reset_decoding(d_audio); struct mp_decoder_entry *decoder = NULL; struct mp_decoder_list *list = audio_select_decoders(d_audio->header->codec, audio_decoders); mp_print_decoders(MSGT_DECAUDIO, MSGL_V, "Codec list:", list); for (int n = 0; n < list->num_entries; n++) { struct mp_decoder_entry *sel = &list->entries[n]; const struct ad_functions *driver = find_driver(sel->family); if (!driver) continue; mp_msg(MSGT_DECAUDIO, MSGL_V, "Opening audio decoder %s:%s\n", sel->family, sel->decoder); d_audio->ad_driver = driver; if (init_audio_codec(d_audio, sel->decoder)) { decoder = sel; break; } mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Audio decoder init failed for " "%s:%s\n", sel->family, sel->decoder); } if (d_audio->ad_driver) { d_audio->decoder_desc = talloc_asprintf(d_audio, "%s [%s:%s]", decoder->desc, decoder->family, decoder->decoder); mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Selected audio codec: %s\n", d_audio->decoder_desc); mp_msg(MSGT_DECAUDIO, MSGL_V, "AUDIO: %d Hz, %d ch, %s\n", d_audio->decoded.rate, d_audio->decoded.channels.num, af_fmt_to_str(d_audio->decoded.format)); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n", d_audio->i_bps * 8, d_audio->decoded.rate, d_audio->decoded.channels.num); } else { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Failed to initialize an audio decoder for codec '%s'.\n", d_audio->header->codec ? d_audio->header->codec : "<unknown>"); } talloc_free(list); return !!d_audio->ad_driver; }
static dentry_t* devfs_lookup(struct _fs_instance_t *instance, struct _dentry_t* dentry, const char * name) { //TODO: gérer dentry pour avoir des sous-dossiers. driver_entry *drentry = find_driver(name); if (drentry != NULL) { inode_t *inode = kmalloc(sizeof(inode_t)); inode->i_ino = 42; //XXX inode->i_mode = 0755; inode->i_uid = 0; inode->i_gid = 0; inode->i_size = 0; inode->i_atime = inode->i_ctime = inode->i_mtime = inode->i_dtime = 0; // XXX inode->i_nlink = 1; inode->i_blocks = 1; inode->i_count = 0; inode->i_instance = instance; inode->i_fops = kmalloc(sizeof(open_file_operations_t)); inode->i_fs_specific = (chardev_interfaces*)(drentry->di); switch(drentry->type) { case CHARDEV: inode->i_fops->readdir = NULL; inode->i_fops->open = ((chardev_interfaces*)(drentry->di))->open; inode->i_fops->write = ((chardev_interfaces*)(drentry->di))->write; inode->i_fops->read = ((chardev_interfaces*)(drentry->di))->read; inode->i_fops->seek = NULL; /* à implémenter */ inode->i_fops->close = ((chardev_interfaces*)(drentry->di))->close; inode->i_fops->ioctl = ((chardev_interfaces*)(drentry->di))->ioctl; break; case BLKDEV: inode->i_fops->readdir = NULL; inode->i_fops->open = ((blkdev_interfaces*)(drentry->di))->open; inode->i_fops->write = NULL; /* à implémenter */ inode->i_fops->read = NULL; /* à implémenter */ inode->i_fops->seek = NULL; /* à implémenter */ inode->i_fops->close = ((blkdev_interfaces*)(drentry->di))->close; inode->i_fops->ioctl = ((blkdev_interfaces*)(drentry->di))->ioctl; break; } dentry_t *d = kmalloc(sizeof(dentry_t)); char *n = strdup(name); d->d_name = (const char*)n; d->d_inode = inode; d->d_pdentry = dentry; return d; } return NULL; }
static const struct timer * timer_open(const char *dname) { const struct timer *tmr = NULL; const char *param = NULL; tmr = find_driver(dname, ¶m, ofbp_timer_start); if (tmr && !tmr->open(param)) return tmr; fprintf(stderr, "Timer driver failed or missing\n"); return NULL; }
int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders) { assert(!sh_audio->initialized); struct mp_decoder_entry *decoder = NULL; struct mp_decoder_list *list = mp_select_audio_decoders(sh_audio->gsh->codec, audio_decoders); mp_print_decoders(MSGT_DECAUDIO, MSGL_V, "Codec list:", list); for (int n = 0; n < list->num_entries; n++) { struct mp_decoder_entry *sel = &list->entries[n]; const struct ad_functions *driver = find_driver(sel->family); if (!driver) continue; mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Opening audio decoder %s:%s\n", sel->family, sel->decoder); sh_audio->ad_driver = driver; if (init_audio_codec(sh_audio, sel->decoder)) { decoder = sel; break; } sh_audio->ad_driver = NULL; mp_tmsg(MSGT_DECAUDIO, MSGL_WARN, "Audio decoder init failed for " "%s:%s\n", sel->family, sel->decoder); } if (sh_audio->initialized) { sh_audio->gsh->decoder_desc = talloc_asprintf(NULL, "%s [%s:%s]", decoder->desc, decoder->family, decoder->decoder); mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Selected audio codec: %s\n", sh_audio->gsh->decoder_desc); mp_msg(MSGT_DECAUDIO, MSGL_V, "AUDIO: %d Hz, %d ch, %s\n", sh_audio->samplerate, sh_audio->channels.num, af_fmt2str_short(sh_audio->sample_format)); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n", sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels.num); } else { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Failed to initialize an audio decoder for codec '%s'.\n", sh_audio->gsh->codec ? sh_audio->gsh->codec : "<unknown>"); } talloc_free(list); return sh_audio->initialized; }
static const struct display * display_open(const char *dname, struct frame_format *dp, struct frame_format *ff) { const struct display *disp = NULL; const char *param = NULL; disp = find_driver(dname, ¶m, ofbp_display_start); if (disp && !disp->open(param, dp, ff)) return disp; fprintf(stderr, "Display driver failed or missing\n"); return NULL; }
bool video_init_best_codec(struct dec_video *d_video, char* video_decoders) { assert(!d_video->vd_driver); video_reset(d_video); d_video->has_broken_packet_pts = -10; // needs 10 packets to reach decision struct mp_decoder_entry *decoder = NULL; struct mp_decoder_list *list = mp_select_video_decoders(d_video->header->codec->codec, video_decoders); mp_print_decoders(d_video->log, MSGL_V, "Codec list:", list); for (int n = 0; n < list->num_entries; n++) { struct mp_decoder_entry *sel = &list->entries[n]; const struct vd_functions *driver = find_driver(sel->family); if (!driver) continue; MP_VERBOSE(d_video, "Opening video decoder %s:%s\n", sel->family, sel->decoder); d_video->vd_driver = driver; if (init_video_codec(d_video, sel->decoder)) { decoder = sel; break; } d_video->vd_driver = NULL; MP_WARN(d_video, "Video decoder init failed for " "%s:%s\n", sel->family, sel->decoder); } if (d_video->vd_driver) { d_video->decoder_desc = talloc_asprintf(d_video, "%s [%s:%s]", decoder->desc, decoder->family, decoder->decoder); MP_VERBOSE(d_video, "Selected video codec: %s\n", d_video->decoder_desc); } else { MP_ERR(d_video, "Failed to initialize a video decoder for codec '%s'.\n", d_video->header->codec->codec); } if (d_video->header->missing_timestamps) { MP_WARN(d_video, "This stream has no timestamps!\n"); MP_WARN(d_video, "Making up playback time using %f FPS.\n", d_video->fps); MP_WARN(d_video, "Seeking will probably fail badly.\n"); } talloc_free(list); return !!d_video->vd_driver; }
static const struct pixconv * pixconv_open(const char *name, const struct frame_format *ffmt, const struct frame_format *dfmt) { const struct pixconv **start = ofbp_pixconv_start; const struct pixconv *conv; do { conv = find_driver(name, NULL, start); if (conv && !conv->open(ffmt, dfmt)) return conv; } while (*start++); fprintf(stderr, "No pixel converter found\n"); return NULL; }
bool video_init_best_codec(struct dec_video *d_video, char* video_decoders) { assert(!d_video->vd_driver); video_reset_decoding(d_video); d_video->has_broken_packet_pts = -10; // needs 10 packets to reach decision struct mp_decoder_entry *decoder = NULL; struct mp_decoder_list *list = mp_select_video_decoders(d_video->header->codec, video_decoders); mp_print_decoders(MSGT_DECVIDEO, MSGL_V, "Codec list:", list); for (int n = 0; n < list->num_entries; n++) { struct mp_decoder_entry *sel = &list->entries[n]; const struct vd_functions *driver = find_driver(sel->family); if (!driver) continue; mp_msg(MSGT_DECVIDEO, MSGL_V, "Opening video decoder %s:%s\n", sel->family, sel->decoder); d_video->vd_driver = driver; if (init_video_codec(d_video, sel->decoder)) { decoder = sel; break; } d_video->vd_driver = NULL; mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Video decoder init failed for " "%s:%s\n", sel->family, sel->decoder); } if (d_video->vd_driver) { d_video->decoder_desc = talloc_asprintf(d_video, "%s [%s:%s]", decoder->desc, decoder->family, decoder->decoder); mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Selected video codec: %s\n", d_video->decoder_desc); } else { mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Failed to initialize a video decoder for codec '%s'.\n", d_video->header->codec ? d_video->header->codec : "<unknown>"); } talloc_free(list); return !!d_video->vd_driver; }
void device_init(void) { int i; io_descriptor_t *descriptor; drivers_available_t *driver; descriptor = (io_descriptor_t*)IO_DESCRIPTOR_AREA; /* search _all_ descriptors (see YAMS documentation) */ for (i=0; i<YAMS_MAX_DEVICES; i++) { if (descriptor->type != 0) { driver = find_driver(descriptor->type); if (driver == NULL) { kprintf("Warning: Unknown hardware device type " "0x%3.3x at 0x%8.8x\n", descriptor->type, descriptor->io_area_base); } else { if (descriptor->irq != 0xffffffff) kprintf("Device: Type 0x%3.3x at 0x%8.8x irq 0x%x " "driver '%s'\n", descriptor->type, descriptor->io_area_base, descriptor->irq, driver->name); else kprintf("Device: Type 0x%3.3x at 0x%8.8x no irq " "driver '%s'\n", descriptor->type, descriptor->io_area_base, driver->name); device_table[number_of_devices]=driver->initfunc(descriptor); if (device_table[number_of_devices] != NULL) { number_of_devices++; if (number_of_devices >= CONFIG_MAX_DEVICES) break; } } } descriptor++; } }
int audio_init_best_codec(struct dec_audio *d_audio, char *audio_decoders) { assert(!d_audio->ad_driver); audio_reset_decoding(d_audio); struct mp_decoder_entry *decoder = NULL; struct mp_decoder_list *list = audio_select_decoders(d_audio->header->codec, audio_decoders); mp_print_decoders(d_audio->log, MSGL_V, "Codec list:", list); for (int n = 0; n < list->num_entries; n++) { struct mp_decoder_entry *sel = &list->entries[n]; const struct ad_functions *driver = find_driver(sel->family); if (!driver) continue; MP_VERBOSE(d_audio, "Opening audio decoder %s:%s\n", sel->family, sel->decoder); d_audio->ad_driver = driver; if (init_audio_codec(d_audio, sel->decoder)) { decoder = sel; break; } MP_WARN(d_audio, "Audio decoder init failed for " "%s:%s\n", sel->family, sel->decoder); } if (d_audio->ad_driver) { d_audio->decoder_desc = talloc_asprintf(d_audio, "%s [%s:%s]", decoder->desc, decoder->family, decoder->decoder); MP_VERBOSE(d_audio, "Selected audio codec: %s\n", d_audio->decoder_desc); } else { MP_ERR(d_audio, "Failed to initialize an audio decoder for codec '%s'.\n", d_audio->header->codec ? d_audio->header->codec : "<unknown>"); } talloc_free(list); return !!d_audio->ad_driver; }
static void write_nets(struct netlist_manager *m, FILE *fd) { struct netlist_net *net; struct netlist_branch *driver; struct netlist_branch *target; net = m->nhead; while(net != NULL) { driver = find_driver(net); if(driver != NULL) { target = net->head; while(target != NULL) { if(!target->output) fprintf(fd, "I%08x:%s -> I%08x:%s;\n", driver->inst->uid, driver->inst->p->output_names[driver->pin_index], target->inst->uid, target->inst->p->input_names[target->pin_index]); target = target->next; } } net = net->next; } }
int obex_mime_type_driver_register(struct obex_mime_type_driver *driver) { if (!driver) { error("Invalid driver"); return -EINVAL; } if (find_driver(driver->target, driver->target_size, driver->mimetype, driver->who, driver->who_size)) { error("Permission denied: %s could not be registered", driver->mimetype); return -EPERM; } if (driver->set_io_watch == NULL) driver->set_io_watch = set_io_watch; DBG("driver %p mimetype %s registered", driver, driver->mimetype); drivers = g_slist_append(drivers, driver); return 0; }
int obex_service_driver_register(struct obex_service_driver *driver) { if (!driver) { error("Invalid driver"); return -EINVAL; } if (find_driver(driver->service)) { error("Permission denied: service %s already registered", driver->name); return -EPERM; } DBG("driver %p service %s registered", driver, driver->name); /* Drivers that support who has priority */ if (driver->who) drivers = g_slist_prepend(drivers, driver); else drivers = g_slist_append(drivers, driver); return 0; }
static int old_capi_manufacturer(unsigned int cmd, void *data) { avmb1_loadandconfigdef ldef; avmb1_extcarddef cdef; avmb1_resetdef rdef; avmb1_getdef gdef; struct capi_driver *driver; struct capi_ctr *card; capicardparams cparams; capiloaddata ldata; int retval; switch (cmd) { case AVMB1_ADDCARD: case AVMB1_ADDCARD_WITH_TYPE: if (cmd == AVMB1_ADDCARD) { if ((retval = copy_from_user((void *) &cdef, data, sizeof(avmb1_carddef)))) return retval; cdef.cardtype = AVM_CARDTYPE_B1; } else { if ((retval = copy_from_user((void *) &cdef, data, sizeof(avmb1_extcarddef)))) return retval; } cparams.port = cdef.port; cparams.irq = cdef.irq; cparams.cardnr = cdef.cardnr; switch (cdef.cardtype) { case AVM_CARDTYPE_B1: driver = find_driver("b1isa"); break; case AVM_CARDTYPE_T1: driver = find_driver("t1isa"); break; default: driver = 0; break; } if (!driver) { printk(KERN_ERR "kcapi: driver not loaded.\n"); return -EIO; } if (!driver->add_card) { printk(KERN_ERR "kcapi: driver has no add card function.\n"); return -EIO; } return driver->add_card(driver, &cparams); case AVMB1_LOAD: case AVMB1_LOAD_AND_CONFIG: if (cmd == AVMB1_LOAD) { if ((retval = copy_from_user((void *) &ldef, data, sizeof(avmb1_loaddef)))) return retval; ldef.t4config.len = 0; ldef.t4config.data = 0; } else { if ((retval = copy_from_user((void *) &ldef, data, sizeof(avmb1_loadandconfigdef)))) return retval; } if (!VALID_CARD(ldef.contr)) return -ESRCH; card = CARD(ldef.contr); if (card->cardstate == CARD_FREE) return -ESRCH; if (card->driver->load_firmware == 0) { printk(KERN_DEBUG "kcapi: load: driver \%s\" has no load function\n", card->driver->name); return -ESRCH; } if (ldef.t4file.len <= 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); return -EINVAL; } if (ldef.t4file.data == 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); return -EINVAL; } ldata.firmware.user = 1; ldata.firmware.data = ldef.t4file.data; ldata.firmware.len = ldef.t4file.len; ldata.configuration.user = 1; ldata.configuration.data = ldef.t4config.data; ldata.configuration.len = ldef.t4config.len; if (card->cardstate != CARD_DETECTED) { printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); return -EBUSY; } card->cardstate = CARD_LOADING; retval = card->driver->load_firmware(card, &ldata); if (retval) { card->cardstate = CARD_DETECTED; return retval; } while (card->cardstate != CARD_RUNNING) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) return -EINTR; } return 0; case AVMB1_RESETCARD: if ((retval = copy_from_user((void *) &rdef, data, sizeof(avmb1_resetdef)))) return retval; if (!VALID_CARD(rdef.contr)) return -ESRCH; card = CARD(rdef.contr); if (card->cardstate == CARD_FREE) return -ESRCH; if (card->cardstate == CARD_DETECTED) return 0; card->driver->reset_ctr(card); while (card->cardstate > CARD_DETECTED) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) return -EINTR; } return 0; case AVMB1_GET_CARDINFO: if ((retval = copy_from_user((void *) &gdef, data, sizeof(avmb1_getdef)))) return retval; if (!VALID_CARD(gdef.contr)) return -ESRCH; card = CARD(gdef.contr); if (card->cardstate == CARD_FREE) return -ESRCH; gdef.cardstate = card->cardstate; if (card->driver == find_driver("t1isa")) gdef.cardtype = AVM_CARDTYPE_T1; else gdef.cardtype = AVM_CARDTYPE_B1; if ((retval = copy_to_user(data, (void *) &gdef, sizeof(avmb1_getdef)))) return retval; return 0; case AVMB1_REMOVECARD: if ((retval = copy_from_user((void *) &rdef, data, sizeof(avmb1_resetdef)))) return retval; if (!VALID_CARD(rdef.contr)) return -ESRCH; card = CARD(rdef.contr); if (card->cardstate == CARD_FREE) return -ESRCH; if (card->cardstate != CARD_DETECTED) return -EBUSY; card->driver->remove_ctr(card); while (card->cardstate != CARD_FREE) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) return -EINTR; } return 0; }
/* * main: * Main program for local process */ int main(int ac, char **av) { char *term; int c; int enter_status; bool Query_driver = false; bool Show_scores = false; enter_status = env_init(Q_CLOAK); while ((c = getopt(ac, av, "Sbcfh:l:mn:op:qst:w:")) != -1) { switch (c) { case 'l': /* rsh compatibility */ case 'n': (void) strncpy(name, optarg, sizeof(name)); break; case 't': team = *optarg; if (!isdigit((unsigned char)team)) { warnx("Team names must be numeric"); team = ' '; } break; case 'o': #ifndef OTTO warnx("The -o flag is reserved for future use."); goto usage; #else Otto_mode = true; break; #endif case 'm': #ifdef MONITOR Am_monitor = true; #else warnx("The monitor was not compiled in."); #endif break; #ifdef INTERNET case 'S': Show_scores = true; break; case 'q': /* query whether hunt is running */ Query_driver = true; break; case 'w': Send_message = optarg; break; case 'h': contacthost = optarg; break; case 'p': contactportstr = optarg; contactport = atoi(contactportstr); break; #else case 'S': case 'q': case 'w': case 'h': case 'p': wanrx("Need TCP/IP for S, q, w, h, and p options."); break; #endif case 'c': enter_status = Q_CLOAK; break; case 'f': #ifdef FLY enter_status = Q_FLY; #else warnx("The flying code was not compiled in."); #endif break; case 's': enter_status = Q_SCAN; break; case 'b': no_beep = !no_beep; break; default: usage: fputs( "usage:\thunt [-qmcsfS] [-n name] [-t team] [-p port] [-w message] [host]\n", stderr); exit(1); } } #ifdef INTERNET if (optind + 1 < ac) goto usage; else if (optind + 1 == ac) contacthost = av[ac - 1]; #else if (optind < ac) goto usage; #endif #ifdef INTERNET serverlist_setup(contacthost, contactport); if (Show_scores) { const struct sockaddr_storage *host; socklen_t hostlen; u_short msg = C_SCORES; unsigned i; serverlist_query(msg); for (i = 0; i < serverlist_num(); i++) { host = serverlist_gethost(i, &hostlen); dump_scores(host, hostlen); } exit(0); } if (Query_driver) { const struct sockaddr_storage *host; socklen_t hostlen; u_short msg = C_MESSAGE; u_short num_players; unsigned i; serverlist_query(msg); for (i = 0; i < serverlist_num(); i++) { host = serverlist_gethost(i, &hostlen); num_players = ntohs(serverlist_getresponse(i)); printf("%d player%s hunting on %s!\n", num_players, (num_players == 1) ? "" : "s", lookuphost(host, hostlen)); } exit(0); } #endif #ifdef OTTO if (Otto_mode) (void) strncpy(name, "otto", sizeof(name)); else #endif fill_in_blanks(); (void) fflush(stdout); if (!isatty(0) || (term = getenv("TERM")) == NULL) errx(1, "no terminal type"); if (!initscr()) errx(0, "couldn't initialize screen"); (void) noecho(); (void) cbreak(); in_visual = true; if (LINES < SCREEN_HEIGHT || COLS < SCREEN_WIDTH) leavex(1, "Need a larger window"); clear_the_screen(); (void) signal(SIGINT, intr); (void) signal(SIGTERM, sigterm); (void) signal(SIGUSR1, sigusr1); (void) signal(SIGPIPE, SIG_IGN); for (;;) { #ifdef INTERNET find_driver(); if (Daemon.sin_port == 0) leavex(1, "Game not found, try again"); jump_in: do { int option; huntsocket = socket(SOCK_FAMILY, SOCK_STREAM, 0); if (huntsocket < 0) err(1, "socket"); option = 1; if (setsockopt(huntsocket, SOL_SOCKET, SO_USELOOPBACK, &option, sizeof option) < 0) warn("setsockopt loopback"); errno = 0; if (connect(huntsocket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) { if (errno != ECONNREFUSED) { leave(1, "connect"); } } else break; sleep(1); } while (close(huntsocket) == 0); #else /* !INTERNET */ /* * set up a socket */ if ((huntsocket = socket(SOCK_FAMILY, SOCK_STREAM, 0)) < 0) err(1, "socket"); /* * attempt to connect the socket to a name; if it fails that * usually means that the driver isn't running, so we start * up the driver. */ Daemon.sun_family = SOCK_FAMILY; (void) strcpy(Daemon.sun_path, huntsockpath); if (connect(huntsocket, &Daemon, DAEMON_SIZE) < 0) { if (errno != ENOENT) { leavex(1, "connect2"); } start_driver(); do { (void) close(huntsocket); if ((huntsocket = socket(SOCK_FAMILY, SOCK_STREAM, 0)) < 0) err(1, "socket"); sleep(2); } while (connect(huntsocket, &Daemon, DAEMON_SIZE) < 0); } #endif do_connect(name, sizeof(name), team, enter_status); #ifdef INTERNET if (Send_message != NULL) { do_message(); if (enter_status == Q_MESSAGE) break; Send_message = NULL; /* don't continue as that will call find_driver */ goto jump_in; } #endif playit(); if ((enter_status = quit(enter_status)) == Q_QUIT) break; } leavex(0, NULL); /* NOTREACHED */ return(0); }
static void device_register(void *descriptors, uint16_t descriptors_len, usbh_device_t *dev) { uint32_t i = 0; dev->drv = 0; uint8_t *buf = (uint8_t *)descriptors; dev->drv = 0; dev->drvdata = 0; uint8_t desc_len = buf[i]; uint8_t desc_type = buf[i + 1]; usbh_dev_driver_info_t device_info; if (desc_type == USB_DT_DEVICE) { struct usb_device_descriptor *device_desc = (void*)&buf[i]; device_info.deviceClass = device_desc->bDeviceClass; device_info.deviceSubClass = device_desc->bDeviceSubClass; device_info.deviceProtocol = device_desc->bDeviceProtocol; device_info.idVendor = device_desc->idVendor; device_info.idProduct = device_desc->idProduct; } else {; return; } while (i < descriptors_len) { desc_len = buf[i]; desc_type = buf[i + 1]; switch (desc_type) { case USB_DT_INTERFACE: { struct usb_interface_descriptor *iface = (void*)&buf[i]; device_info.ifaceClass = iface->bInterfaceClass; device_info.ifaceSubClass = iface->bInterfaceSubClass; device_info.ifaceProtocol = iface->bInterfaceProtocol; const usbh_dev_driver_t *driver = find_driver(&device_info); if (driver) { dev->drv = driver; dev->drvdata = dev->drv->init(dev); if (!dev->drvdata) { } break; } } break; default: break; } if (desc_len == 0) { return; } i += desc_len; } if (dev->drv && dev->drvdata) { // analyze descriptors i = 0; while (i < descriptors_len) { desc_len = buf[i]; void *drvdata = dev->drvdata; if (dev->drv->analyze_descriptor(drvdata, &buf[i])) { return; } i += desc_len; } } }
int main(int argc, char **argv) { AVFormatContext *afc; AVStream *st; AVPacket pk; struct frame_format frame_fmt = { 0 }; const struct pixconv *pixconv = NULL; const struct memman *memman = NULL; const struct codec *codec = NULL; struct frame_format dp; int bufsize = BUFFER_SIZE; pthread_t dispt; unsigned flags = OFBP_DOUBLE_BUF; char *test_param = NULL; char *dispdrv = NULL; char *timer_drv = NULL; char *memman_drv = NULL; char *pixconv_drv = NULL; char *codec_drv = NULL; int opt; int ret = 0; #define error(n) do { ret = n; goto out; } while (0) while ((opt = getopt(argc, argv, "b:d:fFM:P:st:T:v:")) != -1) { switch (opt) { case 'b': bufsize = strtol(optarg, NULL, 0) * 1048576; break; case 'd': dispdrv = optarg; break; case 'F': noaspect = 1; case 'f': flags |= OFBP_FULLSCREEN; break; case 'M': memman_drv = optarg; break; case 'P': pixconv_drv = optarg; break; case 's': flags &= ~OFBP_DOUBLE_BUF; break; case 't': test_param = optarg; break; case 'T': timer_drv = optarg; break; case 'v': codec_drv = optarg; break; } } argc -= optind; argv += optind; if (test_param) return speed_test(dispdrv, memman_drv, pixconv_drv, test_param, flags); if (argc < 1) return 1; av_register_all(); avcodec_register_all(); afc = open_file(argv[0]); st = find_stream(afc); if (!st) { fprintf(stderr, "No video streams found.\n"); exit(1); } codec = find_driver(codec_drv, NULL, ofbp_codec_start); if (!codec) { fprintf(stderr, "Decoder '%s' not found\n", codec_drv); error(1); } if (codec->open(NULL, st->codec, &frame_fmt)) { fprintf(stderr, "Error opening decoder\n"); error(1); } if (!frame_fmt.width) { fprintf(stderr, "Decoder error: frame size not specified\n"); error(1); } dp.pixfmt = frame_fmt.pixfmt; display = display_open(dispdrv, &dp, &frame_fmt); if (!display) error(1); set_scale(&dp, &frame_fmt, flags); if (display->memman) { if (dp.pixfmt == frame_fmt.pixfmt) { memman = display->memman; } else if (display->flags & OFBP_PRIV_MEM) { fprintf(stderr, "Decoder/display pixel format mismatch\n"); error(1); } } if (!memman) memman = find_driver(memman_drv, NULL, ofbp_memman_start); if (!memman) error(1); if ((codec->flags & OFBP_PHYS_MEM) && !(memman->flags & OFBP_PHYS_MEM)) { fprintf(stderr, "Incompatible decoder/memman\n"); error(1); } if (memman->alloc_frames(&frame_fmt, bufsize, &frames, &num_frames)) error(1); if (memman != display->memman) { pixconv = pixconv_open(pixconv_drv, &frame_fmt, &dp); if (!pixconv) error(1); if ((pixconv->flags & OFBP_PHYS_MEM) && !(memman->flags & display->flags & OFBP_PHYS_MEM)) { fprintf(stderr, "Incompatible display/memman/pixconv\n"); error(1); } } timer = timer_open(timer_drv); if (!timer) error(1); init_frames(&frame_fmt); if (display->enable(&frame_fmt, flags, pixconv, &dp)) error(1); pthread_mutex_init(&disp_lock, NULL); sem_init(&disp_sem, 0, 0); signal(SIGINT, sigint); pthread_create(&dispt, NULL, disp_thread, st); while (!stop && !av_read_frame(afc, &pk)) { if (pk.stream_index == st->index) if (codec->decode(&pk)) stop = 1; av_free_packet(&pk); } if (!stop) { sem_post(&disp_sem); while (disp_tail != -1) usleep(100000); } stop = 1; sem_post(&disp_sem); pthread_join(dispt, NULL); out: if (afc) av_close_input_file(afc); if (codec) codec->close(); if (timer) timer->close(); if (memman) memman->free_frames(frames, num_frames); if (display) display->close(); if (pixconv) pixconv->close(); return ret; }
static int speed_test(const char *drv, const char *mem, const char *conv, char *size, unsigned disp_flags) { const struct pixconv *pixconv = NULL; const struct memman *memman = NULL; struct frame_format dp = { 0 }; struct frame_format ff = { 0 }; struct timespec t1, t2; unsigned w, h = 0; unsigned n = 1000; unsigned bufsize; char *ss = size; int i, j; w = strtoul(size, &size, 0); if (*size++) h = strtoul(size, &size, 0); if (*size++) n = strtoul(size, NULL, 0); if (!w || !h || !n) { fprintf(stderr, "Invalid size/count '%s'\n", ss); return 1; } ff.width = ALIGN(w, 32); ff.height = ALIGN(h, 32); ff.disp_x = 0; ff.disp_y = 0; ff.disp_w = w; ff.disp_h = h; dp.pixfmt = ff.pixfmt = PIX_FMT_YUV420P; display = display_open(drv, &dp, &ff); if (!display) return 1; set_scale(&dp, &ff, disp_flags); if (display->memman) { memman = display->memman; ff.pixfmt = dp.pixfmt; } if (!memman) memman = find_driver(mem, NULL, ofbp_memman_start); if (memman->alloc_frames(&ff, 0, &frames, &num_frames)) return 1; if (memman != display->memman) { pixconv = pixconv_open(conv, &ff, &dp); if (!pixconv) return 1; if ((pixconv->flags & OFBP_PHYS_MEM) && !(memman->flags & display->flags & OFBP_PHYS_MEM)) { fprintf(stderr, "Incompatible display/memman/pixconv\n"); return 1; } } init_frames(&ff); if (display->enable(&ff, disp_flags, pixconv, &dp)) return 1; bufsize = ff.disp_w * ff.disp_h * 3 / 2; test_pattern(frames, num_frames, &ff); signal(SIGINT, sigint); clock_gettime(CLOCK_REALTIME, &t1); for (i = 0; i < n && !stop; i++) { struct frame *f = ofbp_get_frame(); display->prepare(f); display->show(f); } clock_gettime(CLOCK_REALTIME, &t2); j = ts_diff_ms(&t2, &t1); fprintf(stderr, "%d ms, %d fps, read %lld B/s, write %lld B/s\n", j, i*1000 / j, 1000LL*i*bufsize / j, 2000LL*i*w*h / j); memman->free_frames(frames, num_frames); display->close(); if (pixconv) pixconv->close(); return 0; }
void video_reset(struct dec_video *d_video) { video_vd_control(d_video, VDCTRL_RESET, NULL); d_video->first_packet_pdts = MP_NOPTS_VALUE; d_video->start_pts = MP_NOPTS_VALUE; d_video->decoded_pts = MP_NOPTS_VALUE; d_video->codec_pts = MP_NOPTS_VALUE; d_video->codec_dts = MP_NOPTS_VALUE; d_video->last_format = d_video->fixed_format = (struct mp_image_params){0}; d_video->dropped_frames = 0; d_video->current_state = DATA_AGAIN; mp_image_unrefp(&d_video->current_mpi); talloc_free(d_video->packet); d_video->packet = NULL; talloc_free(d_video->new_segment); d_video->new_segment = NULL; d_video->start = d_video->end = MP_NOPTS_VALUE; } int video_vd_control(struct dec_video *d_video, int cmd, void *arg) { const struct vd_functions *vd = d_video->vd_driver; if (vd) return vd->control(d_video, cmd, arg); return CONTROL_UNKNOWN; } void video_uninit(struct dec_video *d_video) { if (!d_video) return; mp_image_unrefp(&d_video->current_mpi); mp_image_unrefp(&d_video->cover_art_mpi); if (d_video->vd_driver) { MP_VERBOSE(d_video, "Uninit video.\n"); d_video->vd_driver->uninit(d_video); } talloc_free(d_video->packet); talloc_free(d_video->new_segment); talloc_free(d_video); } static int init_video_codec(struct dec_video *d_video, const char *decoder) { if (!d_video->vd_driver->init(d_video, decoder)) { MP_VERBOSE(d_video, "Video decoder init failed.\n"); return 0; } return 1; } struct mp_decoder_list *video_decoder_list(void) { struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); for (int i = 0; mpcodecs_vd_drivers[i] != NULL; i++) mpcodecs_vd_drivers[i]->add_decoders(list); return list; } static struct mp_decoder_list *mp_select_video_decoders(const char *codec, char *selection) { struct mp_decoder_list *list = video_decoder_list(); struct mp_decoder_list *new = mp_select_decoders(list, codec, selection); talloc_free(list); return new; } static const struct vd_functions *find_driver(const char *name) { for (int i = 0; mpcodecs_vd_drivers[i] != NULL; i++) { if (strcmp(mpcodecs_vd_drivers[i]->name, name) == 0) return mpcodecs_vd_drivers[i]; } return NULL; } bool video_init_best_codec(struct dec_video *d_video) { struct MPOpts *opts = d_video->opts; assert(!d_video->vd_driver); video_reset(d_video); d_video->has_broken_packet_pts = -10; // needs 10 packets to reach decision struct mp_decoder_entry *decoder = NULL; struct mp_decoder_list *list = mp_select_video_decoders(d_video->codec->codec, opts->video_decoders); mp_print_decoders(d_video->log, MSGL_V, "Codec list:", list); for (int n = 0; n < list->num_entries; n++) { struct mp_decoder_entry *sel = &list->entries[n]; const struct vd_functions *driver = find_driver(sel->family); if (!driver) continue; MP_VERBOSE(d_video, "Opening video decoder %s:%s\n", sel->family, sel->decoder); d_video->vd_driver = driver; if (init_video_codec(d_video, sel->decoder)) { decoder = sel; break; } d_video->vd_driver = NULL; MP_WARN(d_video, "Video decoder init failed for " "%s:%s\n", sel->family, sel->decoder); } if (d_video->vd_driver) { d_video->decoder_desc = talloc_asprintf(d_video, "%s [%s:%s]", decoder->desc, decoder->family, decoder->decoder); MP_VERBOSE(d_video, "Selected video codec: %s\n", d_video->decoder_desc); } else { MP_ERR(d_video, "Failed to initialize a video decoder for codec '%s'.\n", d_video->codec->codec); } if (d_video->header->missing_timestamps) { MP_WARN(d_video, "This stream has no timestamps!\n"); MP_WARN(d_video, "Making up playback time using %f FPS.\n", d_video->fps); MP_WARN(d_video, "Seeking will probably fail badly.\n"); } talloc_free(list); return !!d_video->vd_driver; } static void fix_image_params(struct dec_video *d_video, struct mp_image_params *params) { struct MPOpts *opts = d_video->opts; struct mp_image_params p = *params; struct mp_codec_params *c = d_video->codec; MP_VERBOSE(d_video, "Decoder format: %s\n", mp_image_params_to_str(params)); // While mp_image_params normally always have to have d_w/d_h set, the // decoder signals unknown bitstream aspect ratio with both set to 0. float dec_aspect = p.p_w > 0 && p.p_h > 0 ? p.p_w / (float)p.p_h : 0; if (d_video->initial_decoder_aspect == 0) d_video->initial_decoder_aspect = dec_aspect; bool use_container = true; switch (opts->aspect_method) { case 0: // We normally prefer the container aspect, unless the decoder aspect // changes at least once. if (dec_aspect > 0 && d_video->initial_decoder_aspect != dec_aspect) { MP_VERBOSE(d_video, "Using bitstream aspect ratio.\n"); // Even if the aspect switches back, don't use container aspect again. d_video->initial_decoder_aspect = -1; use_container = false; } break; case 1: use_container = false; break; } if (use_container && c->par_w > 0 && c->par_h) { MP_VERBOSE(d_video, "Using container aspect ratio.\n"); p.p_w = c->par_w; p.p_h = c->par_h; } if (opts->movie_aspect >= 0) { MP_VERBOSE(d_video, "Forcing user-set aspect ratio.\n"); if (opts->movie_aspect == 0) { p.p_w = p.p_h = 1; } else { AVRational a = av_d2q(opts->movie_aspect, INT_MAX); mp_image_params_set_dsize(&p, a.num, a.den); } } // Assume square pixels if no aspect ratio is set at all. if (p.p_w <= 0 || p.p_h <= 0) p.p_w = p.p_h = 1; // Detect colorspace from resolution. mp_image_params_guess_csp(&p); d_video->last_format = *params; d_video->fixed_format = p; } static struct mp_image *decode_packet(struct dec_video *d_video, struct demux_packet *packet, int drop_frame) { struct MPOpts *opts = d_video->opts; if (!d_video->vd_driver) return NULL; double pkt_pts = packet ? packet->pts : MP_NOPTS_VALUE; double pkt_dts = packet ? packet->dts : MP_NOPTS_VALUE; if (pkt_pts == MP_NOPTS_VALUE) d_video->has_broken_packet_pts = 1; double pkt_pdts = pkt_pts == MP_NOPTS_VALUE ? pkt_dts : pkt_pts; if (pkt_pdts != MP_NOPTS_VALUE && d_video->first_packet_pdts == MP_NOPTS_VALUE) d_video->first_packet_pdts = pkt_pdts; MP_STATS(d_video, "start decode video"); struct mp_image *mpi = d_video->vd_driver->decode(d_video, packet, drop_frame); MP_STATS(d_video, "end decode video"); // Error, discarded frame, dropped frame, or initial codec delay. if (!mpi || drop_frame) { talloc_free(mpi); return NULL; } if (opts->field_dominance == 0) { mpi->fields |= MP_IMGFIELD_TOP_FIRST | MP_IMGFIELD_INTERLACED; } else if (opts->field_dominance == 1) { mpi->fields &= ~MP_IMGFIELD_TOP_FIRST; mpi->fields |= MP_IMGFIELD_INTERLACED; } // Note: the PTS is reordered, but the DTS is not. Both should be monotonic. double pts = mpi->pts; double dts = mpi->dts; if (pts != MP_NOPTS_VALUE) { if (pts < d_video->codec_pts) d_video->num_codec_pts_problems++; d_video->codec_pts = mpi->pts; } if (dts != MP_NOPTS_VALUE) { if (dts <= d_video->codec_dts) d_video->num_codec_dts_problems++; d_video->codec_dts = mpi->dts; } if (d_video->has_broken_packet_pts < 0) d_video->has_broken_packet_pts++; if (d_video->num_codec_pts_problems) d_video->has_broken_packet_pts = 1; // If PTS is unset, or non-monotonic, fall back to DTS. if ((d_video->num_codec_pts_problems > d_video->num_codec_dts_problems || pts == MP_NOPTS_VALUE) && dts != MP_NOPTS_VALUE) pts = dts; if (!opts->correct_pts || pts == MP_NOPTS_VALUE) { if (opts->correct_pts && !d_video->header->missing_timestamps) MP_WARN(d_video, "No video PTS! Making something up.\n"); double frame_time = 1.0f / (d_video->fps > 0 ? d_video->fps : 25); double base = d_video->first_packet_pdts; pts = d_video->decoded_pts; if (pts == MP_NOPTS_VALUE) { pts = base == MP_NOPTS_VALUE ? 0 : base; } else { pts += frame_time; } } if (!mp_image_params_equal(&d_video->last_format, &mpi->params)) fix_image_params(d_video, &mpi->params); mpi->params = d_video->fixed_format; mpi->pts = pts; d_video->decoded_pts = pts; // Compensate for incorrectly using mpeg-style DTS for avi timestamps. if (d_video->codec->avi_dts && opts->correct_pts && mpi->pts != MP_NOPTS_VALUE && d_video->fps > 0) { int delay = -1; video_vd_control(d_video, VDCTRL_GET_BFRAMES, &delay); mpi->pts -= MPMAX(delay, 0) / d_video->fps; } return mpi; } void video_reset_aspect(struct dec_video *d_video) { d_video->last_format = (struct mp_image_params){0}; } void video_set_framedrop(struct dec_video *d_video, bool enabled) { d_video->framedrop_enabled = enabled; } // Frames before the start timestamp can be dropped. (Used for hr-seek.) void video_set_start(struct dec_video *d_video, double start_pts) { d_video->start_pts = start_pts; } void video_work(struct dec_video *d_video) { if (d_video->current_mpi) return; if (d_video->header->attached_picture) { if (d_video->current_state == DATA_AGAIN && !d_video->cover_art_mpi) { d_video->cover_art_mpi = decode_packet(d_video, d_video->header->attached_picture, 0); // Might need flush. if (!d_video->cover_art_mpi) d_video->cover_art_mpi = decode_packet(d_video, NULL, 0); d_video->current_state = DATA_OK; } if (d_video->current_state == DATA_OK) d_video->current_mpi = mp_image_new_ref(d_video->cover_art_mpi); // (DATA_OK is returned the first time, when current_mpi is sill set) d_video->current_state = DATA_EOF; return; } if (!d_video->packet && !d_video->new_segment && demux_read_packet_async(d_video->header, &d_video->packet) == 0) { d_video->current_state = DATA_WAIT; return; } if (d_video->packet) { if (d_video->packet->dts == MP_NOPTS_VALUE && !d_video->codec->avi_dts) d_video->packet->dts = d_video->packet->pts; } if (d_video->packet && d_video->packet->new_segment) { assert(!d_video->new_segment); d_video->new_segment = d_video->packet; d_video->packet = NULL; } bool had_input_packet = !!d_video->packet; bool had_packet = had_input_packet || d_video->new_segment; double start_pts = d_video->start_pts; if (d_video->start != MP_NOPTS_VALUE && (start_pts == MP_NOPTS_VALUE || d_video->start > start_pts)) start_pts = d_video->start; int framedrop_type = d_video->framedrop_enabled ? 1 : 0; if (start_pts != MP_NOPTS_VALUE && d_video->packet && d_video->packet->pts < start_pts - .005 && !d_video->has_broken_packet_pts) { framedrop_type = 2; } d_video->current_mpi = decode_packet(d_video, d_video->packet, framedrop_type); if (d_video->packet && d_video->packet->len == 0) { talloc_free(d_video->packet); d_video->packet = NULL; } d_video->current_state = DATA_OK; if (!d_video->current_mpi) { d_video->current_state = DATA_EOF; if (had_packet) { if (framedrop_type == 1) d_video->dropped_frames += 1; d_video->current_state = DATA_AGAIN; } } bool segment_ended = !d_video->current_mpi && !had_input_packet; if (d_video->current_mpi && d_video->current_mpi->pts != MP_NOPTS_VALUE) { double vpts = d_video->current_mpi->pts; segment_ended = d_video->end != MP_NOPTS_VALUE && vpts >= d_video->end; if ((d_video->start != MP_NOPTS_VALUE && vpts < d_video->start) || segment_ended) { talloc_free(d_video->current_mpi); d_video->current_mpi = NULL; } } // If there's a new segment, start it as soon as we're drained/finished. if (segment_ended && d_video->new_segment) { struct demux_packet *new_segment = d_video->new_segment; d_video->new_segment = NULL; // Could avoid decoder reinit; would still need flush. d_video->codec = new_segment->codec; if (d_video->vd_driver) d_video->vd_driver->uninit(d_video); d_video->vd_driver = NULL; video_init_best_codec(d_video); d_video->start = new_segment->start; d_video->end = new_segment->end; new_segment->new_segment = false; d_video->packet = new_segment; d_video->current_state = DATA_AGAIN; } } // Fetch an image decoded with video_work(). Returns one of: // DATA_OK: *out_mpi is set to a new image // DATA_WAIT: waiting for demuxer; will receive a wakeup signal // DATA_EOF: end of file, no more frames to be expected // DATA_AGAIN: dropped frame or something similar int video_get_frame(struct dec_video *d_video, struct mp_image **out_mpi) { *out_mpi = NULL; if (d_video->current_mpi) { *out_mpi = d_video->current_mpi; d_video->current_mpi = NULL; return DATA_OK; } if (d_video->current_state == DATA_OK) return DATA_AGAIN; return d_video->current_state; }