summaryrefslogtreecommitdiff
path: root/fftools/ffmpeg_demux.c
diff options
context:
space:
mode:
Diffstat (limited to 'fftools/ffmpeg_demux.c')
-rw-r--r--fftools/ffmpeg_demux.c294
1 files changed, 287 insertions, 7 deletions
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 455d3a3f6a..ccee5166c4 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -72,8 +72,6 @@ typedef struct Demuxer {
int non_blocking;
} Demuxer;
-//#include <sys/prctl.h>
-
typedef struct DemuxMsg {
AVPacket *pkt;
int looping;
@@ -243,10 +241,6 @@ static void *input_thread(void *arg)
AVPacket *pkt;
unsigned flags = d->non_blocking ? AV_THREAD_MESSAGE_NONBLOCK : 0;
int ret = 0;
- char thread_name[16];
-
- //snprintf(thread_name, sizeof(thread_name), "demux%d", f->index);
- //prctl(PR_SET_NAME, (unsigned long)thread_name, 0, 0, 0);
pkt = av_packet_alloc();
if (!pkt) {
@@ -268,7 +262,7 @@ static void *input_thread(void *arg)
pkt->flags |= AV_PKT_FLAG_TRUSTED;
pkt->stream_index = 0;
//fprintf(stderr, "dec received %ld\n", pkt->pts);
- f->streams[f->index]->st->time_base = f->dec->ost->mux_timebase;
+ f->streams[pkt->stream_index]->st->time_base = f->dec->ost->mux_timebase;
}
} else
ret = av_read_frame(f->ctx, pkt);
@@ -1150,3 +1144,289 @@ int ifile_open(const OptionsContext *o, const char *filename, int pass, int idx)
return 0;
}
+
+/*
+ for (int i = 0; i < of->nb_streams; i++) {
+ OutputStream *ost = of->streams[i];
+
+ if (ost->enc_ctx && ost->ist) {
+ InputStream *ist = ost->ist;
+ ist->decoding_needed |= DECODING_FOR_OST;
+ ist->processing_needed = 1;
+
+ if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
+ ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+ err = init_simple_filtergraph(ist, ost);
+ if (err < 0) {
+ av_log(ost, AV_LOG_ERROR,
+ "Error initializing a simple filtergraph\n");
+ exit_program(1);
+ }
+ }
+ } else if (ost->ist) {
+ ost->ist->processing_needed = 1;
+ }
+
+
+
+
+ if (stop_time != INT64_MAX && recording_time != INT64_MAX) {
+ stop_time = INT64_MAX;
+ av_log(mux, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
+ }
+
+ if (stop_time != INT64_MAX && recording_time == INT64_MAX) {
+ int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
+ if (stop_time <= start_time) {
+ av_log(mux, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
+ exit_program(1);
+ } else {
+ recording_time = stop_time - start_time;
+ }
+ }
+
+
+
+*/
+
+static void add_decoder_stream(const OptionsContext *o, InputFile *f, int file_index,
+ const char *output_stream)
+{
+ AVCodecParameters *par;
+ InputStream *ist;
+ char *next;
+
+ OutputFile *of;
+ OutputStream *ost;
+ int of_index, ost_index;
+ char *p;
+
+ int ret;
+
+ of_index = strtol(output_stream, &p, 0);
+ if (of_index < 0 || of_index >= nb_output_files) {
+ av_log(NULL, AV_LOG_FATAL, "Invalid output file index for decoder: %s\n", output_stream);
+ exit_program(1);
+ }
+ of = output_files[of_index];
+
+ ost_index = strtol(p + 1, NULL, 0);
+ if (ost_index < 0 || ost_index >= of->nb_streams) {
+ av_log(NULL, AV_LOG_FATAL, "Invalid output stream index for decoder: %s\n", output_stream);
+ exit_program(1);
+ }
+
+ ost = of->streams[ost_index];
+
+ f->dec = av_mallocz(sizeof(*f->dec));
+ f->dec->of = of;
+ f->dec->ost = ost;
+
+ ret = av_thread_message_queue_alloc(&f->dec->fifo,
+ 256, sizeof(AVPacket*));
+ if (ret < 0)
+ exit_program(1);
+
+ ost->dec = f->dec->fifo;
+
+ ist = ALLOC_ARRAY_ELEM(f->streams, f->nb_streams);
+ ist->st = avformat_new_stream(f->ctx, NULL);
+ ist->file_index = f->index;
+ ist->discard = 1;
+ ist->nb_samples = 0;
+ ist->first_dts = AV_NOPTS_VALUE;
+ ist->min_pts = INT64_MAX;
+ ist->max_pts = INT64_MIN;
+ ist->ts_scale = 1.0;
+
+ ist->st->time_base = ost->mux_timebase;
+ ist->framerate = ost->frame_rate;
+
+ par = ist->st->codecpar;
+ avcodec_parameters_copy(par, ost->st->codecpar);
+
+ if (o->nb_codec_tags) {
+ char *codec_tag = o->codec_tags[0].u.str;
+ uint32_t tag = strtol(codec_tag, &next, 0);
+ if (*next)
+ tag = AV_RL32(codec_tag);
+ par->codec_tag = tag;
+ }
+
+ ist->dec = avcodec_find_decoder(par->codec_id);
+ av_dict_copy(&ist->decoder_opts, o->g->codec_opts, 0);
+
+ ist->reinit_filters = -1;
+ ist->user_set_discard = AVDISCARD_NONE;
+
+ ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE;
+ ist->prev_pkt_pts = AV_NOPTS_VALUE;
+
+ ist->dec_ctx = avcodec_alloc_context3(ist->dec);
+ if (!ist->dec_ctx) {
+ av_log(NULL, AV_LOG_ERROR, "Error allocating the decoder context.\n");
+ exit_program(1);
+ }
+
+ ret = avcodec_parameters_to_context(ist->dec_ctx, par);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
+ exit_program(1);
+ }
+
+ ist->decoded_frame = av_frame_alloc();
+ if (!ist->decoded_frame)
+ exit_program(1);
+
+ ist->pkt = av_packet_alloc();
+ if (!ist->pkt)
+ exit_program(1);
+
+ if (o->bitexact)
+ ist->dec_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
+
+ ist->par = avcodec_parameters_alloc();
+ if (!ist->par)
+ exit_program(1);
+ avcodec_parameters_from_context(ist->par, ist->dec_ctx);
+
+ switch (par->codec_type) {
+ case AVMEDIA_TYPE_VIDEO:
+ if(!ist->dec)
+ ist->dec = avcodec_find_decoder(par->codec_id);
+
+ // avformat_find_stream_info() doesn't set this for us anymore.
+ ist->dec_ctx->framerate = ost->frame_rate;
+
+ if (o->nb_frame_rates) {
+ const char *framerate = o->frame_rates[0].u.str;
+ if (framerate && av_parse_video_rate(&ist->framerate,
+ framerate) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error parsing framerate %s.\n",
+ framerate);
+ exit_program(1);
+ }
+ }
+
+ ist->hwaccel_output_format = AV_PIX_FMT_NONE;
+
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ ist->guess_layout_max = INT_MAX;
+ break;
+ default:
+ abort();
+ }
+}
+
+/* if (stop_time != INT64_MAX && recording_time != INT64_MAX) {
+ stop_time = INT64_MAX;
+ av_log(mux, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
+ }
+
+ if (stop_time != INT64_MAX && recording_time == INT64_MAX) {
+ int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
+ if (stop_time <= start_time) {
+ av_log(mux, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
+ exit_program(1);
+ } else {
+ recording_time = stop_time - start_time;
+ }
+ }
+
+*/
+
+int open_decoder(const OptionsContext *o, const char *filename, int pass, int idx)
+{
+ Demuxer *d;
+ InputFile *f;
+ int i;
+ int64_t timestamp;
+ AVDictionary *unused_opts = NULL;
+ const AVDictionaryEntry *e = NULL;
+
+ if (pass > 0)
+ return 0;
+// has to be checked elsewhere since OptionsContext became a const)
+ // if (o->start_time != AV_NOPTS_VALUE && o->start_time_eof != AV_NOPTS_VALUE) {
+ // av_log(NULL, AV_LOG_WARNING, "Cannot use -ss and -sseof both, using -ss for %s\n", filename);
+ // o->start_time_eof = AV_NOPTS_VALUE;
+ // }
+
+ timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time;
+
+ idx = nb_input_files;
+ d = allocate_array_elem(&input_files, sizeof(*d), &nb_input_files);
+ f = &d->f;
+
+ f->ctx = avformat_alloc_context();
+ f->ctx->iformat = av_find_input_format("matroska");
+
+ f->index = idx;
+ f->start_time = o->start_time;
+ f->recording_time = o->recording_time;
+ f->input_sync_ref = o->input_sync_ref;
+ f->input_ts_offset = o->input_ts_offset;
+ f->ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp);
+ f->rate_emu = o->rate_emu;
+ f->accurate_seek = o->accurate_seek;
+ d->loop = o->loop;
+ d->duration = 0;
+ d->time_base = (AVRational){ 1, 1 };
+
+ add_decoder_stream(o, f, idx, filename);
+
+ f->readrate = o->readrate ? o->readrate : 0.0;
+ if (f->readrate < 0.0f) {
+ av_log(NULL, AV_LOG_ERROR, "Option -readrate for Input #%d is %0.3f; it must be non-negative.\n", nb_input_files, f->readrate);
+ exit_program(1);
+ }
+ if (f->readrate && f->rate_emu) {
+ av_log(NULL, AV_LOG_WARNING, "Both -readrate and -re set for Input #%d. Using -readrate %0.3f.\n", nb_input_files, f->readrate);
+ f->rate_emu = 0;
+ }
+
+ d->thread_queue_size = o->thread_queue_size;
+
+ /* check if all codec options have been used */
+ unused_opts = strip_specifiers(o->g->codec_opts);
+ for (i = f->index; i < f->nb_streams; i++) {
+ e = NULL;
+ while ((e = av_dict_get(f->streams[i]->decoder_opts, "", e,
+ AV_DICT_IGNORE_SUFFIX)))
+ av_dict_set(&unused_opts, e->key, NULL, 0);
+ }
+
+ e = NULL;
+ while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
+ const AVClass *class = avcodec_get_class();
+ const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
+ AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
+ const AVClass *fclass = avformat_get_class();
+ const AVOption *foption = av_opt_find(&fclass, e->key, NULL, 0,
+ AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
+ if (!option || foption)
+ continue;
+
+
+ if (!(option->flags & AV_OPT_FLAG_DECODING_PARAM)) {
+ av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
+ "input file #%d (%s) is not a decoding option.\n", e->key,
+ option->help ? option->help : "", nb_input_files - 1,
+ filename);
+ exit_program(1);
+ }
+
+ av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
+ "input file #%d (%s) has not been used for any stream. The most "
+ "likely reason is either wrong type (e.g. a video option with "
+ "no video streams) or that it is a private option of some decoder "
+ "which was not actually used for any stream.\n", e->key,
+ option->help ? option->help : "", nb_input_files - 1, filename);
+ }
+ av_dict_free(&unused_opts);
+
+ //input_stream_potentially_available = 1;
+
+ return 0;
+}