[Combat FFmpeg] Analyse du filtre audio FFplay

Adresse d'origine : https://juejin.cn/post/7153334309208719368

Les filtres de flux audio sont créés via la fonction configure_audio_filters(). Parce que ffplay veut la polyvalence du code, même si les paramètres de ligne de commande n'utilisent pas de filtres, AVFrame passera par le filtre vide pour faire ce qui suit.

L'organigramme de la fonction configure_audio_filters() est le suivant :

img

La fonction configure_audio_filters() est définie comme suit :

static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format){
    
    ....}

Les paramètres de cette fonction sont expliqués ci-dessous.

VideoState *is est le gestionnaire mondial du lecteur ffplay.

char *afilters est une chaîne de filtre, telle que la commande suivante :

ffplay -af "atempo=2.0" -i juren-5s.mp4

La chaîne "atempo=2.0" sera affectée aux filtres.

int force_output_format, indique s'il faut forcer l'échantillonnage de la trame audio et d'autres informations du filtre d'exportation du buffersink à être identiques à is->audio_tgt.

Comme mentionné précédemment, is->audio_tgt correspond aux informations ouvertes par le périphérique matériel audio. is->audio_tgt est le format audio finalement transmis à SDL. Tous les taux d'échantillonnage, le nombre de canaux, etc. doivent éventuellement être convertis en is->audio_tgt.

Analysons les codes clés de la fonction configure_audio_filters(), comme suit :

img

Cette fonction définit certains tableaux avec seulement 2 éléments au début. C'est en fait la façon dont le projet ffmpeg passe les paramètres. Il existe deux manières principales de passer un tableau dans la fonction.

1. Transmettez la taille du tableau. Combien d’éléments il y a.

2. Passez la fin du tableau.Tant que l'élément de fin (-1) est lu, c'est fini.

La plupart des fonctions de ffmpeg utilisent la deuxième méthode.

Ensuite, il ajustera avfilter_graph_free() pour libérer le conteneur de filtre (FilterGraph). Certains étudiants peuvent se demander si is->agraph NULL n'est-il pas au début ? Pourquoi la libération est-elle nécessaire ?

is->agraph est bien NULL au début, mais la fonction configure_audio_filters() peut être appelée une seconde fois , et is->agraph n'est pas NULL la deuxième fois.

Le premier appel de configure_audio_filters() se fait dans stream_component_open(), comme suit :

img

Le deuxième appel se fait dans audio_thread(), comme suit :

img

Le deuxième appel à configure_audio_filters() est dû au fait que la fréquence d'échantillonnage, les canaux, etc. de l'AVFrame réellement décodé sont incohérents avec ceux enregistrés dans le conteneur. Auparavant, is->audio_filter_src était les données extraites directement du conteneur et de la couche d'encapsulation. Le taux d'échantillonnage audio enregistré par la couche d'encapsulation peut être erroné et le AVFrame réel décodé doit prévaloir.

De plus, notez que la deuxième fois, le paramètre force_output_format sera défini sur 1, ce qui forcera les informations d'échantillonnage du filtre d'exportation buffersink à être définies sur la même valeur que is->audio_tgt.

En fait, configure_audio_filters() sera certainement ajusté une deuxième fois , car la condition is->auddec.pkt_serial != last_serial doit être vraie.

L'étape suivante consiste à définir le nombre de threads utilisés par le filtre. 0 est le nombre de threads sélectionnés automatiquement, comme suit :

is->agraph->nb_threads = filter_nbthreads;

Le troisième point important est de définir les options de rééchantillonnage (aresample_swr_opts) comme suit :

img

Quels types de paramètres de ligne de commande correspondent aux options de rééchantillonnage peuvent être trouvés dans libswresample/options.c, comme suit :

img

Par exemple, comme suit :

ffpaly -ich 1 -i juren-5s.mp4

ich 1 sera analysé et copié dans la variable swr_opts dans ffplay.c.

Une nouvelle fonction av_opt_set() est également utilisée ici. Cette fonction peut non seulement définir les champs d'attributs du filtre , mais également définir les champs d'attributs de la plupart des structures de données , telles que les décodeurs, les wrappers, etc., tant qu'il y a AVClass données à l'intérieur de la structure, vous pouvez utiliser av_opt_set() pour définir les attributs. Pour plus de détails, veuillez lire " Opt.h File Function Analysis "

Le prochain point clé est de définir les filtres d’entrée et de sortie, comme suit :

img

Le filtre d'exportation définit également sample_fmts sur AV_SAMPLE_FMT_S16. Il s'agit d'une fonctionnalité du lecteur ffpaly lui-même, ce qui signifie que quel que soit le format audio du fichier MP4, il sera converti au format AV_SAMPLE_FMT_S16 et envoyé en SDL pour la lecture, et il utilise SDL_OpenAudioDevice pour ouvrir l' audio . Lors de l'installation de l'appareil, le format S16 est utilisé, qui est codé en dur .

La logique de force_output_format est principalement de forcer les informations d'échantillonnage du filtre d'exportation buffersink à être les mêmes que is->audio_tgt. audio_tgt est le format final dans lequel SDL accepte les trames audio.

La première fois que vous appelez la fonction configure_audio_filters(), force_output_format vaut 0 et cette logique ne sera pas entrée.

La dernière étape consiste à ajuster la fonction configure_filtergraph() pour lier les filtres d'entrée et de sortie et créer un conteneur de filtres (FilterGraph), comme suit :

img

La chose la plus importante dans la figure ci-dessus est que le filtre d'entrée et le filtre de sortie sont attribués au gestionnaire global. Plus tard, il vous suffit de transférer la sortie AVFrame du décodeur vers le filtre d'entrée, puis de la lire vers le filtre de sortie.

La logique interne de la fonction configure_filtergraph() est relativement simple. Veuillez l'étudier vous-même. Si vous n'êtes pas familier avec les différentes fonctions de filtre, vous pouvez lire des articles sur les filtres tels que "Introduction au filtre d'échelle de FFmpeg" .

  >>> 音视频开发 视频教程: https://ke.qq.com/course/3202131?flowToken=1031864 
  >>> 音视频开发学习资料、教学视频,免费分享有需要的可以自行添加学习交流群 739729163 领取

Je suppose que tu aimes

Origine blog.csdn.net/weixin_52622200/article/details/131616162
conseillé
Classement