// Select a decoder from the given list for the given codec. The selection // can be influenced by the selection string, which can specify a priority // list of preferred decoders. // This returns a list of decoders to try, with the preferred decoders first. // The selection string corresponds to --vd/--ad directly, and has the // following syntax: // selection = [<entry> ("," <entry>)*] // entry = <family> ":" <decoder> // prefer decoder // entry = <family> ":*" // prefer all decoders // entry = "+" <family> ":" <decoder> // force a decoder // entry = "-" <family> ":" <decoder> // exclude a decoder // entry = "-" // don't add fallback decoders // Forcing a decoder means it's added even if the codec mismatches. struct mp_decoder_list *mp_select_decoders(struct mp_decoder_list *all, const char *codec, const char *selection) { struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); struct mp_decoder_list *remove = talloc_zero(NULL, struct mp_decoder_list); if (!codec) codec = "unknown"; bool stop = false; bstr sel = bstr0(selection); while (sel.len) { bstr entry; bstr_split_tok(sel, ",", &entry, &sel); if (bstr_equals0(entry, "-")) { stop = true; break; } bool force = bstr_eatstart0(&entry, "+"); bool exclude = !force && bstr_eatstart0(&entry, "-"); struct mp_decoder_list *dest = exclude ? remove : list; bstr family, decoder; if (!bstr_split_tok(entry, ":", &family, &decoder)) { mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Decoders must be specified as " "'family:decoder' for the --ad/--vd options.\n"); break; } if (bstr_equals0(decoder, "*")) { for (int n = 0; n < all->num_entries; n++) { struct mp_decoder_entry *cur = &all->entries[n]; if (bstr_equals0(family, cur->family)) add_new(dest, cur, codec); } } else { add_new(dest, find_decoder(all, family, decoder), force ? NULL : codec); } } if (!stop) { // Add the remaining codecs which haven't been added yet for (int n = 0; n < all->num_entries; n++) add_new(list, &all->entries[n], codec); } for (int n = 0; n < remove->num_entries; n++) { struct mp_decoder_entry *ex = &remove->entries[n]; struct mp_decoder_entry *del = find_decoder(list, bstr0(ex->family), bstr0(ex->decoder)); if (del) { int index = del - &list->entries[0]; MP_TARRAY_REMOVE_AT(list->entries, list->num_entries, index); } } talloc_free(remove); return list; }
void Decoder::init_decoder(const int in_width, const int in_height, const int in_pix_fmt, const int codec_ID) { /* Declarations */ AVCodec *codec; /* Find the decoder */ codec = find_decoder(codec_ID); if (!codec) throw std::runtime_error("Could not find codec."); /* Allocate codec context */ codec_context_ = avcodec_alloc_context3(codec); if (!codec_context_) throw std::runtime_error("Could not allocate codec context."); /* Set codec configuration */ codec_context_->pix_fmt = (enum AVPixelFormat) in_pix_fmt; codec_context_->coded_width = in_width; codec_context_->coded_height = in_height; /* Open the codec context */ if (codec_open(codec_context_, codec, NULL) < 0) throw std::runtime_error("Could not open codec context."); /* Allocate Decoder AVFrame */ frame_in_ = boost::make_shared<Frame>(in_width, in_height, in_pix_fmt); has_keyframe_ = false; previous_packet_ = 0; }
// Add entry, but only if it's not yet on the list, and if the codec matches. // If codec == NULL, don't compare codecs. static void add_new(struct mp_decoder_list *to, struct mp_decoder_entry *entry, const char *codec) { if (!entry || (codec && strcmp(entry->codec, codec) != 0)) return; if (!find_decoder(to, bstr0(entry->family), bstr0(entry->decoder))) mp_add_decoder_entry(to, entry); }
static HRESULT WINAPI ComponentFactory_CreateDecoderFromStream( IWICComponentFactory *iface, IStream *pIStream, const GUID *pguidVendor, WICDecodeOptions metadataOptions, IWICBitmapDecoder **ppIDecoder) { HRESULT res; IWICBitmapDecoder *decoder = NULL; TRACE("(%p,%p,%s,%u,%p)\n", iface, pIStream, debugstr_guid(pguidVendor), metadataOptions, ppIDecoder); if (pguidVendor) decoder = find_decoder(pIStream, pguidVendor, metadataOptions); if (!decoder) decoder = find_decoder(pIStream, NULL, metadataOptions); if (decoder) { *ppIDecoder = decoder; return S_OK; } else { if (WARN_ON(wincodecs)) { LARGE_INTEGER seek; BYTE data[4]; ULONG bytesread; WARN("failed to load from a stream\n"); seek.QuadPart = 0; res = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL); if (SUCCEEDED(res)) res = IStream_Read(pIStream, data, 4, &bytesread); if (SUCCEEDED(res)) WARN("first %i bytes of stream=%x %x %x %x\n", bytesread, data[0], data[1], data[2], data[3]); } *ppIDecoder = NULL; return WINCODEC_ERR_COMPONENTNOTFOUND; } }
struct song *read_songs(char *dirname) { /* bleught. string manipulation in C. I hate this part */ struct dirent *de; DIR *dir=opendir(dirname); int buf_size=0; int nsongs=0; char *buf; struct song *songs,*song; while((de=readdir(dir))) { if(find_decoder(de->d_name)) { nsongs++; buf_size+=strlen(de->d_name)+1; } else { printf("skipping %s\n",de->d_name); } } buf=calloc(buf_size,1); songs=calloc(nsongs,sizeof (struct song)); song=&songs[0]; rewinddir(dir); struct decoder *d; while(nsongs && (de=readdir(dir))) { if((d=find_decoder(de->d_name))) { nsongs--; strcpy(buf,de->d_name); song->filename=buf; printf("--%s\n",buf); buf+=strlen(buf)+1; d->read_metadata(song); song->decoder=d; song++; } } song->filename=(char *)0; n_songs=song-songs; return songs; }
/* Find the index in plugins table for the given file. * Return -1 if not found. */ static int find_type (const char *file) { int result = -1; char *extn, *mime; extn = ext_pos (file); mime = NULL; result = find_decoder (extn, file, &mime); free (mime); return result; }
int find_and_open_decoder ( AVCodecContext *ctx, enum AVCodecID codec_id, const char **preferred_decoder_names, int threads ) { AVCodec *codec = find_decoder( codec_id, preferred_decoder_names ); if( !codec ) return -1; ctx->thread_count = threads; return (open_decoder( ctx, codec ) < 0) ? -1 : 0; }
// selection is a ","-separated list of decoders, all in the given family. struct mp_decoder_list *mp_select_decoder_list(struct mp_decoder_list *all, const char *codec, const char *family, const char *selection) { struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); bstr sel = bstr0(selection); while (sel.len) { bstr decoder; bstr_split_tok(sel, ",", &decoder, &sel); add_new(list, find_decoder(all, bstr0(family), decoder), codec); } return list; }
int main(int argc, char **argv) { SDL_Event *event = av_mallocz(sizeof(SDL_Event)); Content *content = av_mallocz(sizeof(Content)); Media *video = av_mallocz(sizeof(Media)); Media *audio = av_mallocz(sizeof(Media)); State *state = av_mallocz(sizeof(State)); SDL_Thread *video_decode_tid1; SDL_Thread *video_decode_tid2; SDL_Thread *read_pkt_tid; SDL_Thread *refresh_tid; // InitPool(2); state->content = content; state->video = video; state->audio = audio; init_video(video); if(argc < 2) { LOGE("Usage : play <content>"); exit(1); } av_register_all(); if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { LOGE("fail to initialize SDL"); exit(1); } av_strlcpy(content->name, argv[1], sizeof(content->name)); LOGE("addr : %x", video->frame_buf); get_content_info(content); LOGI("finding streams"); find_av_streams(content, video, audio); LOGI("finding decoder"); find_decoder(video); video->get_info(video); LOGI("creating reading thread..."); read_pkt_tid = SDL_CreateThread(queue_av_pkt, "read", state); LOGI("initing screen"); init_screen(video); // LOGI("alloc frame"); alloc_frame(video); LOGI("alloc all the frame"); // alloc_all_frame(video); LOGI("creating decode thread1..."); video_decode_tid1 = SDL_CreateThread(decode_video, "decode1", video); refresh(state, 50); event_handle(event); return 0; }
/* Use the stream's MIME type to return a decoder for it, or NULL if no * applicable decoder was found. */ static struct decoder *get_decoder_by_mime_type (struct io_stream *stream) { int i; char *mime; struct decoder *result; result = NULL; mime = xstrdup (io_get_mime_type (stream)); if (mime) { i = find_decoder (NULL, NULL, &mime); if (i != -1) { logit ("Found decoder for MIME type %s: %s", mime, plugins[i].name); result = plugins[i].decoder; } free (mime); } else logit ("No MIME type."); return result; }
static bool find_and_initialize_stream_decoders(struct ff_demuxer *demuxer) { AVFormatContext *format_context = demuxer->format_context; unsigned int i; AVStream *audio_stream = NULL; AVStream *video_stream = NULL; int64_t start_time = INT64_MAX; for (i = 0; i < format_context->nb_streams; i++) { AVCodecContext *codec = format_context->streams[i]->codec; if (codec->codec_type == AVMEDIA_TYPE_VIDEO && !video_stream) video_stream = format_context->streams[i]; if (codec->codec_type == AVMEDIA_TYPE_AUDIO && !audio_stream) audio_stream = format_context->streams[i]; } int default_stream_index = av_find_default_stream_index( demuxer->format_context); if (default_stream_index >= 0) { AVStream *stream = format_context->streams[default_stream_index]; if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) demuxer->clock.sync_type = AV_SYNC_AUDIO_MASTER; else if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) demuxer->clock.sync_type = AV_SYNC_VIDEO_MASTER; } if (video_stream != NULL) find_decoder(demuxer, video_stream); if (audio_stream != NULL) find_decoder(demuxer, audio_stream); if (demuxer->video_decoder == NULL && demuxer->audio_decoder == NULL) { return false; } if (!set_clock_sync_type(demuxer)) { return false; } for (i = 0; i < format_context->nb_streams; i++) { AVStream *st = format_context->streams[i]; int64_t st_start_time; if (st->discard == AVDISCARD_ALL || st->start_time == AV_NOPTS_VALUE) { continue; } st_start_time = av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q); start_time = FFMIN(start_time, st_start_time); } if (format_context->start_time != AV_NOPTS_VALUE) { if (start_time > format_context->start_time || start_time == INT64_MAX) { start_time = format_context->start_time; } } if (start_time != INT64_MAX) { set_decoder_start_time(demuxer->video_decoder, start_time); set_decoder_start_time(demuxer->audio_decoder, start_time); } if (demuxer->audio_decoder != NULL) { if (ff_callbacks_initialize(&demuxer->audio_callbacks)) { ff_decoder_start(demuxer->audio_decoder); } else { ff_decoder_free(demuxer->audio_decoder); demuxer->audio_decoder = NULL; if (!set_clock_sync_type(demuxer)) return false; } } if (demuxer->video_decoder != NULL) { if (ff_callbacks_initialize(&demuxer->video_callbacks)) { ff_decoder_start(demuxer->video_decoder); } else { ff_decoder_free(demuxer->video_decoder); demuxer->video_decoder = NULL; if (!set_clock_sync_type(demuxer)) return false; } } return set_clock_sync_type(demuxer); }
void lwlibav_update_configuration ( lwlibav_decode_handler_t *dhp, uint32_t frame_number, int extradata_index, int64_t rap_pos ) { lwlibav_extradata_handler_t *exhp = &dhp->exh; if( exhp->entry_count == 0 || extradata_index < 0 ) { /* No need to update the extradata. */ exhp->current_index = extradata_index; lwlibav_flush_buffers( dhp ); return; } AVCodecContext *ctx = dhp->format->streams[ dhp->stream_index ]->codec; void *app_specific = ctx->opaque; avcodec_close( ctx ); if( ctx->extradata ) { av_freep( &ctx->extradata ); ctx->extradata_size = 0; } /* Find an appropriate decoder. */ char error_string[96] = { 0 }; lwlibav_extradata_t *entry = &exhp->entries[extradata_index]; const AVCodec *codec = find_decoder( entry->codec_id, dhp->preferred_decoder_names ); if( !codec ) { strcpy( error_string, "Failed to find the decoder.\n" ); goto fail; } /* Get decoder default settings. */ int thread_count = ctx->thread_count; if( avcodec_get_context_defaults3( ctx, codec ) < 0 ) { strcpy( error_string, "Failed to get CODEC default.\n" ); goto fail; } /* Set up decoder basic settings. */ if( ctx->codec_type == AVMEDIA_TYPE_VIDEO ) set_video_basic_settings( dhp, frame_number ); else set_audio_basic_settings( dhp, frame_number ); /* Update extradata. */ if( entry->extradata_size > 0 ) { ctx->extradata = (uint8_t *)av_malloc( entry->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE ); if( !ctx->extradata ) { strcpy( error_string, "Failed to allocate extradata.\n" ); goto fail; } ctx->extradata_size = entry->extradata_size; memcpy( ctx->extradata, entry->extradata, ctx->extradata_size ); memset( ctx->extradata + ctx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE ); } /* AVCodecContext.codec_id is supposed to be set properly in avcodec_open2(). * See lwlibav_flush_buffers(), why this is needed. */ ctx->codec_id = AV_CODEC_ID_NONE; /* This is needed by some CODECs such as UtVideo and raw video. */ ctx->codec_tag = entry->codec_tag; /* Open an appropriate decoder. * Here, we force single threaded decoding since some decoder doesn't do its proper initialization with multi-threaded decoding. */ ctx->thread_count = 1; if( open_decoder( ctx, codec ) < 0 ) { strcpy( error_string, "Failed to open decoder.\n" ); goto fail; } exhp->current_index = extradata_index; exhp->delay_count = 0; /* Set up decoder basic settings by actual decoding. */ if( ctx->codec_type == AVMEDIA_TYPE_VIDEO ? try_decode_video_frame( dhp, frame_number, rap_pos, error_string ) < 0 : try_decode_audio_frame( dhp, frame_number, error_string ) < 0 ) goto fail; /* Reopen/flush with the requested number of threads. */ ctx->thread_count = thread_count; int width = ctx->width; int height = ctx->height; lwlibav_flush_buffers( dhp ); ctx->get_buffer2 = exhp->get_buffer ? exhp->get_buffer : avcodec_default_get_buffer2; ctx->opaque = app_specific; /* avcodec_open2() may have changed resolution unexpectedly. */ ctx->width = width; ctx->height = height; return; fail: exhp->delay_count = 0; dhp->error = 1; lw_log_show( &dhp->lh, LW_LOG_FATAL, "%sIt is recommended you reopen the file.", error_string ); }