
Recherche avancée
Autres articles (71)
-
MediaSPIP 0.1 Beta version
25 avril 2011, parMediaSPIP 0.1 beta is the first version of MediaSPIP proclaimed as "usable".
The zip file provided here only contains the sources of MediaSPIP in its standalone version.
To get a working installation, you must manually install all-software dependencies on the server.
If you want to use this archive for an installation in "farm mode", you will also need to proceed to other manual (...) -
MediaSPIP version 0.1 Beta
16 avril 2011, parMediaSPIP 0.1 beta est la première version de MediaSPIP décrétée comme "utilisable".
Le fichier zip ici présent contient uniquement les sources de MediaSPIP en version standalone.
Pour avoir une installation fonctionnelle, il est nécessaire d’installer manuellement l’ensemble des dépendances logicielles sur le serveur.
Si vous souhaitez utiliser cette archive pour une installation en mode ferme, il vous faudra également procéder à d’autres modifications (...) -
Amélioration de la version de base
13 septembre 2013Jolie sélection multiple
Le plugin Chosen permet d’améliorer l’ergonomie des champs de sélection multiple. Voir les deux images suivantes pour comparer.
Il suffit pour cela d’activer le plugin Chosen (Configuration générale du site > Gestion des plugins), puis de configurer le plugin (Les squelettes > Chosen) en activant l’utilisation de Chosen dans le site public et en spécifiant les éléments de formulaires à améliorer, par exemple select[multiple] pour les listes à sélection multiple (...)
Sur d’autres sites (10567)
-
RTP packets detected as UDP
8 juillet 2024, par fritzHere is what I am trying to do :



WebRTC endpoint > RTP Endpoint > ffmpeg > RTMP server.




This is what my SDP file looks like.



var cm_offer = "v=0\n" +
 "o=- 3641290734 3641290734 IN IP4 127.0.0.1\n" +
 "s=nginx\n" +
 "c=IN IP4 127.0.0.1\n" +
 "t=0 0\n" +
 "m=audio 60820 RTP/AVP 0\n" +
 "a=rtpmap:0 PCMU/8000\n" +
 "a=recvonly\n" +
 "m=video 59618 RTP/AVP 101\n" +
 "a=rtpmap:101 H264/90000\n" +
 "a=recvonly\n";




What's happening is that wireshark can detect the incoming packets at port 59618, but not as RTP packets but UDP packets. I am trying to capture the packets using ffmpeg with the following command :



ubuntu@ip-132-31-40-100:~$ ffmpeg -i udp://127.0.0.1:59618 -vcodec copy stream.mp4
ffmpeg version git-2017-01-22-f1214ad Copyright (c) 2000-2017 the FFmpeg developers
 built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
 configuration: --extra-libs=-ldl --prefix=/opt/ffmpeg --mandir=/usr/share/man --enable-avresample --disable-debug --enable-nonfree --enable-gpl --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb --disable-decoder=amrnb --disable-decoder=amrwb --enable-libpulse --enable-libfreetype --enable-gnutls --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-libvorbis --enable-libmp3lame --enable-libopus --enable-libvpx --enable-libspeex --enable-libass --enable-avisynth --enable-libsoxr --enable-libxvid --enable-libvidstab --enable-libwavpack --enable-nvenc
 libavutil 55. 44.100 / 55. 44.100
 libavcodec 57. 75.100 / 57. 75.100
 libavformat 57. 63.100 / 57. 63.100
 libavdevice 57. 2.100 / 57. 2.100
 libavfilter 6. 69.100 / 6. 69.100
 libavresample 3. 2. 0 / 3. 2. 0
 libswscale 4. 3.101 / 4. 3.101
 libswresample 2. 4.100 / 2. 4.100
 libpostproc 54. 2.100 / 54. 2.100 




All I get is a blinking cursor and The stream.mp4 file is not written to disk after I exit (ctrl+c).



So can you help me figure out :



- 

- why wireshark cannot detect the packets as RTP (I suspect it has something to do with SDP)
- How to handle SDP answer when the RTP endpoint is pushing to ffmpeg which doesn't send an answer back.







Here is the entire code (hello world tutorial modified)



/*
 * (C) Copyright 2014-2015 Kurento (http://kurento.org/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 function getopts(args, opts)
 {
 var result = opts.default || {};
 args.replace(
 new RegExp("([^?=&]+)(=([^&]*))?", "g"),
 function($0, $1, $2, $3) { result[$1] = decodeURI($3); });

 return result;
 };

 var args = getopts(location.search,
 {
 default:
 {
 ws_uri: 'wss://' + location.hostname + ':8433/kurento',
 ice_servers: undefined
 }
 });

 function setIceCandidateCallbacks(webRtcPeer, webRtcEp, onerror)
 {
 webRtcPeer.on('icecandidate', function(candidate) {
 console.log("Local candidate:",candidate);

 candidate = kurentoClient.getComplexType('IceCandidate')(candidate);

 webRtcEp.addIceCandidate(candidate, onerror)
 });

 webRtcEp.on('OnIceCandidate', function(event) {
 var candidate = event.candidate;

 console.log("Remote candidate:",candidate);

 webRtcPeer.addIceCandidate(candidate, onerror);
 });
 }


 function setIceCandidateCallbacks2(webRtcPeer, rtpEp, onerror)
 {
 webRtcPeer.on('icecandidate', function(candidate) {
 console.log("Localr candidate:",candidate);

 candidate = kurentoClient.getComplexType('IceCandidate')(candidate);

 rtpEp.addIceCandidate(candidate, onerror)
 });
 }


 window.addEventListener('load', function()
 {
 console = new Console();

 var webRtcPeer;
 var pipeline;
 var webRtcEpt;

 var videoInput = document.getElementById('videoInput');
 var videoOutput = document.getElementById('videoOutput');

 var startButton = document.getElementById("start");
 var stopButton = document.getElementById("stop");

 startButton.addEventListener("click", function()
 {
 showSpinner(videoInput, videoOutput);

 var options = {
 localVideo: videoInput,
 remoteVideo: videoOutput
 };


 if (args.ice_servers) {
 console.log("Use ICE servers: " + args.ice_servers);
 options.configuration = {
 iceServers : JSON.parse(args.ice_servers)
 };
 } else {
 console.log("Use freeice")
 }

 webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function(error)
 {
 if(error) return onError(error)

 this.generateOffer(onOffer)
 });

 function onOffer(error, sdpOffer)
 {
 if(error) return onError(error)

 kurentoClient(args.ws_uri, function(error, client)
 {
 if(error) return onError(error);

 client.create("MediaPipeline", function(error, _pipeline)
 {
 if(error) return onError(error);

 pipeline = _pipeline;

 pipeline.create("WebRtcEndpoint", function(error, webRtc){
 if(error) return onError(error);

 webRtcEpt = webRtc;

 setIceCandidateCallbacks(webRtcPeer, webRtc, onError)

 webRtc.processOffer(sdpOffer, function(error, sdpAnswer){
 if(error) return onError(error);

 webRtcPeer.processAnswer(sdpAnswer, onError);
 });
 webRtc.gatherCandidates(onError);

 webRtc.connect(webRtc, function(error){
 if(error) return onError(error);

 console.log("Loopback established");
 });
 });



 pipeline.create("RtpEndpoint", function(error, rtp){
 if(error) return onError(error);

 //setIceCandidateCallbacks2(webRtcPeer, rtp, onError)


 var cm_offer = "v=0\n" +
 "o=- 3641290734 3641290734 IN IP4 127.0.0.1\n" +
 "s=nginx\n" +
 "c=IN IP4 127.0.0.1\n" +
 "t=0 0\n" +
 "m=audio 60820 RTP/AVP 0\n" +
 "a=rtpmap:0 PCMU/8000\n" +
 "a=recvonly\n" +
 "m=video 59618 RTP/AVP 101\n" +
 "a=rtpmap:101 H264/90000\n" +
 "a=recvonly\n";



 rtp.processOffer(cm_offer, function(error, cm_sdpAnswer){
 if(error) return onError(error);

 //webRtcPeer.processAnswer(cm_sdpAnswer, onError);
 });
 //rtp.gatherCandidates(onError);

 webRtcEpt.connect(rtp, function(error){
 if(error) return onError(error);

 console.log("RTP endpoint connected to webRTC");
 });
 });









 });
 });
 }
 });
 stopButton.addEventListener("click", stop);


 function stop() {
 if (webRtcPeer) {
 webRtcPeer.dispose();
 webRtcPeer = null;
 }

 if(pipeline){
 pipeline.release();
 pipeline = null;
 }

 hideSpinner(videoInput, videoOutput);
 }

 function onError(error) {
 if(error)
 {
 console.error(error);
 stop();
 }
 }
 })


 function showSpinner() {
 for (var i = 0; i < arguments.length; i++) {
 arguments[i].poster = 'img/transparent-1px.png';
 arguments[i].style.background = "center transparent url('img/spinner.gif') no-repeat";
 }
 }

 function hideSpinner() {
 for (var i = 0; i < arguments.length; i++) {
 arguments[i].src = '';
 arguments[i].poster = 'img/webrtc.png';
 arguments[i].style.background = '';
 }
 }

 /**
 * Lightbox utility (to display media pipeline image in a modal dialog)
 */
 $(document).delegate('*[data-toggle="lightbox"]', 'click', function(event) {
 event.preventDefault();
 $(this).ekkoLightbox();
 });



-
Scale filter crashes with error when used from transcoding example
27 juin 2017, par ValiI’ve modified a bit (just to compile in c++) this code example :
https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/transcoding.c.What works : as is (null filter), a number of other filters like framerate, drawtext, ...
What doesn’t work : scale filter when scaling down.
I use the following syntax for scale ( I’ve tried many others also, same effect) :
"scale=w=iw/2 :-1"The error is : "Input picture width (240) is greater than stride (128)" where the values for width and stride depend on the input.
Misc environment info : windows, VS 2017, input example : rtsp ://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov
Any clue as to what I’m doing wrong ?
Thanks !
EDITED to add working code sample
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avfilter.lib")
/*
* Copyright (c) 2010 Nicolas George
* Copyright (c) 2011 Stefano Sabatini
* Copyright (c) 2014 Andrey Utkin
*
**** EDITED 2017 for testing (see original here: https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/transcoding.c)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @file
* API example for demuxing, decoding, filtering, encoding and muxing
* @example transcoding.c
*/
extern "C"
{
#include <libavcodec></libavcodec>avcodec.h>
#include <libavformat></libavformat>avformat.h>
#include <libavfilter></libavfilter>avfiltergraph.h>
#include <libavfilter></libavfilter>buffersink.h>
#include <libavfilter></libavfilter>buffersrc.h>
#include <libavutil></libavutil>opt.h>
#include <libavutil></libavutil>pixdesc.h>
}
static AVFormatContext *ifmt_ctx;
static AVFormatContext *ofmt_ctx;
typedef struct FilteringContext {
AVFilterContext *buffersink_ctx;
AVFilterContext *buffersrc_ctx;
AVFilterGraph *filter_graph;
} FilteringContext;
static FilteringContext *filter_ctx;
typedef struct StreamContext {
AVCodecContext *dec_ctx;
AVCodecContext *enc_ctx;
} StreamContext;
static StreamContext *stream_ctx;
static int open_input_file(const char *filename, int& videoStreamIndex)
{
int ret;
unsigned int i;
ifmt_ctx = NULL;
if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
return ret;
}
if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
return ret;
}
// Just need video
videoStreamIndex = -1;
for (unsigned int i = 0; i < ifmt_ctx->nb_streams; i++)
{
if (ifmt_ctx->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
continue;
videoStreamIndex = i;
break;
}
if (videoStreamIndex < 0)
{
av_log(NULL, AV_LOG_ERROR, "Cannot find video stream\n");
return videoStreamIndex;
}
stream_ctx = (StreamContext*)av_mallocz_array(ifmt_ctx->nb_streams, sizeof(*stream_ctx));
if (!stream_ctx)
return AVERROR(ENOMEM);
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
// Just need video
if (i != videoStreamIndex)
continue;
AVStream *stream = ifmt_ctx->streams[i];
AVCodec *dec = avcodec_find_decoder(stream->codecpar->codec_id);
AVCodecContext *codec_ctx;
if (!dec) {
av_log(NULL, AV_LOG_ERROR, "Failed to find decoder for stream #%u\n", i);
return AVERROR_DECODER_NOT_FOUND;
}
codec_ctx = avcodec_alloc_context3(dec);
if (!codec_ctx) {
av_log(NULL, AV_LOG_ERROR, "Failed to allocate the decoder context for stream #%u\n", i);
return AVERROR(ENOMEM);
}
ret = avcodec_parameters_to_context(codec_ctx, stream->codecpar);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to copy decoder parameters to input decoder context "
"for stream #%u\n", i);
return ret;
}
/* Reencode video & audio and remux subtitles etc. */
if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
|| codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
codec_ctx->framerate = av_guess_frame_rate(ifmt_ctx, stream, NULL);
/* Open decoder */
ret = avcodec_open2(codec_ctx, dec, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
return ret;
}
}
stream_ctx[i].dec_ctx = codec_ctx;
}
av_dump_format(ifmt_ctx, 0, filename, 0);
return 0;
}
static int open_output_file(const char *filename, const int videoStreamIndex)
{
AVStream *out_stream;
AVStream *in_stream;
AVCodecContext *dec_ctx, *enc_ctx;
AVCodec *encoder;
int ret;
unsigned int i;
ofmt_ctx = NULL;
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);
if (!ofmt_ctx) {
av_log(NULL, AV_LOG_ERROR, "Could not create output context\n");
return AVERROR_UNKNOWN;
}
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
// Just need video
if (i != videoStreamIndex)
continue;
out_stream = avformat_new_stream(ofmt_ctx, NULL);
if (!out_stream) {
av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n");
return AVERROR_UNKNOWN;
}
in_stream = ifmt_ctx->streams[i];
dec_ctx = stream_ctx[i].dec_ctx;
if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
/* in this example, we choose transcoding to same codec */
encoder = avcodec_find_encoder(dec_ctx->codec_id);
if (!encoder) {
av_log(NULL, AV_LOG_FATAL, "Necessary encoder not found\n");
return AVERROR_INVALIDDATA;
}
enc_ctx = avcodec_alloc_context3(encoder);
if (!enc_ctx) {
av_log(NULL, AV_LOG_FATAL, "Failed to allocate the encoder context\n");
return AVERROR(ENOMEM);
}
/* In this example, we transcode to same properties (picture size,
* sample rate etc.). These properties can be changed for output
* streams easily using filters */
enc_ctx->height = dec_ctx->height;
enc_ctx->width = dec_ctx->width;
enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;
/* take first format from list of supported formats */
if (encoder->pix_fmts)
enc_ctx->pix_fmt = encoder->pix_fmts[0];
else
enc_ctx->pix_fmt = dec_ctx->pix_fmt;
/* video time_base can be set to whatever is handy and supported by encoder */
//enc_ctx->time_base = av_inv_q(dec_ctx->framerate);
enc_ctx->time_base = dec_ctx->time_base;
/* Third parameter can be used to pass settings to encoder */
ret = avcodec_open2(enc_ctx, encoder, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);
return ret;
}
ret = avcodec_parameters_from_context(out_stream->codecpar, enc_ctx);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to copy encoder parameters to output stream #%u\n", i);
return ret;
}
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
out_stream->time_base = enc_ctx->time_base;
stream_ctx[i].enc_ctx = enc_ctx;
}
else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) {
av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);
return AVERROR_INVALIDDATA;
}
else {
/* if this stream must be remuxed */
ret = avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Copying parameters for stream #%u failed\n", i);
return ret;
}
out_stream->time_base = in_stream->time_base;
}
}
av_dump_format(ofmt_ctx, 0, filename, 1);
if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {
ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Could not open output file '%s'", filename);
return ret;
}
}
/* init muxer, write output file header */
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n");
return ret;
}
return 0;
}
static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
AVCodecContext *enc_ctx, const char *filter_spec)
{
char args[512];
int ret = 0;
AVFilter *buffersrc = NULL;
AVFilter *buffersink = NULL;
AVFilterContext *buffersrc_ctx = NULL;
AVFilterContext *buffersink_ctx = NULL;
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
AVFilterGraph *filter_graph = avfilter_graph_alloc();
if (!outputs || !inputs || !filter_graph) {
ret = AVERROR(ENOMEM);
goto end;
}
if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
buffersrc = avfilter_get_by_name("buffer");
buffersink = avfilter_get_by_name("buffersink");
if (!buffersrc || !buffersink) {
av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
ret = AVERROR_UNKNOWN;
goto end;
}
snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
dec_ctx->time_base.num, dec_ctx->time_base.den,
dec_ctx->sample_aspect_ratio.num,
dec_ctx->sample_aspect_ratio.den);
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
args, NULL, filter_graph);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
goto end;
}
ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
NULL, NULL, filter_graph);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
goto end;
}
ret = av_opt_set_bin(buffersink_ctx, "pix_fmts",
(uint8_t*)&enc_ctx->pix_fmt, sizeof(enc_ctx->pix_fmt),
AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
goto end;
}
}
else {
ret = AVERROR_UNKNOWN;
goto end;
}
/* Endpoints for the filter graph. */
outputs->name = av_strdup("in");
outputs->filter_ctx = buffersrc_ctx;
outputs->pad_idx = 0;
outputs->next = NULL;
inputs->name = av_strdup("out");
inputs->filter_ctx = buffersink_ctx;
inputs->pad_idx = 0;
inputs->next = NULL;
if (!outputs->name || !inputs->name) {
ret = AVERROR(ENOMEM);
goto end;
}
if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_spec,
&inputs, &outputs, NULL)) < 0)
goto end;
if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
goto end;
/* Fill FilteringContext */
fctx->buffersrc_ctx = buffersrc_ctx;
fctx->buffersink_ctx = buffersink_ctx;
fctx->filter_graph = filter_graph;
end:
avfilter_inout_free(&inputs);
avfilter_inout_free(&outputs);
return ret;
}
static int init_filters(const int videoStreamIndex)
{
const char *filter_spec;
unsigned int i;
int ret;
filter_ctx = (FilteringContext*)av_malloc_array(ifmt_ctx->nb_streams, sizeof(*filter_ctx));
if (!filter_ctx)
return AVERROR(ENOMEM);
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
// Just video
if (i != videoStreamIndex)
continue;
filter_ctx[i].buffersrc_ctx = NULL;
filter_ctx[i].buffersink_ctx = NULL;
filter_ctx[i].filter_graph = NULL;
if (!(ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO
|| ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO))
continue;
filter_spec = "null"; /* passthrough (dummy) filter for video */
//filter_spec = "scale=w=iw/2:-1";
// filter_spec = "drawtext=fontfile=FreeSerif.ttf: text='%{localtime}': x=w-text_w: y=0: fontsize=24: fontcolor=yellow@1.0: box=1: boxcolor=red@1.0";
// filter_spec = "drawtext=fontfile=FreeSerif.ttf :text='test': x=w-text_w: y=text_h: fontsize=24: fontcolor=yellow@1.0: box=1: boxcolor=red@1.0";
ret = init_filter(&filter_ctx[i], stream_ctx[i].dec_ctx,
stream_ctx[i].enc_ctx, filter_spec);
if (ret)
return ret;
}
return 0;
}
static int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame, const int videoStreamIndex) {
// Just video
if (stream_index != videoStreamIndex)
return 0;
int ret;
int got_frame_local;
AVPacket enc_pkt;
int(*enc_func)(AVCodecContext *, AVPacket *, const AVFrame *, int *) =
(ifmt_ctx->streams[stream_index]->codecpar->codec_type ==
AVMEDIA_TYPE_VIDEO) ? avcodec_encode_video2 : avcodec_encode_audio2;
if (!got_frame)
got_frame = &got_frame_local;
// av_log(NULL, AV_LOG_INFO, "Encoding frame\n");
/* encode filtered frame */
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = enc_func(stream_ctx[stream_index].enc_ctx, &enc_pkt,
filt_frame, got_frame);
av_frame_free(&filt_frame);
if (ret < 0)
return ret;
if (!(*got_frame))
return 0;
/* prepare packet for muxing */
/*enc_pkt.stream_index = stream_index;
av_packet_rescale_ts(&enc_pkt, stream_ctx[stream_index].enc_ctx->time_base, ofmt_ctx->streams[stream_index]->time_base);*/
enc_pkt.stream_index = 0;
av_packet_rescale_ts(&enc_pkt, stream_ctx[stream_index].enc_ctx->time_base, ofmt_ctx->streams[0]->time_base);
av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");
/* mux encoded frame */
ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
return ret;
}
static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index, const int videoStreamIndex)
{
// Just video, all else crashes
if (stream_index != videoStreamIndex)
return 0;
int ret;
AVFrame *filt_frame;
// av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n");
/* push the decoded frame into the filtergraph */
ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx,
frame, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
return ret;
}
/* pull filtered frames from the filtergraph */
while (1) {
filt_frame = av_frame_alloc();
if (!filt_frame) {
ret = AVERROR(ENOMEM);
break;
}
// av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n");
ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx,
filt_frame);
if (ret < 0) {
/* if no more frames for output - returns AVERROR(EAGAIN)
* if flushed and no more frames for output - returns AVERROR_EOF
* rewrite retcode to 0 to show it as normal procedure completion
*/
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
ret = 0;
av_frame_free(&filt_frame);
break;
}
filt_frame->pict_type = AV_PICTURE_TYPE_NONE;
ret = encode_write_frame(filt_frame, stream_index, NULL, videoStreamIndex);
if (ret < 0)
break;
}
return ret;
}
static int flush_encoder(unsigned int stream_index, const int videoStreamIndex)
{
int ret;
int got_frame;
// Just video
if (stream_index != videoStreamIndex)
return 0;
if (!(stream_ctx[stream_index].enc_ctx->codec->capabilities &
AV_CODEC_CAP_DELAY))
return 0;
while (1) {
av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index);
ret = encode_write_frame(NULL, stream_index, &got_frame, videoStreamIndex);
if (ret < 0)
break;
if (!got_frame)
return 0;
}
return ret;
}
#include <vector>
int main(int argc, char **argv)
{
int ret;
AVPacket packet;
packet.data = NULL;
packet.size = 0;
AVFrame *frame = NULL;
enum AVMediaType type;
unsigned int stream_index;
unsigned int i;
int got_frame;
int(*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *);
#ifdef _DEBUG
// Hardcoded arguments
std::vector varguments;
{
varguments.push_back(argv[0]);
// Source
varguments.push_back("./big_buck_bunny_short.mp4 ");
// Destination
varguments.push_back("./big_buck_bunny_short-processed.mp4");
}
char** arguments = new char*[varguments.size()];
for (unsigned int i = 0; i < varguments.size(); i++)
{
arguments[i] = varguments[i];
}
argc = varguments.size();
argv = arguments;
#endif // _DEBUG
if (argc != 3) {
av_log(NULL, AV_LOG_ERROR, "Usage: %s <input file="file" /> <output file="file">\n", argv[0]);
return 1;
}
av_register_all();
avfilter_register_all();
int videoStreamIndex = -1;
if ((ret = open_input_file(argv[1], videoStreamIndex)) < 0)
goto end;
if ((ret = open_output_file(argv[2], videoStreamIndex)) < 0)
goto end;
if ((ret = init_filters(videoStreamIndex)) < 0)
goto end;
// Stop after a couple of frames
int framesToGet = 100;
/* read all packets */
//while (framesToGet--)
while(1)
{
if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)
break;
stream_index = packet.stream_index;
// I just need video
if (stream_index != videoStreamIndex) {
av_packet_unref(&packet);
continue;
}
type = ifmt_ctx->streams[packet.stream_index]->codecpar->codec_type;
av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n",
stream_index);
if (filter_ctx[stream_index].filter_graph) {
av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n");
frame = av_frame_alloc();
if (!frame) {
ret = AVERROR(ENOMEM);
break;
}
av_packet_rescale_ts(&packet,
ifmt_ctx->streams[stream_index]->time_base,
stream_ctx[stream_index].dec_ctx->time_base);
dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 :
avcodec_decode_audio4;
ret = dec_func(stream_ctx[stream_index].dec_ctx, frame,
&got_frame, &packet);
if (ret < 0) {
av_frame_free(&frame);
av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");
break;
}
if (got_frame) {
frame->pts = frame->best_effort_timestamp;
ret = filter_encode_write_frame(frame, stream_index, videoStreamIndex);
av_frame_free(&frame);
if (ret < 0)
goto end;
}
else {
av_frame_free(&frame);
}
}
else {
/* remux this frame without reencoding */
av_packet_rescale_ts(&packet,
ifmt_ctx->streams[stream_index]->time_base,
ofmt_ctx->streams[stream_index]->time_base);
ret = av_interleaved_write_frame(ofmt_ctx, &packet);
if (ret < 0)
goto end;
}
av_packet_unref(&packet);
}
/* flush filters and encoders */
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
/* flush filter */
if (!filter_ctx[i].filter_graph)
continue;
ret = filter_encode_write_frame(NULL, i, videoStreamIndex);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n");
goto end;
}
/* flush encoder */
ret = flush_encoder(i, videoStreamIndex);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Flushing encoder failed\n");
goto end;
}
}
av_write_trailer(ofmt_ctx);
end:
av_packet_unref(&packet);
av_frame_free(&frame);
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
// Just video
if (i != videoStreamIndex)
continue;
avcodec_free_context(&stream_ctx[i].dec_ctx);
if (ofmt_ctx && ofmt_ctx->nb_streams > i && ofmt_ctx->streams[i] && stream_ctx[i].enc_ctx)
avcodec_free_context(&stream_ctx[i].enc_ctx);
if (filter_ctx && filter_ctx[i].filter_graph)
avfilter_graph_free(&filter_ctx[i].filter_graph);
}
av_free(filter_ctx);
av_free(stream_ctx);
avformat_close_input(&ifmt_ctx);
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_closep(&ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
/*if (ret < 0)
av_log(NULL, AV_LOG_ERROR, "Error occurred: %s\n", av_err2str(ret));*/
return ret ? 1 : 0;
}
</output></vector> -
Merge remote-tracking branch ’rbultje/vp9-profile1-wip’
1er mai 2015, par Michael NiedermayerMerge remote-tracking branch ’rbultje/vp9-profile1-wip’
* rbultje/vp9-profile1-wip :
vp9 : add fate test for 422.
vp9 : copy bug in libvpx for 4:2:2 chroma bs=8x4/4x4 prediction.
vp9 : add yuv440 fate test.
vp9 : fix mask_edges and filter_plane_rows/cols() for 440.
vp9 : more specifically specify mask destination to mask_edges().
vp9 : add fate test for profile 1 444.
vp9 : don’t create special u/v filter masks for 444.
vp9 : merge uv loopfilter code into generic filter_plane_rows/cols().
vp9 : split out loopfilter luma rows/cols functions from loopfilter_sb().
vp9 : invert order of two conditions.
vp9 : use correct chroma subsampling for profile 1 inter block recon.
vp9 : use correct chroma subsampling for profile 1 intra block recon.
vp9 : take chroma subsampling into account when walking the block tree.
vp9 : support non-420 chroma subsampling for profile 1 token decoding.
vp9 : increase buffer sizes for non-420 chroma subsamplings.
vp9 : profile 1 header decoding.Merged-by : Michael Niedermayer <michaelni@gmx.at>