
Recherche avancée
Autres articles (71)
-
Configurer la prise en compte des langues
15 novembre 2010, parAccéder à la configuration et ajouter des langues prises en compte
Afin de configurer la prise en compte de nouvelles langues, il est nécessaire de se rendre dans la partie "Administrer" du site.
De là, dans le menu de navigation, vous pouvez accéder à une partie "Gestion des langues" permettant d’activer la prise en compte de nouvelles langues.
Chaque nouvelle langue ajoutée reste désactivable tant qu’aucun objet n’est créé dans cette langue. Dans ce cas, elle devient grisée dans la configuration et (...) -
Websites made with MediaSPIP
2 mai 2011, parThis page lists some websites based on MediaSPIP.
-
Support de tous types de médias
10 avril 2011Contrairement à beaucoup de logiciels et autres plate-formes modernes de partage de documents, MediaSPIP a l’ambition de gérer un maximum de formats de documents différents qu’ils soient de type : images (png, gif, jpg, bmp et autres...) ; audio (MP3, Ogg, Wav et autres...) ; vidéo (Avi, MP4, Ogv, mpg, mov, wmv et autres...) ; contenu textuel, code ou autres (open office, microsoft office (tableur, présentation), web (html, css), LaTeX, Google Earth) (...)
Sur d’autres sites (7604)
-
Problems with outputting stream format as RTMP via FFmpeg C-API
9 janvier 2024, par dongrixinyuI am using FFmpeg's C API to push video streams
rtmp://....
into an SRS server.

The input stream is an MP4 file namedjuren-30s.mp4
.

The output stream is also an MP4 file namedjuren-30s-5.mp4
.

My piece of code (see further down) works fine when used in the following steps :

mp4 -> demux -> decode -> rgb images -> encode -> mux -> mp4
.

Problem :


When I changed the output stream to an online RTMP url named
rtmp://ip:port/live/stream_nb_23
(just an example, you can change it according to your server and rules.)

result : This code would be corrupted
mp4 -> rtmp(flv)
.

What I've tried :


Changing the output format

I changed the output format param to become flv when I initialized theavformat_alloc_output_context2
. But this didn't help.

Debugging the output

When I executedffprobe rtmp://ip:port/live/xxxxxxx
, I got the following errors and did not know why :

[h264 @ 0x55a925e3ba80] luma_log2_weight_denom 12 is out of range
[h264 @ 0x55a925e3ba80] Missing reference picture, default is 2
[h264 @ 0x55a925e3ba80] concealing 8003 DC, 8003 AC, 8003 MV errors in P frame
[h264 @ 0x55a925e3ba80] QP 4294966938 out of range
[h264 @ 0x55a925e3ba80] decode_slice_header error
[h264 @ 0x55a925e3ba80] no frame!
[h264 @ 0x55a925e3ba80] luma_log2_weight_denom 21 is out of range
[h264 @ 0x55a925e3ba80] luma_log2_weight_denom 10 is out of range
[h264 @ 0x55a925e3ba80] chroma_log2_weight_denom 12 is out of range
[h264 @ 0x55a925e3ba80] Missing reference picture, default is 0
[h264 @ 0x55a925e3ba80] decode_slice_header error
[h264 @ 0x55a925e3ba80] QP 4294967066 out of range
[h264 @ 0x55a925e3ba80] decode_slice_header error
[h264 @ 0x55a925e3ba80] no frame!
[h264 @ 0x55a925e3ba80] QP 341 out of range
[h264 @ 0x55a925e3ba80] decode_slice_header error



I am confused about the difference between MP4 and RTMP of how to use FFmpeg C-API to produce a correct output stream format.


Besides, I also wanna learn how to convert video and audio streams into other formats using FFmpeg C-api, such as
flv
,ts
,rtsp
, etc.

Code to reproduce the problem :


- 

-
I have also put the project files (code, video files) on Github.


-
The C code shown below can be specifically found at Main.c which is a minimum version to reproduce. It can be reproduced and run successfully.








So how to make this code output to RTMP without getting issue of an unplayable video ?


#include 
#include "libavformat/avformat.h"
int main()
{
 int ret = 0; int err;

 //Open input file
 char filename[] = "juren-30s.mp4";
 AVFormatContext *fmt_ctx = avformat_alloc_context();
 if (!fmt_ctx) {
 printf("error code %d \n",AVERROR(ENOMEM));
 return ENOMEM;
 }
 if((err = avformat_open_input(&fmt_ctx, filename,NULL,NULL)) < 0){
 printf("can not open file %d \n",err);
 return err;
 }

 //Open the decoder
 AVCodecContext *avctx = avcodec_alloc_context3(NULL);
 ret = avcodec_parameters_to_context(avctx, fmt_ctx->streams[0]->codecpar);
 if (ret < 0){
 printf("error code %d \n",ret);
 return ret;
 }
 AVCodec *codec = avcodec_find_decoder(avctx->codec_id);
 if ((ret = avcodec_open2(avctx, codec, NULL)) < 0) {
 printf("open codec faile %d \n",ret);
 return ret;
 }

 //Open the output file container
 char filename_out[] = "juren-30s-5.mp4";
 AVFormatContext *fmt_ctx_out = NULL;
 err = avformat_alloc_output_context2(&fmt_ctx_out, NULL, NULL, filename_out);
 if (!fmt_ctx_out) {
 printf("error code %d \n",AVERROR(ENOMEM));
 return ENOMEM;
 }
 //Add all the way to the container context
 AVStream *st = avformat_new_stream(fmt_ctx_out, NULL);
 st->time_base = fmt_ctx->streams[0]->time_base;

 AVCodecContext *enc_ctx = NULL;
 
 AVPacket *pt = av_packet_alloc();
 AVFrame *frame = av_frame_alloc();
 AVPacket *pkt_out = av_packet_alloc();

 int frame_num = 0; int read_end = 0;
 
 for(;;){
 if( 1 == read_end ){ break;}

 ret = av_read_frame(fmt_ctx, pkt);
 //Skip and do not process audio packets
 if( 1 == pkt->stream_index ){
 av_packet_unref(pt);
 continue;
 }

 if ( AVERROR_EOF == ret) {
 //After reading the file, the data and size of pkt should be null at this time
 avcodec_send_packet(avctx, NULL);
 }else {
 if( 0 != ret){
 printf("read error code %d \n",ret);
 return ENOMEM;
 }else{
 retry:
 if (avcodec_send_packet(avctx, pkt) == AVERROR(EAGAIN)) {
 printf("Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
 //Here you can consider sleeping for 0.1 seconds and returning EAGAIN. This is usually because there is a bug in ffmpeg's internal API.
 goto retry;
 }
 //Release the encoded data in pkt
 av_packet_unref(pt);
 }

 }

 //The loop keeps reading data from the decoder until there is no more data to read.
 for(;;){
 //Read AVFrame
 ret = avcodec_receive_frame(avctx, frame);
 /* Release the YUV data in the frame,
 * Since av_frame_unref is called in the avcodec_receive_frame function, the following code can be commented.
 * So we don't need to manually unref this AVFrame
 * */
 //off_frame_unref(frame);

 if( AVERROR(EAGAIN) == ret ){
 //Prompt EAGAIN means the decoder needs more AVPackets
 //Jump out of the first layer of for and let the decoder get more AVPackets
 break;
 }else if( AVERROR_EOF == ret ){
 /* The prompt AVERROR_EOF means that an AVPacket with both data and size NULL has been sent to the decoder before.
 * Sending NULL AVPacket prompts the decoder to flush out all cached frames.
 * Usually a NULL AVPacket is sent only after reading the input file, or when another video stream needs to be decoded with an existing decoder.
 *
 * */

 /* Send null AVFrame to the encoder and let the encoder flush out the remaining data.
 * */
 ret = avcodec_send_frame(enc_ctx, NULL);
 for(;;){
 ret = avcodec_receive_packet(enc_ctx, pkt_out);
 //It is impossible to return EAGAIN here, if there is any, exit directly.
 if (ret == AVERROR(EAGAIN)){
 printf("avcodec_receive_packet error code %d \n",ret);
 return ret;
 }
 
 if ( AVERROR_EOF == ret ){ break; }
 
 //Encode the AVPacket, print some information first, and then write it to the file.
 printf("pkt_out size : %d \n",pkt_out->size);
 //Set the stream_index of AVPacket so that you know which stream it is.
 pkt_out->stream_index = st->index;
 //Convert the time base of AVPacket to the time base of the output stream.
 pkt_out->pts = av_rescale_q_rnd(pkt_out->pts, fmt_ctx->streams[0]->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
 pkt_out->dts = av_rescale_q_rnd(pkt_out->dts, fmt_ctx->streams[0]->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
 pkt_out->duration = av_rescale_q_rnd(pkt_out->duration, fmt_ctx->streams[0]->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);


 ret = av_interleaved_write_frame(fmt_ctx_out, pkt_out);
 if (ret < 0) {
 printf("av_interleaved_write_frame faile %d \n",ret);
 return ret;
 }
 av_packet_unref(pt_out);
 }
 av_write_trailer(fmt_ctx_out);
 //Jump out of the second layer of for, the file has been decoded.
 read_end = 1;
 break;
 }else if( ret >= 0 ){
 //Only when a frame is decoded can the encoder be initialized.
 if( NULL == enc_ctx ){
 //Open the encoder and set encoding information.
 AVCodec *encode = avcodec_find_encoder(AV_CODEC_ID_H264);
 enc_ctx = avcodec_alloc_context3(encode);
 enc_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
 enc_ctx->bit_rate = 400000;
 enc_ctx->framerate = avctx->framerate;
 enc_ctx->gop_size = 30;
 enc_ctx->max_b_frames = 10;
 enc_ctx->profile = FF_PROFILE_H264_MAIN;
 
 /*
 * In fact, the following information is also available in the container. You can also open the encoder directly in the container at the beginning.
 * I took these encoder parameters from AVFrame because the difference in the container is final.
 * Because the AVFrame you decoded may go through a filter, the information will be transformed after the filter, but this article does not use filters.
 */
 
 //The time base of the encoder should be the time base of AVFrame, because AVFrame is the input. The time base of AVFrame is the time base of the stream.
 enc_ctx->time_base = fmt_ctx->streams[0]->time_base;
 enc_ctx->width = fmt_ctx->streams[0]->codecpar->width;
 enc_ctx->height = fmt_ctx->streams[0]->codecpar->height;
 enc_ctx->sample_aspect_ratio = st->sample_aspect_ratio = frame->sample_aspect_ratio;
 enc_ctx->pix_fmt = frame->format;
 enc_ctx->color_range = frame->color_range;
 enc_ctx->color_primaries = frame->color_primaries;
 enc_ctx->color_trc = frame->color_trc;
 enc_ctx->colorspace = frame->colorspace;
 enc_ctx->chroma_sample_location = frame->chroma_location;

 /* Note that the value of this field_order is different for different videos. I have written it here.
 * Because the video in this article is AV_FIELD_PROGRESSIVE
 * The production environment needs to process different videos
 */
 enc_ctx->field_order = AV_FIELD_PROGRESSIVE;

 /* Now we need to copy the encoder parameters to the stream. When decoding, assign parameters from the stream to the decoder.
 * Now let’s do it in reverse.
 * */
 ret = avcodec_parameters_from_context(st->codecpar,enc_ctx);
 if (ret < 0){
 printf("error code %d \n",ret);
 return ret;
 }
 if ((ret = avcodec_open2(enc_ctx, encode, NULL)) < 0) {
 printf("open codec faile %d \n",ret);
 return ret;
 }

 //Formally open the output file
 if ((ret = avio_open2(&fmt_ctx_out->pb, filename_out, AVIO_FLAG_WRITE,&fmt_ctx_out->interrupt_callback,NULL)) < 0) {
 printf("avio_open2 fail %d \n",ret);
 return ret;
 }

 //Write the file header first.
 ret = avformat_write_header(fmt_ctx_out,NULL);
 if (ret < 0) {
 printf("avformat_write_header fail %d \n",ret);
 return ret;
 }

 }

 //Send AVFrame to the encoder, and then continuously read AVPacket
 ret = avcodec_send_frame(enc_ctx, frame);
 if (ret < 0) {
 printf("avcodec_send_frame fail %d \n",ret);
 return ret;
 }
 for(;;){
 ret = avcodec_receive_packet(enc_ctx, pkt_out);
 if (ret == AVERROR(EAGAIN)){ break; }
 
 if (ret < 0){
 printf("avcodec_receive_packet fail %d \n",ret);
 return ret;
 }
 
 //Encode the AVPacket, print some information first, and then write it to the file.
 printf("pkt_out size : %d \n",pkt_out->size);

 //Set the stream_index of AVPacket so that you know which stream it is.
 pkt_out->stream_index = st->index;
 
 //Convert the time base of AVPacket to the time base of the output stream.
 pkt_out->pts = av_rescale_q_rnd(pkt_out->pts, fmt_ctx->streams[0]->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
 pkt_out->dts = av_rescale_q_rnd(pkt_out->dts, fmt_ctx->streams[0]->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
 pkt_out->duration = av_rescale_q_rnd(pkt_out->duration, fmt_ctx->streams[0]->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);

 ret = av_interleaved_write_frame(fmt_ctx_out, pkt_out);
 if (ret < 0) {
 printf("av_interleaved_write_frame faile %d \n",ret);
 return ret;
 }
 av_packet_unref(pt_out);
 }

 }
 else{ printf("other fail \n"); return ret;}
 }
 }
 
 av_frame_free(&frame); av_packet_free(&pt); av_packet_free(&pkt_out);
 
 //Close the encoder and decoder.
 avcodec_close(avctx); avcodec_close(enc_ctx);

 //Release container memory.
 avformat_free_context(fmt_ctx);

 //Must adjust avio_closep, otherwise the data may not be written in, it will be 0kb
 avio_closep(&fmt_ctx_out->pb);
 avformat_free_context(fmt_ctx_out);
 printf("done \n");

 return 0;
}



This problem has haunted over my head for about three weeks. I still have no idea where the key bug exists. Really appreciate it if any FFmpeg expert could help me.


-
-
My SBC Collection
31 décembre 2023, par Multimedia Mike — GeneralLike many computer nerds in the last decade, I have accumulated more than a few single-board computers, or “SBCs”, which are small computers based around a system-on-a-chip (SoC) that nearly always features an ARM CPU at its core. Surprisingly few of these units are Raspberry Pi units, though that brand has come to exemplify and dominate the product category.
Also, as is the case for many computer nerds, most of these SBCs lay fallow for years at a time. Equipped with an inexpensive lightbox that I procured in the last year, I decided I could at least create glamour shots of various units and catalog them in a blog post.
While Raspberry Pi still enjoys the most mindshare far and away, and while I do have a few Raspberry Pi units in my inventory, I have always been a bigger fan of the ODROID brand, which works with convenient importers around the world (in the USA, I can vouch for Ameridroid, to whom I’ve forked over a fair amount of cash for these computing toys).
As mentioned, Raspberry Pi undisputedly has the most mindshare of all these SBC brands and I often wonder why… and then I immediately remind myself that it has the biggest ecosystem, and has a variety of turnkey projects and applications (such as Pi-hole and PiVPN) that promise a lower barrier to entry — as well as a slightly lower price point — than some of these other options. ODROID had a decent ecosystem for awhile, especially considering the monthly ODROID Magazine, though that ceased publication in July 2020. The Raspberry Pi and its variants were famously difficult to come by due to the global chip shortage from 2021-2023. Meanwhile, I had no trouble procuring these boards during the same timeframe.
So let’s delve into the collection…
Cubieboard
The Raspberry Pi came out in 2012 and by 2013 I was somewhat coveting one to hack on. Finally ! An accessible ARM platform to play with. I had heard of the BeagleBoard for years but never tried to get my hands on one. I was thinking about taking the plunge on a new Raspberry Pi, but a colleague told me I should skip that and go with this new hotness called the Cubieboard, based on an Allwinner SoC. The big value-add that this board had vs. a Raspberry Pi was that it had a SATA adapter. Although now that it has been a decade, it only now occurs to me to quander whether it was true SATA or a USB-to-SATA bridge. Looking it up now, I’m led to believe that the SoC supported the functionality natively.Anyway, I did get it up and running but never did much with it, thus setting the tone for future SBC endeavors. No photos because I gave it to another tech enthusiast years ago, whose SBC collection dwarfs my own.
ODROID-XU4
I can’t recall exactly when or how I first encountered the ODROID brand. I probably read about it on some enthusiast page or another circa 2014 and decided to try one out. I eventually acquired a total of 3 of these ODROID-XU4 units, each with a different case, 1 with a fan and 2 passively-cooled :This is based on the Samsung Exynos 5422 SoC, the same series as was used in their Note 3 phone released in 2013. It has been a fun chip to play with. The XU4 was also my first introduction to the eMMC storage solution that is commonly supported on the ODROID SBCs (alongside micro-SD). eMMC offers many benefits over SD in terms of read/write speed as well as well as longevity/write cycles. That’s getting less relevant these days, however, as more and more SBCs are being released with direct NVMe SSD support.
I had initially wanted to make a retro-gaming device built on this platform (see the handheld section later for more meditations on that). In support of this common hobbyist goal, there is this nifty case XU4 case which apes the aesthetic of the Nintendo N64 :
It even has a cool programmable LCD screen. Maybe one day I’ll find a use for it.
For awhile, one of these XU4 units (likely the noisy, fan-cooled one) was contributing results to the FFmpeg FATE system.
While it features gigabit ethernet and a USB3 port, I once tried to see if I could get 2 Gbps throughput with the unit using a USB3-gigabit dongle. I had curious results in that the total amount of traffic throughput could never exceed 1 Gbps across both interfaces. I.e., if 1 interface was dealing with 1 Gbps and the other interface tried to run at 1 Gbps, they would both only run at 500 Mbps. That remains a mystery to me since I don’t see that limitation with Intel chips.
Still, the XU4 has been useful for a variety of projects and prototyping over the years.
ODROID-HC2 NAS
I find that a lot of my fellow nerds massively overengineer their homelab NAS setups. I’ll explore this in a future post. For my part, people tend to find my homelab NAS solution slightly underengineered. This is the ODROID-HC2 (the “HC” stands for “Home Cloud”) :It has the same guts as the ODROID-XU4 except no video output and the USB3 function is leveraged for a SATA bridge. This allows you to plug a SATA hard drive directly into the unit :
Believe it or not, this has been my home NAS solution for something like 6 or 7 years now– I don’t clearly remember when I purchased it and put it into service.
But isn’t this sort of irresponsible ? What about a failure of the main drive ? That’s why I have an external drive connected for backing up the most important data via rsync :
The power consumption can’t be beat– Profiling for a few weeks of average usage worked out to 4.5 kWh for the ODROID-HC2… per month.
ODROID-C2
I was on a kick of ordering more SBCs at one point. This is the ODROID-C2, equipped with a 64-bit Amlogic SoC :I had this on the FATE farm for awhile, performing 64-bit ARM builds (vs. the XU4’s 32-bit builds). As memory serves, it was unreliable and would occasionally freeze up.
Here is a view of the eMMC storage through the bottom of the translucent case :
ODROID-N2+
Out of all my ODROID SBCs, this is the unit that I long to “get back to” the most– the ODROID-N2+ :Very capable unit that makes a great little desktop. I have some projects I want to develop using it so that it will force me to have a focused development environment.
Raspberry Pi
Eventually, I did break down and get a Raspberry Pi. I had a specific purpose in mind and, much to my surprise, I have stuck to it :I was using one of the ODROID-XU4 units as a VPN gateway. Eventually, I wanted to convert the XU4 to something else and I decided to run the VPN gateway as an appliance on the simplest device I could. So I procured this complete hand-me-down unit from eBay and went to work. This was also the first time I discovered the DietPi distribution and this box has been in service running Wireguard via PiVPN for many years.
I also have a Raspberry Pi 3B+ kicking around somewhere. I used it as a Steam Link device for awhile.
SOPINE + Baseboard
Also procured when I was on this “let’s buy random SBCs” kick. The Pine64 SOPINE is actually a compute module that comes in the form factor of a memory module.Back to using Allwinner SoCs. In order to make this thing useful, you need to place it in something. It’s possible to get a mini-ITX form factor board that can accommodate 7 of these modules. Before going to that extreme, there is this much simpler baseboard which can also use eMMC for storage.
I really need to find an appropriate case for this one as it currently performs its duty while sitting on an anti-static bag.
NanoPi NEO3
I enjoy running the DietPi distribution on many of these SBCs (as it’s developed not just for Raspberry Pi). I have also found their website to be a useful resource for discovering new SBCs. That’s how I found the NanoPi series and zeroed in on this NEO3 unit, sporting a Rockchip SoC, and photographed here with some American currency in order to illustrate its relative size :I often forget about this computer because it’s off in another room, just quietly performing its assigned duty.
MangoPi MQ-Pro
So far, I’ve heard of these fruits prepending the Greek letter pi for naming small computing products :- Raspberry – the O.G.
- Banana – seems to be popular for hobbyist router/switches
- Orange
- Atomic
- Nano
- Mango
Okay, so the AtomicPi and NanoPi names don’t really make sense considering the fruit convention.
Anyway, the newest entry is the MangoPi. These showed up on Ameridroid a few months ago. There are 2 variants : the MQ-Pro and the MQ-Quad. I picked one and rolled with it.
When it arrived, I unpacked it, assembled the pieces, downloaded a distro, tossed that on a micro-SD card, connected a monitor and keyboard to it via its USB-C port, got the distro up and running, configured the wireless networking with a static IP address and installed sshd, and it was ready to go as a headless server for an edge application.
The unit came with no instructions that I can recall. After I got it set up, I remember thinking, “What is wrong with me ? Why is it that I just know how to do all of this without any documentation ?”
Only after I got it up and running and poked around a bit did I realize that this SBC doesn’t have an ARM SoC– it’s a RISC-V SoC. It uses the Allwinner D1, so it looks like I came full circle back to Allwinner.
So I now have my first piece of RISC-V hobbyist kit, although I learned recently from Kostya that it’s not that great for multimedia.
Handheld Gaming Units
The folks at Hardkernel have also produced a series of handheld retro-gaming devices called ODROID-GO. The first one resembled the original Nintendo Game Boy, came as a kit to be assembled, and emulated 5 classic consoles. It also had some hackability to it. Quite a cool little device, and inexpensive too. I have since passed it along to another gaming enthusiast.Later came the ODROID-GO Advance, also a kit, but emulating more devices. I was extremely eager to get my hands on this since it could emulate SNES in addition to NES. It also features a headphone jack, unlike the earlier model. True to form, after I received mine, it took me about 13 months before I got around to assembling it. After that, the biggest challenge I had was trying to find an appropriate case for it.
Even though it may try to copy the general aesthetic and form factor of the Game Boy Advance, cases for the GBA don’t fit this correctly.
Further, Hardkernel have also released the ODROID-GO Super and Ultra models that do more and more. The Advance, Super, and Ultra models have powerful SoCs and feature much more hackability than the first ODROID-GO model.
I know that the guts of the Advance have been used in other products as well. The same is likely true for the Super and Ultra.
Ultimately, the ODROID-GO Advance was just another project I assembled and then set aside since I like the idea of playing old games much more than actually doing it. Plus, the fact has finally crystalized in my mind over the past few years that I have never enjoyed handheld gaming and likely will never enjoy handheld gaming, even after I started wearing glasses. Not that I’m averse to old Game Boy / Color / Advance games, but if I’m going to play them, I’d rather emulate them on a large display.
The Future
In some of my weaker moments, I consider ordering up certain Banana Pi products (like the Banana Pi BPI-R2) with a case and doing my own router tricks using some open source router/firewall solution. And then I remind myself that my existing prosumer-type home router is doing just fine. But maybe one day…The post My SBC Collection first appeared on Breaking Eggs And Making Omelettes.
-
Evolution #3361 (Nouveau) : Tri par défaut des entrées des menus du bandeau de l’espace privé
5 décembre 2014, par tcharlss (*´_ゝ`)Sur un site nu, sans aucun plugin, le bandeau de navigation de l’espace privé reste utilisable car il y a peu d’éléments.
Par contre, dès que les menus commencent à se peupler en installant des plugins, ça devient difficile de s’y retrouver car il n’y a pas de logique de tri apparente.
Mais surtout, entre 2 sites ayant les mêmes plugins, les entrées des menus peuvent être classées différement. C’est un peu gênant pour jongler entre un site de dev et un site en ligne, cf. image en pièce-jointe.À priori et à fortiori, les entrées sont organisées de la sorte :
- D’abord les entrées des plugins du core, toujours dans le même ordre, fixé.
- Ensuite les entrées ajoutées par les plugins, et là, c’est la fête. Ils sont rangés selon la date de leur installation, peut-être ?
Bref, je propose :
- Soit de tout classer alphabétiquement
- Soit idem, tout en plaçant en premier les entrées du core (donc 2 groupes, chacun classés alphabétiquement)
Qu’en pensez-vous ?
Pour les gens curieux, les fichiers concernés sont ceux-là :
- http://core.spip.org/projects/spip/repository/entry/spip/prive/squelettes/inclure/barre-nav.html
- http://core.spip.org/projects/spip/repository/entry/spip/ecrire/inc/bandeau.php
- http://core.spip.org/projects/spip/repository/entry/spip/ecrire/inc/boutons.php
Comme je suis sympa, je mets ça en priorité « bas »