int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; int ret, i, simple = !fg->graph_desc; const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : fg->graph_desc; avfilter_graph_free(&fg->graph); if (!(fg->graph = avfilter_graph_alloc())) return AVERROR(ENOMEM); if (simple) { OutputStream *ost = fg->outputs[0]->ost; char args[512]; AVDictionaryEntry *e = NULL; args[0] = 0; while ((e = av_dict_get(ost->sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args)-1] = 0; fg->graph->scale_sws_opts = av_strdup(args); args[0] = 0; while ((e = av_dict_get(ost->swr_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args)-1] = 0; av_opt_set(fg->graph, "aresample_swr_opts", args, 0); args[0] = '\0'; while ((e = av_dict_get(fg->outputs[0]->ost->resample_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args) - 1] = '\0'; fg->graph->resample_lavr_opts = av_strdup(args); e = av_dict_get(ost->encoder_opts, "threads", NULL, 0); if (e) av_opt_set(fg->graph, "threads", e->value, 0); } if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) return ret; if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { const char *num_inputs; const char *num_outputs; if (!outputs) { num_outputs = "0"; } else if (outputs->next) { num_outputs = ">1"; } else { num_outputs = "1"; } if (!inputs) { num_inputs = "0"; } else if (inputs->next) { num_inputs = ">1"; } else { num_inputs = "1"; } av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " "to have exactly 1 input and 1 output." " However, it had %s input(s) and %s output(s)." " Please adjust, or use a complex filtergraph (-filter_complex) instead.\n", graph_desc, num_inputs, num_outputs); return AVERROR(EINVAL); } for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) { avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return ret; } avfilter_inout_free(&inputs); for (cur = outputs, i = 0; cur; cur = cur->next, i++) configure_output_filter(fg, fg->outputs[i], cur); avfilter_inout_free(&outputs); if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) return ret; fg->reconfiguration = 1; for (i = 0; i < fg->nb_outputs; i++) { OutputStream *ost = fg->outputs[i]->ost; if (!ost->enc) { /* identical to the same check in ffmpeg.c, needed because complex filter graphs are initialized earlier */ av_log(NULL, AV_LOG_ERROR, "Encoder (codec %s) not found for output stream #%d:%d\n", avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index); return AVERROR(EINVAL); } if (ost->enc->type == AVMEDIA_TYPE_AUDIO && !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) av_buffersink_set_frame_size(ost->filter->filter, ost->enc_ctx->frame_size); } return 0; }
static void write_metadata(AVFormatContext *s, unsigned int ts) { AVIOContext *pb = s->pb; FLVContext *flv = s->priv_data; int metadata_count = 0; int64_t metadata_size_pos, data_size, metadata_count_pos; AVDictionaryEntry *tag = NULL; /* write meta_tag */ avio_w8(pb, 18); // tag type META metadata_size_pos = avio_tell(pb); avio_wb24(pb, 0); // size of data part (sum of all parts below) avio_wb24(pb, ts); // timestamp avio_wb32(pb, 0); // reserved /* now data of data_size size */ /* first event name as a string */ avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, "onMetaData"); // 12 bytes /* mixed array (hash) with size and string/type/data tuples */ avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); metadata_count_pos = avio_tell(pb); metadata_count = 4 * !!flv->video_par + 5 * !!flv->audio_par + 1 * !!flv->data_par + 2; // +2 for duration and file size avio_wb32(pb, metadata_count); put_amf_string(pb, "duration"); flv->duration_offset = avio_tell(pb); // fill in the guessed duration, it'll be corrected later if incorrect put_amf_double(pb, s->duration / AV_TIME_BASE); if (flv->video_par) { put_amf_string(pb, "width"); put_amf_double(pb, flv->video_par->width); put_amf_string(pb, "height"); put_amf_double(pb, flv->video_par->height); put_amf_string(pb, "videodatarate"); put_amf_double(pb, flv->video_par->bit_rate / 1024.0); if (flv->framerate != 0.0) { put_amf_string(pb, "framerate"); put_amf_double(pb, flv->framerate); metadata_count++; } put_amf_string(pb, "videocodecid"); put_amf_double(pb, flv->video_par->codec_tag); } if (flv->audio_par) { put_amf_string(pb, "audiodatarate"); put_amf_double(pb, flv->audio_par->bit_rate / 1024.0); put_amf_string(pb, "audiosamplerate"); put_amf_double(pb, flv->audio_par->sample_rate); put_amf_string(pb, "audiosamplesize"); put_amf_double(pb, flv->audio_par->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16); put_amf_string(pb, "stereo"); put_amf_bool(pb, flv->audio_par->channels == 2); put_amf_string(pb, "audiocodecid"); put_amf_double(pb, flv->audio_par->codec_tag); } if (flv->data_par) { put_amf_string(pb, "datastream"); put_amf_double(pb, 0.0); } while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { put_amf_string(pb, tag->key); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, tag->value); metadata_count++; } put_amf_string(pb, "filesize"); flv->filesize_offset = avio_tell(pb); put_amf_double(pb, 0); // delayed write put_amf_string(pb, ""); avio_w8(pb, AMF_END_OF_OBJECT); /* write total size of tag */ data_size = avio_tell(pb) - metadata_size_pos - 10; avio_seek(pb, metadata_count_pos, SEEK_SET); avio_wb32(pb, metadata_count); avio_seek(pb, metadata_size_pos, SEEK_SET); avio_wb24(pb, data_size); avio_skip(pb, data_size + 10 - 3); avio_wb32(pb, data_size + 11); }
static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) { char *pix_fmts; OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; AVCodecContext *codec = ost->enc_ctx; AVFilterContext *last_filter = out->filter_ctx; int pad_idx = out->pad_idx; int ret; char name[255]; snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index); ret = avfilter_graph_create_filter(&ofilter->filter, avfilter_get_by_name("buffersink"), name, NULL, NULL, fg->graph); if (ret < 0) return ret; if (codec->width || codec->height) { char args[255]; AVFilterContext *filter; AVDictionaryEntry *e = NULL; snprintf(args, sizeof(args), "%d:%d", codec->width, codec->height); while ((e = av_dict_get(ost->sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value); } snprintf(name, sizeof(name), "scaler for output stream %d:%d", ost->file_index, ost->index); if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"), name, args, NULL, fg->graph)) < 0) return ret; if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) return ret; last_filter = filter; pad_idx = 0; } if ((pix_fmts = choose_pix_fmts(ost))) { AVFilterContext *filter; snprintf(name, sizeof(name), "pixel format for output stream %d:%d", ost->file_index, ost->index); ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("format"), "format", pix_fmts, NULL, fg->graph); av_freep(&pix_fmts); if (ret < 0) return ret; if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) return ret; last_filter = filter; pad_idx = 0; } if (ost->frame_rate.num && 0) { AVFilterContext *fps; char args[255]; snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num, ost->frame_rate.den); snprintf(name, sizeof(name), "fps for output stream %d:%d", ost->file_index, ost->index); ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"), name, args, NULL, fg->graph); if (ret < 0) return ret; ret = avfilter_link(last_filter, pad_idx, fps, 0); if (ret < 0) return ret; last_filter = fps; pad_idx = 0; } snprintf(name, sizeof(name), "trim for output stream %d:%d", ost->file_index, ost->index); ret = insert_trim(of->start_time, of->recording_time, &last_filter, &pad_idx, name); if (ret < 0) return ret; if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0) return ret; return 0; }
static int tta_read_header(AVFormatContext *s, AVFormatParameters *ap) { TTAContext *c = s->priv_data; AVStream *st; int i, channels, bps, samplerate, datalen, framelen; uint64_t framepos, start_offset; if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); start_offset = avio_tell(s->pb); if (avio_rl32(s->pb) != AV_RL32("TTA1")) return -1; // not tta file avio_skip(s->pb, 2); // FIXME: flags channels = avio_rl16(s->pb); bps = avio_rl16(s->pb); samplerate = avio_rl32(s->pb); if(samplerate <= 0 || samplerate > 1000000){ av_log(s, AV_LOG_ERROR, "nonsense samplerate\n"); return -1; } datalen = avio_rl32(s->pb); if(datalen < 0){ av_log(s, AV_LOG_ERROR, "nonsense datalen\n"); return -1; } avio_skip(s->pb, 4); // header crc framelen = samplerate*256/245; c->totalframes = datalen / framelen + ((datalen % framelen) ? 1 : 0); c->currentframe = 0; if(c->totalframes >= UINT_MAX/sizeof(uint32_t)){ av_log(s, AV_LOG_ERROR, "totalframes too large\n"); return -1; } st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 64, 1, samplerate); st->start_time = 0; st->duration = datalen; framepos = avio_tell(s->pb) + 4*c->totalframes + 4; for (i = 0; i < c->totalframes; i++) { uint32_t size = avio_rl32(s->pb); av_add_index_entry(st, framepos, i*framelen, size, 0, AVINDEX_KEYFRAME); framepos += size; } avio_skip(s->pb, 4); // seektable crc st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_TTA; st->codec->channels = channels; st->codec->sample_rate = samplerate; st->codec->bits_per_coded_sample = bps; st->codec->extradata_size = avio_tell(s->pb) - start_offset; if(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){ //this check is redundant as avio_read should fail av_log(s, AV_LOG_ERROR, "extradata_size too large\n"); return -1; } st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE); avio_seek(s->pb, start_offset, SEEK_SET); avio_read(s->pb, st->codec->extradata, st->codec->extradata_size); return 0; }
static int rv10_write_header(AVFormatContext *ctx, int data_size, int index_pos) { RMMuxContext *rm = ctx->priv_data; AVIOContext *s = ctx->pb; StreamInfo *stream; unsigned char *data_offset_ptr, *start_ptr; const char *desc, *mimetype; int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i; int bit_rate, v, duration, flags, data_pos; AVDictionaryEntry *tag; start_ptr = s->buf_ptr; ffio_wfourcc(s, ".RMF"); avio_wb32(s,18); /* header size */ avio_wb16(s,0); avio_wb32(s,0); avio_wb32(s,4 + ctx->nb_streams); /* num headers */ ffio_wfourcc(s,"PROP"); avio_wb32(s, 50); avio_wb16(s, 0); packet_max_size = 0; packet_total_size = 0; nb_packets = 0; bit_rate = 0; duration = 0; for(i=0;i<ctx->nb_streams;i++) { StreamInfo *stream = &rm->streams[i]; bit_rate += stream->bit_rate; if (stream->packet_max_size > packet_max_size) packet_max_size = stream->packet_max_size; nb_packets += stream->nb_packets; packet_total_size += stream->packet_total_size; /* select maximum duration */ v = av_rescale_q_rnd(stream->total_frames, (AVRational){1000, 1}, stream->frame_rate, AV_ROUND_ZERO); if (v > duration) duration = v; } avio_wb32(s, bit_rate); /* max bit rate */ avio_wb32(s, bit_rate); /* avg bit rate */ avio_wb32(s, packet_max_size); /* max packet size */ if (nb_packets > 0) packet_avg_size = packet_total_size / nb_packets; else packet_avg_size = 0; avio_wb32(s, packet_avg_size); /* avg packet size */ avio_wb32(s, nb_packets); /* num packets */ avio_wb32(s, duration); /* duration */ avio_wb32(s, BUFFER_DURATION); /* preroll */ avio_wb32(s, index_pos); /* index offset */ /* computation of data the data offset */ data_offset_ptr = s->buf_ptr; avio_wb32(s, 0); /* data offset : will be patched after */ avio_wb16(s, ctx->nb_streams); /* num streams */ flags = 1 | 2; /* save allowed & perfect play */ if (!s->seekable) flags |= 4; /* live broadcast */ avio_wb16(s, flags); /* comments */ ffio_wfourcc(s,"CONT"); size = 4 * 2 + 10; for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { tag = av_dict_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); if(tag) size += strlen(tag->value); } avio_wb32(s,size); avio_wb16(s,0); for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { tag = av_dict_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); put_str(s, tag ? tag->value : ""); } for(i=0;i<ctx->nb_streams;i++) { int codec_data_size; stream = &rm->streams[i]; if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) { desc = "The Audio Stream"; mimetype = "audio/x-pn-realaudio"; codec_data_size = 73; } else { desc = "The Video Stream"; mimetype = "video/x-pn-realvideo"; codec_data_size = 34; } ffio_wfourcc(s,"MDPR"); size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size; avio_wb32(s, size); avio_wb16(s, 0); avio_wb16(s, i); /* stream number */ avio_wb32(s, stream->bit_rate); /* max bit rate */ avio_wb32(s, stream->bit_rate); /* avg bit rate */ avio_wb32(s, stream->packet_max_size); /* max packet size */ if (stream->nb_packets > 0) packet_avg_size = stream->packet_total_size / stream->nb_packets; else packet_avg_size = 0; avio_wb32(s, packet_avg_size); /* avg packet size */ avio_wb32(s, 0); /* start time */ avio_wb32(s, BUFFER_DURATION); /* preroll */ /* duration */ if (!s->seekable || !stream->total_frames) avio_wb32(s, (int)(3600 * 1000)); else avio_wb32(s, av_rescale_q_rnd(stream->total_frames, (AVRational){1000, 1}, stream->frame_rate, AV_ROUND_ZERO)); put_str8(s, desc); put_str8(s, mimetype); avio_wb32(s, codec_data_size); if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) { int coded_frame_size, fscode, sample_rate; sample_rate = stream->enc->sample_rate; coded_frame_size = (stream->enc->bit_rate * stream->enc->frame_size) / (8 * sample_rate); /* audio codec info */ avio_write(s, ".ra", 3); avio_w8(s, 0xfd); avio_wb32(s, 0x00040000); /* version */ ffio_wfourcc(s, ".ra4"); avio_wb32(s, 0x01b53530); /* stream length */ avio_wb16(s, 4); /* unknown */ avio_wb32(s, 0x39); /* header size */ switch(sample_rate) { case 48000: case 24000: case 12000: fscode = 1; break; default: case 44100: case 22050: case 11025: fscode = 2; break; case 32000: case 16000: case 8000: fscode = 3; } avio_wb16(s, fscode); /* codec additional info, for AC-3, seems to be a frequency code */ /* special hack to compensate rounding errors... */ if (coded_frame_size == 557) coded_frame_size--; avio_wb32(s, coded_frame_size); /* frame length */ avio_wb32(s, 0x51540); /* unknown */ avio_wb32(s, stream->enc->bit_rate / 8 * 60); /* bytes per minute */ avio_wb32(s, stream->enc->bit_rate / 8 * 60); /* bytes per minute */ avio_wb16(s, 0x01); /* frame length : seems to be very important */ avio_wb16(s, coded_frame_size); avio_wb32(s, 0); /* unknown */ avio_wb16(s, stream->enc->sample_rate); /* sample rate */ avio_wb32(s, 0x10); /* unknown */ avio_wb16(s, stream->enc->channels); put_str8(s, "Int0"); /* codec name */ if (stream->enc->codec_tag) { avio_w8(s, 4); /* tag length */ avio_wl32(s, stream->enc->codec_tag); } else { av_log(ctx, AV_LOG_ERROR, "Invalid codec tag\n"); return -1; } avio_wb16(s, 0); /* title length */ avio_wb16(s, 0); /* author length */ avio_wb16(s, 0); /* copyright length */ avio_w8(s, 0); /* end of header */ } else { /* video codec info */ avio_wb32(s,34); /* size */ ffio_wfourcc(s, "VIDO"); if(stream->enc->codec_id == AV_CODEC_ID_RV10) ffio_wfourcc(s,"RV10"); else ffio_wfourcc(s,"RV20"); avio_wb16(s, stream->enc->width); avio_wb16(s, stream->enc->height); avio_wb16(s, stream->frame_rate.num / stream->frame_rate.den); /* frames per seconds ? */ avio_wb32(s,0); /* unknown meaning */ avio_wb16(s, stream->frame_rate.num / stream->frame_rate.den); /* unknown meaning */ avio_wb32(s,0); /* unknown meaning */ avio_wb16(s, 8); /* unknown meaning */ /* Seems to be the codec version: only use basic H263. The next versions seems to add a diffential DC coding as in MPEG... nothing new under the sun */ if(stream->enc->codec_id == AV_CODEC_ID_RV10) avio_wb32(s,0x10000000); else avio_wb32(s,0x20103001); //avio_wb32(s,0x10003000); } } /* patch data offset field */ data_pos = s->buf_ptr - start_ptr; rm->data_pos = data_pos; data_offset_ptr[0] = data_pos >> 24; data_offset_ptr[1] = data_pos >> 16; data_offset_ptr[2] = data_pos >> 8; data_offset_ptr[3] = data_pos; /* data stream */ ffio_wfourcc(s, "DATA"); avio_wb32(s,data_size + 10 + 8); avio_wb16(s,0); avio_wb32(s, nb_packets); /* number of packets */ avio_wb32(s,0); /* next data header */ return 0; }
int avfilter_init_str(AVFilterContext *filter, const char *args) { AVDictionary *options = NULL; AVDictionaryEntry *e; int ret = 0; if (args && *args) { if (!filter->filter->priv_class) { av_log(filter, AV_LOG_ERROR, "This filter does not take any " "options, but options were provided: %s.\n", args); return AVERROR(EINVAL); } #if FF_API_OLD_FILTER_OPTS if (!strcmp(filter->filter->name, "scale") && strchr(args, ':') && strchr(args, ':') < strchr(args, '=')) { /* old w:h:flags=<flags> syntax */ char *copy = av_strdup(args); char *p; av_log(filter, AV_LOG_WARNING, "The <w>:<h>:flags=<flags> option " "syntax is deprecated. Use either <w>:<h>:<flags> or " "w=<w>:h=<h>:flags=<flags>.\n"); if (!copy) { ret = AVERROR(ENOMEM); goto fail; } p = strrchr(copy, ':'); if (p) { *p++ = 0; ret = av_dict_parse_string(&options, p, "=", ":", 0); } if (ret >= 0) ret = process_unnamed_options(filter, &options, copy); av_freep(©); if (ret < 0) goto fail; } else #endif if (strchr(args, '=')) { /* assume a list of key1=value1:key2=value2:... */ ret = av_dict_parse_string(&options, args, "=", ":", 0); if (ret < 0) goto fail; #if FF_API_OLD_FILTER_OPTS } else if (!strcmp(filter->filter->name, "format") || !strcmp(filter->filter->name, "noformat") || !strcmp(filter->filter->name, "frei0r") || !strcmp(filter->filter->name, "frei0r_src") || !strcmp(filter->filter->name, "ocv")) { /* a hack for compatibility with the old syntax * replace colons with |s */ char *copy = av_strdup(args); char *p = copy; int nb_leading = 0; // number of leading colons to skip if (!copy) { ret = AVERROR(ENOMEM); goto fail; } if (!strcmp(filter->filter->name, "frei0r") || !strcmp(filter->filter->name, "ocv")) nb_leading = 1; else if (!strcmp(filter->filter->name, "frei0r_src")) nb_leading = 3; while (nb_leading--) { p = strchr(p, ':'); if (!p) { p = copy + strlen(copy); break; } p++; } if (strchr(p, ':')) { av_log(filter, AV_LOG_WARNING, "This syntax is deprecated. Use " "'|' to separate the list items.\n"); } while ((p = strchr(p, ':'))) *p++ = '|'; ret = process_unnamed_options(filter, &options, copy); av_freep(©); if (ret < 0) goto fail; #endif } else { ret = process_unnamed_options(filter, &options, args); if (ret < 0) goto fail; } } ret = avfilter_init_dict(filter, &options); if (ret < 0) goto fail; if ((e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX))) { av_log(filter, AV_LOG_ERROR, "No such option: %s.\n", e->key); ret = AVERROR_OPTION_NOT_FOUND; goto fail; } fail: av_dict_free(&options); return ret; }
static av_cold int libkvazaar_init(AVCodecContext *avctx) { int retval = 0; kvz_config *cfg = NULL; kvz_encoder *enc = NULL; const kvz_api *const api = kvz_api_get(8); LibkvazaarContext *const ctx = avctx->priv_data; // Kvazaar requires width and height to be multiples of eight. if (avctx->width % 8 || avctx->height % 8) { av_log(avctx, AV_LOG_ERROR, "Video dimensions are not a multiple of 8.\n"); retval = AVERROR_INVALIDDATA; goto done; } cfg = api->config_alloc(); if (!cfg) { av_log(avctx, AV_LOG_ERROR, "Could not allocate kvazaar config structure.\n"); retval = AVERROR(ENOMEM); goto done; } if (!api->config_init(cfg)) { av_log(avctx, AV_LOG_ERROR, "Could not initialize kvazaar config structure.\n"); retval = AVERROR_EXTERNAL; goto done; } cfg->width = avctx->width; cfg->height = avctx->height; cfg->framerate = avctx->time_base.den / (double)(avctx->time_base.num * avctx->ticks_per_frame); cfg->target_bitrate = avctx->bit_rate; cfg->vui.sar_width = avctx->sample_aspect_ratio.num; cfg->vui.sar_height = avctx->sample_aspect_ratio.den; if (ctx->kvz_params) { AVDictionary *dict = NULL; if (!av_dict_parse_string(&dict, ctx->kvz_params, "=", ",", 0)) { AVDictionaryEntry *entry = NULL; while ((entry = av_dict_get(dict, "", entry, AV_DICT_IGNORE_SUFFIX))) { if (!api->config_parse(cfg, entry->key, entry->value)) { av_log(avctx, AV_LOG_WARNING, "Invalid option: %s=%s.\n", entry->key, entry->value); } } av_dict_free(&dict); } } enc = api->encoder_open(cfg); if (!enc) { av_log(avctx, AV_LOG_ERROR, "Could not open kvazaar encoder.\n"); retval = AVERROR_EXTERNAL; goto done; } ctx->api = api; ctx->encoder = enc; ctx->config = cfg; enc = NULL; cfg = NULL; done: api->config_destroy(cfg); api->encoder_close(enc); return retval; }
/***************************************************************************** * VideoCommand: Create/Delete a video encoder *****************************************************************************/ static mtime_t VideoCommand( sout_stream_t *p_stream, sout_stream_id_t *id ) { sout_stream_sys_t *p_sys = p_stream->p_sys; if ( p_sys->i_cmd == 0 && !(id->p_queued->i_flags & BLOCK_FLAG_TYPE_I) ) { mtime_t i_dts = id->p_queued->i_dts; block_t *p_block = id->p_queued->p_next; while ( p_block != NULL ) { if ( p_block->i_flags & BLOCK_FLAG_TYPE_I ) return i_dts; i_dts = p_block->i_dts; p_block = p_block->p_next; } return 0; } p_sys->i_old_cmd = p_sys->i_cmd; if ( id->ff_enc ) { vlc_avcodec_lock(); avcodec_close( id->ff_enc_c ); vlc_avcodec_unlock(); av_free( id->ff_enc_c ); av_free( id->p_frame ); free( id->p_buffer_out ); id->ff_enc = NULL; } if ( p_sys->i_cmd > 0 ) { /* Create a new encoder. */ int i_ff_codec = AV_CODEC_ID_MPEG2VIDEO; int i_aspect_num, i_aspect_den; if( i_ff_codec == 0 ) { msg_Err( p_stream, "cannot find encoder" ); return 0; } id->ff_enc = avcodec_find_encoder( i_ff_codec ); if( !id->ff_enc ) { msg_Err( p_stream, "cannot find encoder (avcodec)" ); return 0; } id->ff_enc_c = avcodec_alloc_context3( id->ff_enc ); id->ff_enc_c->dsp_mask = GetVlcDspMask(); id->ff_enc_c->width = p_sys->p_pictures[p_sys->i_cmd-1].format.i_width; id->ff_enc_c->height = p_sys->p_pictures[p_sys->i_cmd-1].format.i_height; av_reduce( &i_aspect_num, &i_aspect_den, p_sys->i_aspect, VOUT_ASPECT_FACTOR, 1 << 30 /* something big */ ); av_reduce( &id->ff_enc_c->sample_aspect_ratio.num, &id->ff_enc_c->sample_aspect_ratio.den, i_aspect_num * (int64_t)id->ff_enc_c->height, i_aspect_den * (int64_t)id->ff_enc_c->width, 1 << 30 ); id->ff_enc_c->time_base.num = 1; id->ff_enc_c->time_base.den = 25; /* FIXME */ id->ff_enc_c->gop_size = 200; id->ff_enc_c->max_b_frames = 0; id->ff_enc_c->flags |= CODEC_FLAG_QSCALE | CODEC_FLAG_INPUT_PRESERVED | CODEC_FLAG_LOW_DELAY; id->ff_enc_c->mb_decision = FF_MB_DECISION_SIMPLE; id->ff_enc_c->pix_fmt = PIX_FMT_YUV420P; vlc_avcodec_lock(); int ret; #if LIBAVCODEC_VERSION_MAJOR >= 54 AVDictionary *options = NULL; if (p_sys->options) av_dict_copy(&options, p_sys->options, 0); #endif ret = avcodec_open2( id->ff_enc_c, id->ff_enc, options ? &options : NULL ); vlc_avcodec_unlock(); #if LIBAVCODEC_VERSION_MAJOR >= 54 AVDictionaryEntry *t = NULL; while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) { msg_Err( p_stream, "Unknown option \"%s\"", t->key ); } av_dict_free(&options); #endif if (ret) { msg_Err( p_stream, "cannot open encoder" ); return 0; } id->p_buffer_out = malloc( id->ff_enc_c->width * id->ff_enc_c->height * 3 ); id->p_frame = avcodec_alloc_frame(); id->p_frame->linesize[0] = p_sys->p_pictures[p_sys->i_cmd-1].p[0].i_pitch; id->p_frame->linesize[1] = p_sys->p_pictures[p_sys->i_cmd-1].p[1].i_pitch; id->p_frame->linesize[2] = p_sys->p_pictures[p_sys->i_cmd-1].p[2].i_pitch; id->p_frame->data[0] = p_sys->p_pictures[p_sys->i_cmd-1].p[0].p_pixels; id->p_frame->data[1] = p_sys->p_pictures[p_sys->i_cmd-1].p[1].p_pixels; id->p_frame->data[2] = p_sys->p_pictures[p_sys->i_cmd-1].p[2].p_pixels; id->i_nb_pred = p_sys->i_gop; } return 0; }
static int avi_write_header(AVFormatContext *s) { AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; AVCodecContext *stream, *video_enc; int64_t list1, list2, strh, strf; AVDictionaryEntry *t = NULL; if (s->nb_streams > AVI_MAX_STREAM_COUNT) { av_log(s, AV_LOG_ERROR, "AVI does not support >%d streams\n", AVI_MAX_STREAM_COUNT); return -1; } for(n=0;n<s->nb_streams;n++) { s->streams[n]->priv_data= av_mallocz(sizeof(AVIStream)); if(!s->streams[n]->priv_data) return AVERROR(ENOMEM); } /* header list */ avi->riff_id = 0; list1 = avi_start_new_riff(s, pb, "AVI ", "hdrl"); /* avi header */ ffio_wfourcc(pb, "avih"); avio_wl32(pb, 14 * 4); bitrate = 0; video_enc = NULL; for(n=0;n<s->nb_streams;n++) { stream = s->streams[n]->codec; bitrate += stream->bit_rate; if (stream->codec_type == AVMEDIA_TYPE_VIDEO) video_enc = stream; } nb_frames = 0; if(video_enc){ avio_wl32(pb, (uint32_t)(INT64_C(1000000) * video_enc->time_base.num / video_enc->time_base.den)); } else { avio_wl32(pb, 0); } avio_wl32(pb, bitrate / 8); /* XXX: not quite exact */ avio_wl32(pb, 0); /* padding */ if (!pb->seekable) avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */ else avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ avi->frames_hdr_all = avio_tell(pb); /* remember this offset to fill later */ avio_wl32(pb, nb_frames); /* nb frames, filled later */ avio_wl32(pb, 0); /* initial frame */ avio_wl32(pb, s->nb_streams); /* nb streams */ avio_wl32(pb, 1024 * 1024); /* suggested buffer size */ if(video_enc){ avio_wl32(pb, video_enc->width); avio_wl32(pb, video_enc->height); } else { avio_wl32(pb, 0); avio_wl32(pb, 0); } avio_wl32(pb, 0); /* reserved */ avio_wl32(pb, 0); /* reserved */ avio_wl32(pb, 0); /* reserved */ avio_wl32(pb, 0); /* reserved */ /* stream list */ for(i=0;i<n;i++) { AVIStream *avist= s->streams[i]->priv_data; list2 = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "strl"); stream = s->streams[i]->codec; /* stream generic header */ strh = ff_start_tag(pb, "strh"); switch(stream->codec_type) { case AVMEDIA_TYPE_SUBTITLE: // XSUB subtitles behave like video tracks, other subtitles // are not (yet) supported. if (stream->codec_id != CODEC_ID_XSUB) { av_log(s, AV_LOG_ERROR, "Subtitle streams other than DivX XSUB are not supported by the AVI muxer.\n"); return AVERROR_PATCHWELCOME; } case AVMEDIA_TYPE_VIDEO: ffio_wfourcc(pb, "vids"); break; case AVMEDIA_TYPE_AUDIO: ffio_wfourcc(pb, "auds"); break; // case AVMEDIA_TYPE_TEXT : ffio_wfourcc(pb, "txts"); break; case AVMEDIA_TYPE_DATA : ffio_wfourcc(pb, "dats"); break; } if(stream->codec_type == AVMEDIA_TYPE_VIDEO || stream->codec_id == CODEC_ID_XSUB) avio_wl32(pb, stream->codec_tag); else avio_wl32(pb, 1); avio_wl32(pb, 0); /* flags */ avio_wl16(pb, 0); /* priority */ avio_wl16(pb, 0); /* language */ avio_wl32(pb, 0); /* initial frame */ ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); avio_wl32(pb, au_scale); /* scale */ avio_wl32(pb, au_byterate); /* rate */ avpriv_set_pts_info(s->streams[i], 64, au_scale, au_byterate); avio_wl32(pb, 0); /* start */ avist->frames_hdr_strm = avio_tell(pb); /* remember this offset to fill later */ if (!pb->seekable) avio_wl32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */ else avio_wl32(pb, 0); /* length, XXX: filled later */ /* suggested buffer size */ //FIXME set at the end to largest chunk if(stream->codec_type == AVMEDIA_TYPE_VIDEO) avio_wl32(pb, 1024 * 1024); else if(stream->codec_type == AVMEDIA_TYPE_AUDIO) avio_wl32(pb, 12 * 1024); else avio_wl32(pb, 0); avio_wl32(pb, -1); /* quality */ avio_wl32(pb, au_ssize); /* sample size */ avio_wl32(pb, 0); avio_wl16(pb, stream->width); avio_wl16(pb, stream->height); ff_end_tag(pb, strh); if(stream->codec_type != AVMEDIA_TYPE_DATA){ strf = ff_start_tag(pb, "strf"); switch(stream->codec_type) { case AVMEDIA_TYPE_SUBTITLE: // XSUB subtitles behave like video tracks, other subtitles // are not (yet) supported. if (stream->codec_id != CODEC_ID_XSUB) break; case AVMEDIA_TYPE_VIDEO: ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0); break; case AVMEDIA_TYPE_AUDIO: if (ff_put_wav_header(pb, stream) < 0) { return -1; } break; default: return -1; } ff_end_tag(pb, strf); if ((t = av_dict_get(s->streams[i]->metadata, "title", NULL, 0))) { avi_write_info_tag(s->pb, "strn", t->value); t = NULL; } } if (pb->seekable) { unsigned char tag[5]; int j; /* Starting to lay out AVI OpenDML master index. * We want to make it JUNK entry for now, since we'd * like to get away without making AVI an OpenDML one * for compatibility reasons. */ avist->indexes.entry = avist->indexes.ents_allocated = 0; avist->indexes.indx_start = ff_start_tag(pb, "JUNK"); avio_wl16(pb, 4); /* wLongsPerEntry */ avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */ avio_w8(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */ avio_wl32(pb, 0); /* nEntriesInUse (will fill out later on) */ ffio_wfourcc(pb, avi_stream2fourcc(tag, i, stream->codec_type)); /* dwChunkId */ avio_wl64(pb, 0); /* dwReserved[3] avio_wl32(pb, 0); Must be 0. */ for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++) avio_wl64(pb, 0); ff_end_tag(pb, avist->indexes.indx_start); } if( stream->codec_type == AVMEDIA_TYPE_VIDEO && s->streams[i]->sample_aspect_ratio.num>0 && s->streams[i]->sample_aspect_ratio.den>0){ int vprp= ff_start_tag(pb, "vprp"); AVRational dar = av_mul_q(s->streams[i]->sample_aspect_ratio, (AVRational){stream->width, stream->height}); int num, den; av_reduce(&num, &den, dar.num, dar.den, 0xFFFF); avio_wl32(pb, 0); //video format = unknown avio_wl32(pb, 0); //video standard= unknown avio_wl32(pb, lrintf(1.0/av_q2d(stream->time_base))); avio_wl32(pb, stream->width ); avio_wl32(pb, stream->height); avio_wl16(pb, den); avio_wl16(pb, num); avio_wl32(pb, stream->width ); avio_wl32(pb, stream->height); avio_wl32(pb, 1); //progressive FIXME avio_wl32(pb, stream->height); avio_wl32(pb, stream->width ); avio_wl32(pb, stream->height); avio_wl32(pb, stream->width ); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, 0); ff_end_tag(pb, vprp); } ff_end_tag(pb, list2); } if (pb->seekable) { /* AVI could become an OpenDML one, if it grows beyond 2Gb range */ avi->odml_list = ff_start_tag(pb, "JUNK"); ffio_wfourcc(pb, "odml"); ffio_wfourcc(pb, "dmlh"); avio_wl32(pb, 248); for (i = 0; i < 248; i+= 4) avio_wl32(pb, 0); ff_end_tag(pb, avi->odml_list); } ff_end_tag(pb, list1); list2 = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "INFO"); ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL); for (i = 0; *ff_riff_tags[i]; i++) { if ((t = av_dict_get(s->metadata, ff_riff_tags[i], NULL, AV_DICT_MATCH_CASE))) avi_write_info_tag(s->pb, t->key, t->value); } ff_end_tag(pb, list2); /* some padding for easier tag editing */ list2 = ff_start_tag(pb, "JUNK"); for (i = 0; i < 1016; i += 4) avio_wl32(pb, 0); ff_end_tag(pb, list2); avi->movi_list = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "movi"); avio_flush(pb); return 0; }
int OpenAvio(vlc_object_t *object) { access_t *access = (access_t*)object; access_sys_t *sys = malloc(sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->context = NULL; /* We accept: * - avio://full_url * - url (only a subset of available protocols). */ char *url; if (!strcmp(access->psz_access, "avio")) url = strdup(access->psz_location); else if (asprintf(&url, "%s://%s", access->psz_access, access->psz_location) < 0) url = NULL; if (!url) { free(sys); return VLC_ENOMEM; } /* */ vlc_init_avformat(object); int ret; #if LIBAVFORMAT_VERSION_MAJOR < 54 ret = avio_open(&sys->context, url, AVIO_FLAG_READ); #else AVIOInterruptCB cb = { .callback = UrlInterruptCallback, .opaque = access, }; AVDictionary *options = NULL; char *psz_opts = var_InheritString(access, "avio-options"); if (psz_opts && *psz_opts) { options = vlc_av_get_options(psz_opts); free(psz_opts); } ret = avio_open2(&sys->context, url, AVIO_FLAG_READ, &cb, &options); AVDictionaryEntry *t = NULL; while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) msg_Err( access, "unknown option \"%s\"", t->key ); av_dict_free(&options); #endif if (ret < 0) { msg_Err(access, "Failed to open %s: %s", url, vlc_strerror_c(AVUNERROR(ret))); free(url); goto error; } free(url); #if LIBAVFORMAT_VERSION_MAJOR < 54 /* We can accept only one active user at any time */ if (SetupAvioCb(VLC_OBJECT(access))) { msg_Err(access, "Module aready in use"); avio_close(sys->context); goto error; } #endif int64_t size = avio_size(sys->context); bool seekable; #if LIBAVFORMAT_VERSION_MAJOR < 54 seekable = !sys->context->is_streamed; #else seekable = sys->context->seekable; #endif msg_Dbg(access, "%sseekable, size=%"PRIi64, seekable ? "" : "not ", size); sys->size = size > 0 ? size : 0; /* */ access_InitFields(access); access->pf_read = Read; access->pf_block = NULL; access->pf_control = Control; access->pf_seek = Seek; access->p_sys = sys; return VLC_SUCCESS; error: free(sys); return VLC_EGENERIC; }
/***************************************************************************** * Add: Add an input elementary stream *****************************************************************************/ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) { sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_id_t *id; id = calloc( 1, sizeof( sout_stream_id_t ) ); if( !id ) return NULL; if( p_fmt->i_cat == VIDEO_ES && p_fmt->i_codec == VLC_CODEC_MPGV ) { id->b_switcher_video = true; p_fmt->i_codec = VLC_CODEC_MPGV; msg_Dbg( p_stream, "creating video switcher for fcc=`%4.4s' cmd:%d", (char*)&p_fmt->i_codec, p_sys->i_cmd ); } else if ( p_fmt->i_cat == AUDIO_ES && p_fmt->i_codec == VLC_CODEC_MPGA && p_sys->b_audio ) { int i_ff_codec = AV_CODEC_ID_MP2; int i; id->b_switcher_audio = true; msg_Dbg( p_stream, "creating audio switcher for fcc=`%4.4s' cmd:%d", (char*)&p_fmt->i_codec, p_sys->i_cmd ); /* Allocate the encoder right now. */ if( i_ff_codec == 0 ) { msg_Err( p_stream, "cannot find encoder" ); free( id ); return NULL; } id->ff_enc = avcodec_find_encoder( i_ff_codec ); if( !id->ff_enc ) { msg_Err( p_stream, "cannot find encoder (avcodec)" ); free( id ); return NULL; } id->ff_enc_c = avcodec_alloc_context3( id->ff_enc ); id->ff_enc_c->dsp_mask = GetVlcDspMask(); id->ff_enc_c->sample_rate = p_fmt->audio.i_rate; id->ff_enc_c->time_base.num = 1; id->ff_enc_c->time_base.den = p_fmt->audio.i_rate; id->ff_enc_c->channels = p_fmt->audio.i_channels; id->ff_enc_c->bit_rate = p_fmt->i_bitrate; int ret; #if LIBAVCODEC_VERSION_MAJOR >= 54 AVDictionary *options = NULL; if (p_sys->options) av_dict_copy(&options, p_sys->options, 0); vlc_avcodec_lock(); ret = avcodec_open2( id->ff_enc_c, id->ff_enc, options ? &options : NULL ); vlc_avcodec_unlock(); AVDictionaryEntry *t = NULL; while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) { msg_Err( p_stream, "Unknown option \"%s\"", t->key ); } av_dict_free(&options); #else vlc_avcodec_lock(); ret = avcodec_open( id->ff_enc_c, id->ff_enc ); vlc_avcodec_unlock(); #endif if (ret) { msg_Err( p_stream, "cannot open encoder" ); av_free( id->ff_enc_c ); free( id ); return NULL; } id->p_buffer_out = malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE * 2 ); id->p_samples = calloc( id->ff_enc_c->frame_size * p_fmt->audio.i_channels, sizeof(int16_t) ); if( !id->p_buffer_out || !id->p_samples ) goto error; for( i = 0; i < MAX_AUDIO; i++ ) { if( p_sys->pp_audio_ids[i] == NULL ) { p_sys->pp_audio_ids[i] = id; break; } } if( i == MAX_AUDIO ) { msg_Err( p_stream, "too many audio streams!" ); goto error; } } else { msg_Dbg( p_stream, "do not know what to do when switching (fcc=`%4.4s')", (char*)&p_fmt->i_codec ); } /* src format */ memcpy( &id->f_src, p_fmt, sizeof( es_format_t ) ); /* open output stream */ id->id = p_stream->p_next->pf_add( p_stream->p_next, p_fmt ); if( id->id != NULL ) return id; error: vlc_avcodec_lock(); avcodec_close( id->ff_enc_c ); vlc_avcodec_unlock(); free( id->p_samples ); free( id->p_buffer_out ); av_free( id->ff_enc_c ); free( id ); return NULL; }
static int mpc_read_header(AVFormatContext *s) { MPCContext *c = s->priv_data; AVStream *st; if(avio_rl24(s->pb) != MKTAG('M', 'P', '+', 0)){ av_log(s, AV_LOG_ERROR, "Not a Musepack file\n"); return AVERROR_INVALIDDATA; } c->ver = avio_r8(s->pb); if(c->ver != 0x07 && c->ver != 0x17){ av_log(s, AV_LOG_ERROR, "Can demux Musepack SV7, got version %02X\n", c->ver); return AVERROR_INVALIDDATA; } c->fcount = avio_rl32(s->pb); if((int64_t)c->fcount * sizeof(MPCFrame) >= UINT_MAX){ av_log(s, AV_LOG_ERROR, "Too many frames, seeking is not possible\n"); return AVERROR_INVALIDDATA; } if(c->fcount){ c->frames = av_malloc(c->fcount * sizeof(MPCFrame)); if(!c->frames){ av_log(s, AV_LOG_ERROR, "Cannot allocate seektable\n"); return AVERROR(ENOMEM); } }else{ av_log(s, AV_LOG_WARNING, "Container reports no frames\n"); } c->curframe = 0; c->lastframe = -1; c->curbits = 8; c->frames_noted = 0; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = AV_CODEC_ID_MUSEPACK7; st->codec->channels = 2; st->codec->bits_per_coded_sample = 16; st->codec->extradata_size = 16; st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE); avio_read(s->pb, st->codec->extradata, 16); st->codec->sample_rate = mpc_rate[st->codec->extradata[2] & 3]; avpriv_set_pts_info(st, 32, MPC_FRAMESIZE, st->codec->sample_rate); /* scan for seekpoints */ st->start_time = 0; st->duration = c->fcount; /* try to read APE tags */ if (s->pb->seekable) { int64_t pos = avio_tell(s->pb); ff_ape_parse_tag(s); if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); avio_seek(s->pb, pos, SEEK_SET); } return 0; }
void Libav::initMeta(AVFormatContext *fmt_ctx) { AVDictionaryEntry *tag = NULL; char *container = NULL; while ((tag = av_dict_get(fmt_ctx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { meta[std::string(tag->key)] = std::string(tag->value); if (strcmp(tag->key,"major_brand")==0) { // mp4 or mov if (strcmp(tag->value,"qt")==0) { container = "mov"; } if (strcmp(tag->value,"mp42")==0) { container = "mp4"; } } } if (container == NULL) { meta[std::string("FORMAT_NAME")] = std::string(fmt_ctx->iformat->name); } else { meta[std::string("FORMAT_NAME")] = std::string(container); } std::stringstream numberStreams; numberStreams << fmt_ctx->nb_streams; meta[std::string("STREAMS")] = numberStreams.str(); for(int i=0; i<fmt_ctx->nb_streams; i++) { AVCodecContext *codec_ctx = fmt_ctx->streams[i]->codec; const char * stream_type = av_get_media_type_string(fmt_ctx->streams[i]->codec->codec_type); char key[128]; // possible overflow char val[128]; // as above sprintf (key,"STREAM_%d_TYPE",i); meta [std::string(key)]= std::string(stream_type); sprintf (key,"STREAM_%s_CODEC_ID",stream_type); meta[std::string(key)]=std::string(av_get_codecid(codec_ctx->codec_id)); if (fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { sprintf(key,"STREAM_%s_AFPS_RATIO",stream_type); sprintf(val,"%d:%d",fmt_ctx->streams[i]->avg_frame_rate.num,fmt_ctx->streams[i]->avg_frame_rate.den); meta[std::string(key)]=std::string(val); sprintf(key,"STREAM_%s_FPS_RATIO",stream_type); sprintf(val,"%d:%d",fmt_ctx->streams[i]->r_frame_rate.num,fmt_ctx->streams[i]->r_frame_rate.den); meta[std::string(key)]=std::string(val); sprintf(key,"STREAM_%s_FPS",stream_type); sprintf(val,"%f",1.0*fmt_ctx->streams[i]->r_frame_rate.num / fmt_ctx->streams[i]->r_frame_rate.den); meta[std::string(key)]=std::string(val); sprintf (key,"STREAM_%s_WIDTH",stream_type); sprintf (val,"%d",codec_ctx->width); meta[std::string(key)]=std::string(val); sprintf (key,"STREAM_%s_HEIGHT",stream_type); sprintf (val,"%d",codec_ctx->height); meta[std::string(key)]=std::string(val); sprintf (key,"STREAM_%s_PIX_FMT",stream_type); // std::cerr << codec_ctx->pix_fmt << "\n"; const char * pixFmtName = av_get_pix_fmt_name(codec_ctx->pix_fmt); // std::cerr << av_get_pix_fmt_name(codec_ctx->pix_fmt) << "\n"; if (pixFmtName) meta[std::string(key)]=std::string(pixFmtName); sprintf(key,"STREAM_%s_SAR",stream_type); sprintf(val,"%d:%d",codec_ctx->sample_aspect_ratio.num,codec_ctx->sample_aspect_ratio.den); meta[std::string(key)]=std::string(val); sprintf (key,"STREAM_%s_REFFRAMES",stream_type); sprintf (val,"%d",codec_ctx->refs); meta[std::string(key)]=std::string(val); sprintf (key,"STREAM_%s_COLORSPACE",stream_type); meta[std::string(key)] = std::string(av_get_colorspace(codec_ctx->colorspace)); sprintf (key,"STREAM_%s_COLORRANGE",stream_type); meta[std::string(key)] = std::string(av_get_colorrange(codec_ctx->color_range)); sprintf (key,"STREAM_%s_FIELDORDER",stream_type); meta[std::string(key)] = std::string(av_get_field_order(codec_ctx->field_order)); } if (fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { sprintf (key,"STREAM_%s_SAMPLERATE",stream_type); sprintf(val,"%d",codec_ctx->sample_rate); meta[std::string(key)]=std::string(val); sprintf (key,"STREAM_%s_CHANNELS",stream_type); sprintf(val,"%d",codec_ctx->channels); meta[std::string(key)]=std::string(val); sprintf (key,"STREAM_%s_SAMPLEFORMAT",stream_type); const char * smpFmtName = av_get_sample_fmt_name(codec_ctx->sample_fmt); if (smpFmtName) meta[std::string(key)]=std::string(smpFmtName); } while ((tag = av_dict_get(fmt_ctx->streams[i]->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { sprintf(key,"STREAM_%s_%s", stream_type,tag->key); meta[std::string(key)]=std::string(tag->value); } } }
/* write the header (used two times if non streamed) */ static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size) { ASFContext *asf = (ASFContext *)s->priv_data; AVIOContext *pb = s->pb; AVDictionaryEntry *tags[5]; int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; int has_title; int metadata_count; AVCodecContext *enc; int64_t header_offset, cur_pos, hpos; int bit_rate; int64_t duration; ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL); tags[0] = av_dict_get(s->metadata, "title" , NULL, 0); tags[1] = av_dict_get(s->metadata, "author" , NULL, 0); tags[2] = av_dict_get(s->metadata, "copyright", NULL, 0); tags[3] = av_dict_get(s->metadata, "comment" , NULL, 0); tags[4] = av_dict_get(s->metadata, "rating" , NULL, 0); duration = asf->duration + PREROLL_TIME * 10000; has_title = tags[0] || tags[1] || tags[2] || tags[3] || tags[4]; metadata_count = s->metadata ? s->metadata->count : 0; bit_rate = 0; for(n=0;n<s->nb_streams;n++) { enc = s->streams[n]->codec; avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ bit_rate += enc->bit_rate; } if (asf->is_streamed) { put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */ } ff_put_guid(pb, &ff_asf_header); avio_wl64(pb, -1); /* header length, will be patched after */ avio_wl32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */ avio_w8(pb, 1); /* ??? */ avio_w8(pb, 2); /* ??? */ /* file header */ header_offset = avio_tell(pb); hpos = put_header(pb, &ff_asf_file_header); ff_put_guid(pb, &ff_asf_my_guid); avio_wl64(pb, file_size); file_time = 0; avio_wl64(pb, unix_to_file_time(file_time)); avio_wl64(pb, asf->nb_packets); /* number of packets */ avio_wl64(pb, duration); /* end time stamp (in 100ns units) */ avio_wl64(pb, asf->duration); /* duration (in 100ns units) */ avio_wl64(pb, PREROLL_TIME); /* start time stamp */ avio_wl32(pb, (asf->is_streamed || !pb->seekable ) ? 3 : 2); /* ??? */ avio_wl32(pb, s->packet_size); /* packet size */ avio_wl32(pb, s->packet_size); /* packet size */ avio_wl32(pb, bit_rate); /* Nominal data rate in bps */ end_header(pb, hpos); /* unknown headers */ hpos = put_header(pb, &ff_asf_head1_guid); ff_put_guid(pb, &ff_asf_head2_guid); avio_wl32(pb, 6); avio_wl16(pb, 0); end_header(pb, hpos); /* title and other infos */ if (has_title) { int len; uint8_t *buf; AVIOContext *dyn_buf; if (avio_open_dyn_buf(&dyn_buf) < 0) return AVERROR(ENOMEM); hpos = put_header(pb, &ff_asf_comment_header); for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) { len = tags[n] ? avio_put_str16le(dyn_buf, tags[n]->value) : 0; avio_wl16(pb, len); } len = avio_close_dyn_buf(dyn_buf, &buf); avio_write(pb, buf, len); av_freep(&buf); end_header(pb, hpos); } if (metadata_count) { AVDictionaryEntry *tag = NULL; hpos = put_header(pb, &ff_asf_extended_content_header); avio_wl16(pb, metadata_count); while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { put_str16(pb, tag->key); avio_wl16(pb, 0); put_str16(pb, tag->value); } end_header(pb, hpos); } /* stream headers */ for(n=0;n<s->nb_streams;n++) { int64_t es_pos; // ASFStream *stream = &asf->streams[n]; enc = s->streams[n]->codec; asf->streams[n].num = n + 1; asf->streams[n].seq = 0; switch(enc->codec_type) { case AVMEDIA_TYPE_AUDIO: wav_extra_size = 0; extra_size = 18 + wav_extra_size; extra_size2 = 8; break; default: case AVMEDIA_TYPE_VIDEO: wav_extra_size = enc->extradata_size; extra_size = 0x33 + wav_extra_size; extra_size2 = 0; break; } hpos = put_header(pb, &ff_asf_stream_header); if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { ff_put_guid(pb, &ff_asf_audio_stream); ff_put_guid(pb, &ff_asf_audio_conceal_spread); } else { ff_put_guid(pb, &ff_asf_video_stream); ff_put_guid(pb, &ff_asf_video_conceal_none); } avio_wl64(pb, 0); /* ??? */ es_pos = avio_tell(pb); avio_wl32(pb, extra_size); /* wav header len */ avio_wl32(pb, extra_size2); /* additional data len */ avio_wl16(pb, n + 1); /* stream number */ avio_wl32(pb, 0); /* ??? */ if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { /* WAVEFORMATEX header */ int wavsize = ff_put_wav_header(pb, enc); if (wavsize < 0) return -1; if (wavsize != extra_size) { cur_pos = avio_tell(pb); avio_seek(pb, es_pos, SEEK_SET); avio_wl32(pb, wavsize); /* wav header len */ avio_seek(pb, cur_pos, SEEK_SET); } /* ERROR Correction */ avio_w8(pb, 0x01); if(enc->codec_id == CODEC_ID_ADPCM_G726 || !enc->block_align){ avio_wl16(pb, 0x0190); avio_wl16(pb, 0x0190); }else{ avio_wl16(pb, enc->block_align); avio_wl16(pb, enc->block_align); } avio_wl16(pb, 0x01); avio_w8(pb, 0x00); } else { avio_wl32(pb, enc->width); avio_wl32(pb, enc->height); avio_w8(pb, 2); /* ??? */ avio_wl16(pb, 40 + enc->extradata_size); /* size */ /* BITMAPINFOHEADER header */ ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1); } end_header(pb, hpos); } /* media comments */ hpos = put_header(pb, &ff_asf_codec_comment_header); ff_put_guid(pb, &ff_asf_codec_comment1_header); avio_wl32(pb, s->nb_streams); for(n=0;n<s->nb_streams;n++) { AVCodec *p; const char *desc; int len; uint8_t *buf; AVIOContext *dyn_buf; enc = s->streams[n]->codec; p = avcodec_find_encoder(enc->codec_id); if(enc->codec_type == AVMEDIA_TYPE_AUDIO) avio_wl16(pb, 2); else if(enc->codec_type == AVMEDIA_TYPE_VIDEO) avio_wl16(pb, 1); else avio_wl16(pb, -1); if(enc->codec_id == CODEC_ID_WMAV2) desc = "Windows Media Audio V8"; else desc = p ? p->name : enc->codec_name; if ( avio_open_dyn_buf(&dyn_buf) < 0) return AVERROR(ENOMEM); avio_put_str16le(dyn_buf, desc); len = avio_close_dyn_buf(dyn_buf, &buf); avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2 avio_write(pb, buf, len); av_freep(&buf); avio_wl16(pb, 0); /* no parameters */ /* id */ if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { avio_wl16(pb, 2); avio_wl16(pb, enc->codec_tag); } else { avio_wl16(pb, 4); avio_wl32(pb, enc->codec_tag); } if(!enc->codec_tag) return -1; } end_header(pb, hpos); /* patch the header size fields */ cur_pos = avio_tell(pb); header_size = cur_pos - header_offset; if (asf->is_streamed) { header_size += 8 + 30 + 50; avio_seek(pb, header_offset - 10 - 30, SEEK_SET); avio_wl16(pb, header_size); avio_seek(pb, header_offset - 2 - 30, SEEK_SET); avio_wl16(pb, header_size); header_size -= 8 + 30 + 50; } header_size += 24 + 6; avio_seek(pb, header_offset - 14, SEEK_SET); avio_wl64(pb, header_size); avio_seek(pb, cur_pos, SEEK_SET); /* movie chunk, followed by packets of packet_size */ asf->data_offset = cur_pos; ff_put_guid(pb, &ff_asf_data_header); avio_wl64(pb, data_chunk_size); ff_put_guid(pb, &ff_asf_my_guid); avio_wl64(pb, asf->nb_packets); /* nb packets */ avio_w8(pb, 1); /* ??? */ avio_w8(pb, 1); /* ??? */ return 0; }
static int flv_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; FLVContext *flv = s->priv_data; AVCodecContext *audio_enc = NULL, *video_enc = NULL; int i, metadata_count = 0; double framerate = 0.0; int64_t metadata_size_pos, data_size, metadata_count_pos; AVDictionaryEntry *tag = NULL; for(i=0; i<s->nb_streams; i++){ AVCodecContext *enc = s->streams[i]->codec; FLVStreamContext *sc; if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) { framerate = av_q2d(s->streams[i]->r_frame_rate); } else { framerate = 1/av_q2d(s->streams[i]->codec->time_base); } video_enc = enc; if(enc->codec_tag == 0) { av_log(enc, AV_LOG_ERROR, "video codec not compatible with flv\n"); return -1; } } else if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { audio_enc = enc; if(get_audio_flags(enc)<0) return -1; } avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ sc = av_mallocz(sizeof(FLVStreamContext)); if (!sc) return AVERROR(ENOMEM); s->streams[i]->priv_data = sc; sc->last_ts = -1; } flv->delay = AV_NOPTS_VALUE; avio_write(pb, "FLV", 3); avio_w8(pb,1); avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!audio_enc + FLV_HEADER_FLAG_HASVIDEO * !!video_enc); avio_wb32(pb,9); avio_wb32(pb,0); for(i=0; i<s->nb_streams; i++){ if(s->streams[i]->codec->codec_tag == 5){ avio_w8(pb,8); // message type avio_wb24(pb,0); // include flags avio_wb24(pb,0); // time stamp avio_wb32(pb,0); // reserved avio_wb32(pb,11); // size flv->reserved=5; } } /* write meta_tag */ avio_w8(pb, 18); // tag type META metadata_size_pos= avio_tell(pb); avio_wb24(pb, 0); // size of data part (sum of all parts below) avio_wb24(pb, 0); // time stamp avio_wb32(pb, 0); // reserved /* now data of data_size size */ /* first event name as a string */ avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, "onMetaData"); // 12 bytes /* mixed array (hash) with size and string/type/data tuples */ avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); metadata_count_pos = avio_tell(pb); metadata_count = 5*!!video_enc + 5*!!audio_enc + 2; // +2 for duration and file size avio_wb32(pb, metadata_count); put_amf_string(pb, "duration"); flv->duration_offset= avio_tell(pb); put_amf_double(pb, s->duration / AV_TIME_BASE); // fill in the guessed duration, it'll be corrected later if incorrect if(video_enc){ put_amf_string(pb, "width"); put_amf_double(pb, video_enc->width); put_amf_string(pb, "height"); put_amf_double(pb, video_enc->height); put_amf_string(pb, "videodatarate"); put_amf_double(pb, video_enc->bit_rate / 1024.0); put_amf_string(pb, "framerate"); put_amf_double(pb, framerate); put_amf_string(pb, "videocodecid"); put_amf_double(pb, video_enc->codec_tag); } if(audio_enc){ put_amf_string(pb, "audiodatarate"); put_amf_double(pb, audio_enc->bit_rate / 1024.0); put_amf_string(pb, "audiosamplerate"); put_amf_double(pb, audio_enc->sample_rate); put_amf_string(pb, "audiosamplesize"); put_amf_double(pb, audio_enc->codec_id == CODEC_ID_PCM_U8 ? 8 : 16); put_amf_string(pb, "stereo"); put_amf_bool(pb, audio_enc->channels == 2); put_amf_string(pb, "audiocodecid"); put_amf_double(pb, audio_enc->codec_tag); } while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { if( !strcmp(tag->key, "width") ||!strcmp(tag->key, "height") ||!strcmp(tag->key, "videodatarate") ||!strcmp(tag->key, "framerate") ||!strcmp(tag->key, "videocodecid") ||!strcmp(tag->key, "audiodatarate") ||!strcmp(tag->key, "audiosamplerate") ||!strcmp(tag->key, "audiosamplesize") ||!strcmp(tag->key, "stereo") ||!strcmp(tag->key, "audiocodecid") ||!strcmp(tag->key, "duration") ||!strcmp(tag->key, "onMetaData") ){ av_log(s, AV_LOG_DEBUG, "ignoring metadata for %s\n", tag->key); continue; } put_amf_string(pb, tag->key); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, tag->value); metadata_count++; } put_amf_string(pb, "filesize"); flv->filesize_offset= avio_tell(pb); put_amf_double(pb, 0); // delayed write put_amf_string(pb, ""); avio_w8(pb, AMF_END_OF_OBJECT); /* write total size of tag */ data_size= avio_tell(pb) - metadata_size_pos - 10; avio_seek(pb, metadata_count_pos, SEEK_SET); avio_wb32(pb, metadata_count); avio_seek(pb, metadata_size_pos, SEEK_SET); avio_wb24(pb, data_size); avio_skip(pb, data_size + 10 - 3); avio_wb32(pb, data_size + 11); for (i = 0; i < s->nb_streams; i++) { AVCodecContext *enc = s->streams[i]->codec; if (enc->codec_id == CODEC_ID_AAC || enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4) { int64_t pos; avio_w8(pb, enc->codec_type == AVMEDIA_TYPE_VIDEO ? FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO); avio_wb24(pb, 0); // size patched later avio_wb24(pb, 0); // ts avio_w8(pb, 0); // ts ext avio_wb24(pb, 0); // streamid pos = avio_tell(pb); if (enc->codec_id == CODEC_ID_AAC) { avio_w8(pb, get_audio_flags(enc)); avio_w8(pb, 0); // AAC sequence header avio_write(pb, enc->extradata, enc->extradata_size); } else { avio_w8(pb, enc->codec_tag | FLV_FRAME_KEY); // flags avio_w8(pb, 0); // AVC sequence header avio_wb24(pb, 0); // composition time ff_isom_write_avcc(pb, enc->extradata, enc->extradata_size); } data_size = avio_tell(pb) - pos; avio_seek(pb, -data_size - 10, SEEK_CUR); avio_wb24(pb, data_size); avio_skip(pb, data_size + 10 - 3); avio_wb32(pb, data_size + 11); // previous tag size } } return 0; }
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags) { AVDictionary *m = *pm; AVDictionaryEntry *tag = av_dict_get(m, key, NULL, flags); char *oldval = NULL; if (!m) m = *pm = av_mallocz(sizeof(*m)); if (!m) goto err_out; if (tag) { if (flags & AV_DICT_DONT_OVERWRITE) { if (flags & AV_DICT_DONT_STRDUP_KEY) av_free((void*)key); if (flags & AV_DICT_DONT_STRDUP_VAL) av_free((void*)value); return 0; } if (flags & AV_DICT_APPEND) oldval = tag->value; else av_free(tag->value); av_free(tag->key); *tag = m->elems[--m->count]; } else { AVDictionaryEntry *tmp = av_realloc(m->elems, (m->count + 1) * sizeof(*m->elems)); if (!tmp) goto err_out; m->elems = tmp; } if (value) { if (flags & AV_DICT_DONT_STRDUP_KEY) m->elems[m->count].key = (char*)(intptr_t)key; else m->elems[m->count].key = av_strdup(key); if (!m->elems[m->count].key) goto err_out; if (flags & AV_DICT_DONT_STRDUP_VAL) { m->elems[m->count].value = (char*)(intptr_t)value; } else if (oldval && flags & AV_DICT_APPEND) { int len = strlen(oldval) + strlen(value) + 1; char *newval = av_mallocz(len); if (!newval) goto err_out; av_strlcat(newval, oldval, len); av_freep(&oldval); av_strlcat(newval, value, len); m->elems[m->count].value = newval; } else m->elems[m->count].value = av_strdup(value); m->count++; } if (!m->count) { av_freep(&m->elems); av_freep(pm); } return 0; err_out: if (m && !m->count) { av_freep(&m->elems); av_freep(pm); } if (flags & AV_DICT_DONT_STRDUP_KEY) av_free((void*)key); if (flags & AV_DICT_DONT_STRDUP_VAL) av_free((void*)value); return AVERROR(ENOMEM); }
std::string lavf_get_stream_description(const AVStream *pStream) { AVCodecParameters *par = pStream->codecpar; std::string codec_name = get_codec_name(par); const char *lang = get_stream_language(pStream); std::string sLanguage; if(lang) { sLanguage = ProbeLangForLanguage(lang); if (sLanguage.empty()) { sLanguage = lang; } } const char * title = lavf_get_stream_title(pStream); // Empty titles are rather useless if (title && strlen(title) == 0) title = nullptr; int64_t bitrate = get_bit_rate(par); std::ostringstream buf; switch(par->codec_type) { case AVMEDIA_TYPE_VIDEO: buf << "V: "; // Title/Language if (title && lang) { buf << title << " [" << lang << "] ("; } else if (title) { // Print either title or lang buf << title << " ("; } else if (lang) { buf << sLanguage << " [" << lang << "] ("; } // Codec buf << codec_name; // Pixel Format if (const char *pix_fmt = av_get_pix_fmt_name((AVPixelFormat)par->format)) { buf << ", " << pix_fmt; } // Dimensions if (par->width) { buf << ", " << par->width << "x" << par->height; } // Bitrate if (bitrate > 0) { buf << ", " << (bitrate / 1000) << " kb/s"; } if (par->codec_id == AV_CODEC_ID_H264 && par->profile == FF_PROFILE_H264_STEREO_HIGH) { AVDictionaryEntry *entry = av_dict_get(pStream->metadata, "stereo_mode", nullptr, 0); if (entry && strcmp(entry->value, "mvc_lr") == 0) buf << ", lr"; else if (entry && strcmp(entry->value, "mvc_rl") == 0) buf << ", rl"; } // Closing tag if (title || lang) { buf << ")"; } buf << format_flags(pStream->disposition); break; case AVMEDIA_TYPE_AUDIO: buf << "A: "; // Title/Language if (title && lang) { buf << title << " [" << lang << "] ("; } else if (title) { // Print either title or lang buf << title << " ("; } else if (lang) { buf << sLanguage << " [" << lang << "] ("; } // Codec buf << codec_name; // Sample Rate if (par->sample_rate) { buf << ", " << par->sample_rate << " Hz"; } if (par->channels) { // Get channel layout char channel[32]; av_get_channel_layout_string(channel, 32, par->channels, par->channel_layout); buf << ", " << channel; } // Sample Format if (show_sample_fmt(par) && get_bits_per_sample(par, true)) { if (par->format == AV_SAMPLE_FMT_FLT || par->format == AV_SAMPLE_FMT_DBL) { buf << ", fp"; } else { buf << ", s"; } buf << get_bits_per_sample(par, true); } // Bitrate if (bitrate > 0) { buf << ", " << (bitrate / 1000) << " kb/s"; } // Closing tag if (title || lang) { buf << ")"; } // Flags buf << format_flags(pStream->disposition); break; case AVMEDIA_TYPE_SUBTITLE: buf << "S: "; // Title/Language if (title && lang) { buf << title << " [" << lang << "] ("; } else if (title) { // Print either title or lang buf << title << " ("; } else if (lang) { buf << sLanguage << " [" << lang << "] ("; } // Codec buf << codec_name; if (title || lang) { buf << ")"; } // Subtitle flags buf << format_flags(pStream->disposition); break; default: buf << "Unknown: Stream #" << pStream->index; break; } return buf.str(); }
int ff_ape_write_tag(AVFormatContext *s) { AVDictionaryEntry *e = NULL; int size, ret, count = 0; AVIOContext *dyn_bc = NULL; uint8_t *dyn_buf = NULL; if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) goto end; // flags avio_wl32(dyn_bc, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER | APE_TAG_FLAG_IS_HEADER); ffio_fill(dyn_bc, 0, 8); // reserved while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) { int val_len; if (!string_is_ascii(e->key)) { av_log(s, AV_LOG_WARNING, "Non ASCII keys are not allowed\n"); continue; } val_len = strlen(e->value); avio_wl32(dyn_bc, val_len); // value length avio_wl32(dyn_bc, 0); // item flags avio_put_str(dyn_bc, e->key); // key avio_write(dyn_bc, e->value, val_len); // value count++; } if (!count) goto end; size = avio_close_dyn_buf(dyn_bc, &dyn_buf); if (size <= 0) goto end; size += 20; // header avio_write(s->pb, "APETAGEX", 8); // id avio_wl32(s->pb, APE_TAG_VERSION); // version avio_wl32(s->pb, size); avio_wl32(s->pb, count); avio_write(s->pb, dyn_buf, size - 20); // footer avio_write(s->pb, "APETAGEX", 8); // id avio_wl32(s->pb, APE_TAG_VERSION); // version avio_wl32(s->pb, size); // size avio_wl32(s->pb, count); // tag count // flags avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER); ffio_fill(s->pb, 0, 8); // reserved end: if (dyn_bc && !dyn_buf) avio_close_dyn_buf(dyn_bc, &dyn_buf); av_freep(&dyn_buf); return ret; }
int avfilter_init_str(AVFilterContext *filter, const char *args) { AVDictionary *options = NULL; AVDictionaryEntry *e; int ret = 0; if (args && *args) { if (!filter->filter->priv_class) { av_log(filter, AV_LOG_ERROR, "This filter does not take any " "options, but options were provided: %s.\n", args); return AVERROR(EINVAL); } #if FF_API_OLD_FILTER_OPTS if ( !strcmp(filter->filter->name, "format") || !strcmp(filter->filter->name, "noformat") || !strcmp(filter->filter->name, "frei0r") || !strcmp(filter->filter->name, "frei0r_src") || !strcmp(filter->filter->name, "ocv") || !strcmp(filter->filter->name, "pan") || !strcmp(filter->filter->name, "pp") || !strcmp(filter->filter->name, "aevalsrc")) { /* a hack for compatibility with the old syntax * replace colons with |s */ char *copy = av_strdup(args); char *p = copy; int nb_leading = 0; // number of leading colons to skip int deprecated = 0; if (!copy) { ret = AVERROR(ENOMEM); goto fail; } if (!strcmp(filter->filter->name, "frei0r") || !strcmp(filter->filter->name, "ocv")) nb_leading = 1; else if (!strcmp(filter->filter->name, "frei0r_src")) nb_leading = 3; while (nb_leading--) { p = strchr(p, ':'); if (!p) { p = copy + strlen(copy); break; } p++; } deprecated = strchr(p, ':') != NULL; if (!strcmp(filter->filter->name, "aevalsrc")) { deprecated = 0; while ((p = strchr(p, ':')) && p[1] != ':') { const char *epos = strchr(p + 1, '='); const char *spos = strchr(p + 1, ':'); const int next_token_is_opt = epos && (!spos || epos < spos); if (next_token_is_opt) { p++; break; } /* next token does not contain a '=', assume a channel expression */ deprecated = 1; *p++ = '|'; } if (p && *p == ':') { // double sep '::' found deprecated = 1; memmove(p, p + 1, strlen(p)); } } else while ((p = strchr(p, ':'))) *p++ = '|'; if (deprecated) av_log(filter, AV_LOG_WARNING, "This syntax is deprecated. Use " "'|' to separate the list items.\n"); av_log(filter, AV_LOG_DEBUG, "compat: called with args=[%s]\n", copy); ret = process_options(filter, &options, copy); av_freep(©); if (ret < 0) goto fail; #endif } else { #if CONFIG_MP_FILTER if (!strcmp(filter->filter->name, "mp")) { char *escaped; if (!strncmp(args, "filter=", 7)) args += 7; ret = av_escape(&escaped, args, ":=", AV_ESCAPE_MODE_BACKSLASH, 0); if (ret < 0) { av_log(filter, AV_LOG_ERROR, "Unable to escape MPlayer filters arg '%s'\n", args); goto fail; } ret = process_options(filter, &options, escaped); av_free(escaped); } else #endif ret = process_options(filter, &options, args); if (ret < 0) goto fail; } } ret = avfilter_init_dict(filter, &options); if (ret < 0) goto fail; if ((e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX))) { av_log(filter, AV_LOG_ERROR, "No such option: %s.\n", e->key); ret = AVERROR_OPTION_NOT_FOUND; goto fail; } fail: av_dict_free(&options); return ret; }
static int sap_write_header(AVFormatContext *s) { struct SAPState *sap = s->priv_data; char host[1024], path[1024], url[1024], announce_addr[50] = ""; char *option_list; int port = 9875, base_port = 5004, i, pos = 0, same_port = 0, ttl = 255; AVFormatContext **contexts = NULL; int ret = 0; struct sockaddr_storage localaddr; socklen_t addrlen = sizeof(localaddr); int udp_fd; AVDictionaryEntry* title = av_dict_get(s->metadata, "title", NULL, 0); if (!ff_network_init()) return AVERROR(EIO); /* extract hostname and port */ av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &base_port, path, sizeof(path), s->filename); if (base_port < 0) base_port = 5004; /* search for options */ option_list = strrchr(path, '?'); if (option_list) { char buf[50]; if (av_find_info_tag(buf, sizeof(buf), "announce_port", option_list)) { port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "same_port", option_list)) { same_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "ttl", option_list)) { ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "announce_addr", option_list)) { av_strlcpy(announce_addr, buf, sizeof(announce_addr)); } } if (!announce_addr[0]) { struct addrinfo hints = { 0 }, *ai = NULL; hints.ai_family = AF_UNSPEC; if (getaddrinfo(host, NULL, &hints, &ai)) { av_log(s, AV_LOG_ERROR, "Unable to resolve %s\n", host); ret = AVERROR(EIO); goto fail; } if (ai->ai_family == AF_INET) { /* Also known as sap.mcast.net */ av_strlcpy(announce_addr, "224.2.127.254", sizeof(announce_addr)); #if HAVE_STRUCT_SOCKADDR_IN6 } else if (ai->ai_family == AF_INET6) { /* With IPv6, you can use the same destination in many different * multicast subnets, to choose how far you want it routed. * This one is intended to be routed globally. */ av_strlcpy(announce_addr, "ff0e::2:7ffe", sizeof(announce_addr)); #endif } else { freeaddrinfo(ai); av_log(s, AV_LOG_ERROR, "Host %s resolved to unsupported " "address family\n", host); ret = AVERROR(EIO); goto fail; } freeaddrinfo(ai); } contexts = av_mallocz(sizeof(AVFormatContext*) * s->nb_streams); if (!contexts) { ret = AVERROR(ENOMEM); goto fail; } if (s->start_time_realtime == 0 || s->start_time_realtime == AV_NOPTS_VALUE) s->start_time_realtime = av_gettime(); for (i = 0; i < s->nb_streams; i++) { URLContext *fd; ff_url_join(url, sizeof(url), "rtp", NULL, host, base_port, "?ttl=%d", ttl); if (!same_port) base_port += 2; ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); if (ret) { ret = AVERROR(EIO); goto fail; } ret = ff_rtp_chain_mux_open(&contexts[i], s, s->streams[i], fd, 0, i); if (ret < 0) goto fail; s->streams[i]->priv_data = contexts[i]; av_strlcpy(contexts[i]->filename, url, sizeof(contexts[i]->filename)); } if (s->nb_streams > 0 && title) av_dict_set(&contexts[0]->metadata, "title", title->value, 0); ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port, "?ttl=%d&connect=1", ttl); ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); if (ret) { ret = AVERROR(EIO); goto fail; } udp_fd = ffurl_get_file_handle(sap->ann_fd); if (getsockname(udp_fd, (struct sockaddr*) &localaddr, &addrlen)) { ret = AVERROR(EIO); goto fail; } if (localaddr.ss_family != AF_INET #if HAVE_STRUCT_SOCKADDR_IN6 && localaddr.ss_family != AF_INET6 #endif ) { av_log(s, AV_LOG_ERROR, "Unsupported protocol family\n"); ret = AVERROR(EIO); goto fail; } sap->ann_size = 8192; sap->ann = av_mallocz(sap->ann_size); if (!sap->ann) { ret = AVERROR(EIO); goto fail; } sap->ann[pos] = (1 << 5); #if HAVE_STRUCT_SOCKADDR_IN6 if (localaddr.ss_family == AF_INET6) sap->ann[pos] |= 0x10; #endif pos++; sap->ann[pos++] = 0; /* Authentication length */ AV_WB16(&sap->ann[pos], av_get_random_seed()); pos += 2; if (localaddr.ss_family == AF_INET) { memcpy(&sap->ann[pos], &((struct sockaddr_in*)&localaddr)->sin_addr, sizeof(struct in_addr)); pos += sizeof(struct in_addr); #if HAVE_STRUCT_SOCKADDR_IN6 } else { memcpy(&sap->ann[pos], &((struct sockaddr_in6*)&localaddr)->sin6_addr, sizeof(struct in6_addr)); pos += sizeof(struct in6_addr); #endif } av_strlcpy(&sap->ann[pos], "application/sdp", sap->ann_size - pos); pos += strlen(&sap->ann[pos]) + 1; if (av_sdp_create(contexts, s->nb_streams, &sap->ann[pos], sap->ann_size - pos)) { ret = AVERROR_INVALIDDATA; goto fail; } av_freep(&contexts); av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", &sap->ann[pos]); pos += strlen(&sap->ann[pos]); sap->ann_size = pos; if (sap->ann_size > sap->ann_fd->max_packet_size) { av_log(s, AV_LOG_ERROR, "Announcement too large to send in one " "packet\n"); goto fail; } return 0; fail: av_free(contexts); sap_write_close(s); return ret; }