Recherche avancée

Médias (1)

Mot : - Tags -/lev manovitch

Autres articles (34)

  • Publier sur MédiaSpip

    13 juin 2013

    Puis-je poster des contenus à partir d’une tablette Ipad ?
    Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir

  • Les formats acceptés

    28 janvier 2010, par

    Les commandes suivantes permettent d’avoir des informations sur les formats et codecs gérés par l’installation local de ffmpeg :
    ffmpeg -codecs ffmpeg -formats
    Les format videos acceptés en entrée
    Cette liste est non exhaustive, elle met en exergue les principaux formats utilisés : h264 : H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 m4v : raw MPEG-4 video format flv : Flash Video (FLV) / Sorenson Spark / Sorenson H.263 Theora wmv :
    Les formats vidéos de sortie possibles
    Dans un premier temps on (...)

  • Ajouter notes et légendes aux images

    7 février 2011, par

    Pour pouvoir ajouter notes et légendes aux images, la première étape est d’installer le plugin "Légendes".
    Une fois le plugin activé, vous pouvez le configurer dans l’espace de configuration afin de modifier les droits de création / modification et de suppression des notes. Par défaut seuls les administrateurs du site peuvent ajouter des notes aux images.
    Modification lors de l’ajout d’un média
    Lors de l’ajout d’un média de type "image" un nouveau bouton apparait au dessus de la prévisualisation (...)

Sur d’autres sites (6738)

  • How do i properly setup ffmpeg and fix this "Permission Denied" error im getting ?

    8 décembre 2020, par ExaNori

    Error im getting
C:/Users/Motzumoto/Desktop/AGB/ffmpeg/bin: Permission denied

    


    I already have ffmpeg installed to path on my windows 10 machine, but that didnt fix it, so i just tried to put ffmpeg in my bots directory, that didnt do it either.
Heres my music code if anyone can help
It uses a mixture of youtube-dl and ffmpeg
If there are also any errors that would stop this from working at all it'd be nice if you could show me them, im quite tired of this as of now and im honestly just about to scrap this idea and forget about it

    


    I've tried linking the path to the ffmpeg.exe, that still didnt work, i got the same error, i have no idea what to do

    


    import asyncio
import logging
import math
from urllib import request

import discord
from discord.ext import commands
import youtube_dl
from utils.guilds import Guilds
import ffmpeg
from asyncio import run_coroutine_threadsafe as coroutine

DOWNLOAD_PATH = "audio" # download path of the file
STREAM_INDICATOR_PREFIX = "${STREAM}:"




# options
ytdl_options = {
    "quiet": True,
    "forceipv4": True,
    "noplaylist": True,
    "no_warnings": True,
    "ignoreerrors": True,
    "nooverwrites": True,
    "restrictfilenames": True,
    "nocheckcertificate": True,
    "default_search": "auto",
    "format": "bestaudio/best",
}
ffmpeg_options = {
    "options": "-vn" # indicates that we have disabled video recording in the output file
}

ytdl = youtube_dl.YoutubeDL(ytdl_options) # youtube_dl object

# checks functions
def is_connected(ctx):
    """Check if the bot is connected to a voice channel."""
    
    if ctx.voice_client:
        return True
    
    return False
def is_same_channel(ctx):
    """Check if the bot and the user is in the same channel."""
    
    # try to get their voice channel id if there's any
    try:
        bot_channel_id = ctx.voice_client.channel.id
        user_channel_id = ctx.author.voice.channel.id
    # if one of them is not connected to a voice channel then they're not together
    except AttributeError:
        return False
    
    # check if their voice channel id is the same
    if bot_channel_id == user_channel_id:
        return True
    
    return False
async def checks(ctx):
    """Do some checking."""
    
    # check if the user and the bot is in the same channel
    if not is_same_channel(ctx):
        await ctx.send("I am not with you. How dare you to command me like that.")
        return False
    
    return True

# other function
async def create_source(ctx, query):
    """Creates youtube_dl audio source for discord.py voice client."""
    
    try:
        async with ctx.typing(): # shows that the bot is typing in chat while searching for an audio source
            source = await YTDLSource.from_url(query, ctx.bot.loop) # creates a youtube_dl source
    except IndexError: # if found nothing
        await ctx.send("I found nothing with the given query..")
        return None
    
    return source

class Music(commands.Cog, name="music"):
    def __init__(self, bot):
        self.bot = bot
        self.guilds = Guilds() # collection of some guilds that this bot is currently in
    
    async def cog_command_error(self, ctx, error):
        """Catch all errors of this cog."""
        
        # a check on a command has failed
        if isinstance(error, commands.CheckFailure):
            await ctx.send("I'm not connected to any voice channel.")
        # ignore this error because it is already handled at the command itself
        elif isinstance(error, commands.errors.BadArgument):
            pass
        # otherwise, log all the other errors
        else:
            music_logger.exception(error)
            await ctx.send(error)
    
    @commands.command()
    async def join(self, ctx):
        """Invite me to your voice channel."""
        
        try:
            async with ctx.typing(): # shows that the bot is typing in chat while joining the voice channel
                await ctx.author.voice.channel.connect()
                await ctx.send("Alright, I joined your voice channel.")
        # user is not yet connected to a voice channel
        except AttributeError:
            await ctx.send(f"You must be connected to a voice channel first {ctx.author.name}.")
        # bot is already connected to a voice channel
        except discord.ClientException:
            if is_same_channel(ctx):
                await ctx.send("I'm already with you.")
            else:
                await ctx.send("I'm already with somebody else.")
    
    @commands.command()
    @commands.check(is_connected)
    async def leave(self, ctx):
        """Kick me out of your voice channel."""
        
        # do some checking before executing this command
        if not await checks(ctx):
            return
        
        # reset some bot's states
        self.guilds(ctx).has_played_voice = False # reset 'has_played_voice' state
        self.guilds(ctx).queue.clear() # reset the queue
        
        # finally, stop and disconnect the bot
        ctx.voice_client.stop() # stop the bot's voice
        await ctx.voice_client.disconnect() # disconnect the bot from voice channel
        await ctx.send("Ah, alright, cya.")
    
    async def play_source(self, ctx, vc, source):
        """Play an audio to a voice channel."""
        
        def play_next(error):
            """Executes when the voice client is done playing."""
            
            # log the errors if there is any
            if error:
                music_logger.exception(error)
                coroutine(ctx.send(error), self.bot.loop)
            
            # ensure that there is a song in queue
            if self.guilds(ctx).queue.queue:
                coroutine(ctx.invoke(self.bot.get_command("next")), self.bot.loop) # go to the next song
        
        vc.play(source, after=play_next) # play the voice to the voice channel
        await ctx.send(f"Now playing '{source.title}'.")
    
    @commands.command(aliases=("p", "stream"))
    async def play(self, ctx, *, query=""):
        """Play a song for you."""
        
        # check if the query argument is empty
        if not query:
            # if yes, cancel this command
            await ctx.send("What should I play?")
            return
        
        # check if this command is invoked using 'stream' alias
        if ctx.invoked_with == "stream":
            SIP = STREAM_INDICATOR_PREFIX # put prefix to the title of the source that indicates that it must be streamed
        else:
            SIP = ""
        
        # ensure that the bot is connected a voice channel
        try:
            # connect the bot to the user voice channel
            await ctx.author.voice.channel.connect()
        except AttributeError:
            # user is not yet connected to a voice channel
            await ctx.send(f"You must be connected to a voice channel first {ctx.author.name}.")
            return
        except discord.ClientException:
            pass # just ignore if bot is already connected to the voice channel
        
        # do some other checking before executing this command
        if not await checks(ctx):
            return
        
        # create the audio source
        source = await create_source(ctx, SIP + query)
        
        # ensure that there is actually a source
        if source:
            # initialize bot's states if the the queue is still empty
            if not self.guilds(ctx).queue.queue:
                self.guilds(ctx).has_played_voice = True # this means that the bot has played in the voice at least once
                self.guilds(ctx).queue.enqueue(SIP + source.title)
            
            # play the audio
            try:
                await self.play_source(ctx, ctx.voice_client, source)
            # enqueue the source if audio is already playing
            except discord.ClientException:
                self.guilds(ctx).queue.enqueue(SIP + source.title)
                await ctx.send(f"'{source.title}' is added to the queue.")
    
    @commands.command()
    @commands.check(is_connected)
    async def volume(self, ctx, *, vol=None):
        """Adjust my voice volume."""
        
        # do some checking before executing this command
        if not await checks(ctx):
            return
        
        vc = ctx.voice_client # get the voice client
        
        # ensure that the bot is playing voice in order to change the volume
        if not self.guilds(ctx).has_played_voice:
            await ctx.send("I haven't even started yet.")
            return
        elif vc.source is None:
            await ctx.send("I am not playing anything.")
            return
        
        # check if user has passed an argument
        if vol is None:
            await ctx.send("I expect an argument from 0 to 100.")
            return
        
        # cast string argument 'vol' into a float
        try:
            vol = float(vol)
        # except if the argument is not a number
        except ValueError:
            await ctx.send("The argument must only be a number.")
            return
        
        # set the volume
        if vol >= 0 and vol <= 100: # bound the volume from 0 to 100
            vc.source.volume = vol / 100
        else:
            await ctx.send("I expect a value from 0 to 100.")
    
    @commands.command()
    @commands.check(is_connected)
    async def pause(self, ctx):
        """Pause the song."""
        
        # do some checking before executing this command
        if not await checks(ctx):
            return
        
        vc = ctx.voice_client # get the voice client
        
        # ensure that the bot's voice is playing in order to pause
        if vc.is_playing():
            vc.pause()
            await ctx.send("Alright, paused.")
        # the bot haven't played yet
        elif not self.guilds(ctx).has_played_voice:
            await ctx.send("I haven't even started yet.")
        # there is no song in queue
        elif not self.guilds(ctx).queue.queue:
            await ctx.send("I am not playing anything.")
        else:
            await ctx.send("I already paused.")
    
    @commands.command()
    @commands.check(is_connected)
    async def resume(self, ctx):
        """Resume the song."""
        
        # do some checking before executing this command
        if not await checks(ctx):
            return
        
        vc = ctx.voice_client # get the voice client
        
        # ensure that the bot's voice is paused in order to resume
        if vc.is_paused():
            vc.resume()
            await ctx.send("Alright, song resumed")
        # the bot haven't played yet
        elif not self.guilds(ctx).has_played_voice:
            await ctx.send("I haven't even started yet.")
        # there is no song in queue
        elif not self.guilds(ctx).queue.queue:
            await ctx.send("I am not playing anything.")
        else:
            await ctx.send("I am not paused.")
    
    async def update_song(self, ctx):
        """Change the currently playing song."""
        
        vc = ctx.voice_client # get the voice client
        current = self.guilds(ctx).queue.current # get the current song in queue if there's any
        
        # ensure that the queue is not empty
        if current:
            source = await create_source(ctx, current) # create the audio source
        # the bot haven't played yet
        elif not self.guilds(ctx).has_played_voice:
            await ctx.send("I haven't even started yet.")
            return
        else:
            vc.stop() # stop the voice just to be sure
            await ctx.send("No more songs unfortunately.")
            return
        
        # if voice client is already playing, just change the source
        if vc.is_playing():
            vc.source = source
            await ctx.send(f"Now playing '{source.title}'.")
        # otherwise, play the source
        else:
            await self.play_source(ctx, vc, source)
    
    @commands.command()
    @commands.check(is_connected)
    async def next(self, ctx):
        """Skip the current song."""
        
        # do some checking before executing this command
        if not await checks(ctx):
            return
        
        self.guilds(ctx).queue.shift(1) # shift the queue to the left
        await self.update_song(ctx) # change the current song
    
    @commands.command()
    @commands.check(is_connected)
    async def prev(self, ctx):
        """Go back to the previous song."""
        
        # do some checking before executing this command
        if not await checks(ctx):
            return
        
        self.guilds(ctx).queue.shift(-1) # shift the queue to the right
        await self.update_song(ctx) # change the current song
    
    @commands.command()
    @commands.check(is_connected)
    async def removesong(self, ctx, *, index=1):
        """Remove a song in the queue."""
        
        # do some checking before executing this command
        if not await checks(ctx):
            return
        
        index -= 1 # decrement the 'index' to match the zero-based index of Python
        
        # if index is equal to 0, that means remove the currently playing song
        # do some extra stuff before removing the current song
        if index == 0:
            # try to remove a song in queue
            try:
                self.guilds(ctx).queue.dequeue() # dequeue a song in the queue
                self.guilds(ctx).queue.shift(-1) # shift the queue to the right so that the next song will be played instead of the next next song
                await ctx.invoke(self.bot.get_command("next")) # finally, play the next song
            # except when the queue is empty
            except IndexError:
                await ctx.send("I haven't even started yet.")
        # otherwise, just remove a song in queue
        else:
            # try to remove the song in queue
            try:
                self.guilds(ctx).queue.pop(index)
                await ctx.send("Song removed")
            # except if the song is not in the queue
            except IndexError:
                # check if the bot has not started playing yet
                if not self.guilds(ctx).has_played_voice:
                    await ctx.send("I haven't even started yet...")
                else:
                    await ctx.send(f"I can't remove that {ctx.author.name} because it doesn't exist.")
    @removesong.error
    async def remove_error(self, ctx, error):
        """Error handler for the 'remove' command."""
        
        # check if the argument is bad
        if isinstance(error, commands.errors.BadArgument):
            await ctx.send(f"I can't remove that {ctx.author.name}.")
            await ctx.send("The argument must only be a number or leave it none.")
    
    @commands.command()
    @commands.check(is_connected)
    async def stop(self, ctx):
        """Stop all the songs."""
        
        # do some checking before executing this command
        if not await checks(ctx):
            return
        
        vc = ctx.voice_client # get the voice client
        
        # ensure that the bot is connected to the voice client
        if vc.is_playing() or vc.is_paused():
            self.guilds(ctx).queue.clear() # reset the queue
            ctx.voice_client.stop() # stop the bot's voice
            await ctx.send("Playback stopped")
        # the bot haven't played yet
        elif not self.guilds(ctx).has_played_voice:
            await ctx.send("I haven't even started yet.")
        else:
            await ctx.send("I already stopped.")
    
    @commands.command()
    @commands.check(is_connected)
    async def queue(self, ctx):
        """Show the queue of songs."""
        
        SIP = STREAM_INDICATOR_PREFIX # shorten the variable name
        
        # do some checking before executing this command
        if not await checks(ctx):
            return
        
        # try to send the songs in the queue
        try:
            # format the queue to make it readable
            queue = [
                f"{i}." + (" (STREAM) " if q.startswith(SIP) else " ") + q.split(SIP)[-1]
                for i, q in enumerate(self.guilds(ctx).queue.queue, 1)
            ]
            
            await ctx.send("\n".join(queue))
        # except if it is empty
        except HTTPException:
            await ctx.send("No songs in queue.")

class YTDLSource(discord.PCMVolumeTransformer):
    """Creates a youtube_dl audio source with volume control."""
    
    def __init__(self, source, *, data, volume=1):
        super().__init__(source, volume)
        self.data = data
        self.title = data.get("title")
        self.url = data.get("url")
    
    @classmethod
    async def from_url(cls, url, loop):
        """Get source by URL."""
        
        # check if the URL is must be streamed
        if url.startswith(STREAM_INDICATOR_PREFIX):
            stream = True
        else:
            stream = False
        
        # get data from the given URL
        data = await loop.run_in_executor(
            None,
            (lambda:
                ytdl.extract_info(
                    url.split(STREAM_INDICATOR_PREFIX)[-1], # remove the prefix from the URL
                    download=not stream
                ))
        )
        ##$$$$ fix error somtimes
        # take the first item from the entries if there's any
        if "entries" in data:
            try:
                data = data["entries"][0]
            except Exception as e:
                music_logger.exception(e)
                return None
        
        filepath = data["url"] if stream else ytdl.prepare_filename(data) # source url or download path of the file, depends on the 'stream' parameter
        return cls(discord.FFmpegPCMAudio("C:/Users/Motzumoto/Desktop/AGB/ffmpeg/bin", **ffmpeg_options), data=data) # create and return the source

def setup(bot):
    bot.add_cog(Music(bot))



    


  • Using ffmpeg to trim video : correct duration, but output file size too large

    28 novembre 2022, par ddessert

    I have a digitized 8mm 16fps .mp4 that I'm trying to split into clips using ffmpeg (5.1.2) on MacOS terminal. The output file trims to the correct duration but the filesize is too large.

    


    ffmpeg -ss 05:09 -i input.mp4 -t 02:19 -an -sn -dn -c copy output.mp4


    


    input.mp4 : 11:56 in duration and 8.24 GB in filesize (bitrate 674251 kbits/s).
    
output.mp4 : 02:19 in duration and 5.15 GB in filesize (too large).

    


    5.15 GB is the filesize I'd expect for a clip that is 05:09 + 02:19 in duration at input.mp4's 674251 Kbits/s :
    
(05:09+02:19) * 674251 kbits/sec = 5.16 GB

    


    I've tried various -ss start_pos and -t duration values with similar results. The output file is correctly duration in time and unexpectedly (start_pos+duration)*bitrate in filesize.

    


    I've consulted this ShotStack.io article on trimming with ffmpeg and this ffmpeg wiki section on cutting small sections from files. Neither specifically states that the resulting file size will be trimmed to match the duration of the clip, but I'd think that'd be useful.

    


    ffmpeg stdout :

    


    [mov,mp4,m4a,3gp,3g2,mj2 @ 0x14ff04760] Using non-standard frame rate 16384/1024
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    creation_time   : 2021-07-24T11:23:44.000000Z
    encoder         : Lavf58.45.100
  Duration: 00:11:56.13, start: 0.000000, bitrate: 92041 kb/s
  Stream #0:0[0x1](und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, bt709/bt709/unknown, progressive), 5120x3840 [SAR 1:1 DAR 4:3], 91715 kb/s, 16 fps, 16 tbr, 16384 tbn (default)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      timecode        : 17:15:11:05
  Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 159 kb/s (default)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:2[0x3](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 159 kb/s (default)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:3[0x4](eng): Data: none (tmcd / 0x64636D74)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : TimeCodeHandler
      timecode        : 17:15:11:05
File 'output.mp4' already exists. Overwrite? [y/N] y
[mp4 @ 0x14ff08660] Using non-standard frame rate 16/1
    Last message repeated 1 times
Output #0, mp4, to 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf59.27.100
  Stream #0:0(und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, bt709/bt709/unknown, progressive), 5120x3840 [SAR 1:1 DAR 4:3], q=2-31, 91715 kb/s, 16 fps, 16 tbr, 16384 tbn (default)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      timecode        : 17:15:11:05
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame= 4290 fps=0.0 q=-1.0 Lsize= 2988507kB time=00:02:18.93 bitrate=176207.6kbits/s speed= 189x    
video:2988420kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.002924%


    


    ffprobe output.mp4

    


    [mov,mp4,m4a,3gp,3g2,mj2 @ 0x130804080] Using non-standard frame rate 16384/1024
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf59.27.100
  Duration: 00:02:19.31, start: 0.000000, bitrate: 175732 kb/s
  Stream #0:0[0x1](und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, bt709/bt709/unknown, progressive), 5120x3840 [SAR 1:1 DAR 4:3], 91304 kb/s, 16 fps, 16 tbr, 16384 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      timecode        : 17:15:11:05
  Stream #0:1[0x2](eng): Data: none (tmcd / 0x64636D74)
    Metadata:
      handler_name    : VideoHandler
      timecode        : 17:15:11:05
Unsupported codec with id 0 for input stream 1


    


  • Beware the builtins

    14 janvier 2010, par Mans — Compilers

    GCC includes a large number of builtin functions allegedly providing optimised code for common operations not easily expressed directly in C. Rather than taking such claims at face value (this is GCC after all), I decided to conduct a small investigation to see how well a few of these functions are actually implemented for various targets.

    For my test, I selected the following functions :

    • __builtin_bswap32 : Byte-swap a 32-bit word.
    • __builtin_bswap64 : Byte-swap a 64-bit word.
    • __builtin_clz : Count leading zeros in a word.
    • __builtin_ctz : Count trailing zeros in a word.
    • __builtin_prefetch : Prefetch data into cache.

    To test the quality of these builtins, I wrapped each in a normal function, then compiled the code for these targets :

    • ARMv7
    • AVR32
    • MIPS
    • MIPS64
    • PowerPC
    • PowerPC64
    • x86
    • x86_64

    In all cases I used compiler flags were -O3 -fomit-frame-pointer plus any flags required to select a modern CPU model.

    ARM

    Both __builtin_clz and __builtin_prefetch generate the expected CLZ and PLD instructions respectively. The code for __builtin_ctz is reasonable for ARMv6 and earlier :

    rsb     r3, r0, #0
    and     r0, r3, r0
    clz     r0, r0
    rsb     r0, r0, #31
    

    For ARMv7 (in fact v6T2), however, using the new bit-reversal instruction would have been better :

    rbit    r0, r0
    clz     r0, r0
    

    I suspect this is simply a matter of the function not yet having been updated for ARMv7, which is perhaps even excusable given the relatively rare use cases for it.

    The byte-reversal functions are where it gets shocking. Rather than use the REV instruction found from ARMv6 on, both of them generate external calls to __bswapsi2 and __bswapdi2 in libgcc, which is plain C code :

    SItype
    __bswapsi2 (SItype u)
    
      return ((((u) & 0xff000000) >> 24)
              | (((u) & 0x00ff0000) >>  8)
              | (((u) & 0x0000ff00) <<  8)
              | (((u) & 0x000000ff) << 24)) ;
    
    

    DItype
    __bswapdi2 (DItype u)

    return ((((u) & 0xff00000000000000ull) >> 56)
    | (((u) & 0x00ff000000000000ull) >> 40)
    | (((u) & 0x0000ff0000000000ull) >> 24)
    | (((u) & 0x000000ff00000000ull) >> 8)
    | (((u) & 0x00000000ff000000ull) << 8)
    | (((u) & 0x0000000000ff0000ull) << 24)
    | (((u) & 0x000000000000ff00ull) << 40)
    | (((u) & 0x00000000000000ffull) << 56)) ;

    While the 32-bit version compiles to a reasonable-looking shift/mask/or job, the 64-bit one is a real WTF. Brace yourselves :

    push    r4, r5, r6, r7, r8, r9, sl, fp
    mov     r5, #0
    mov     r6, #65280 ; 0xff00
    sub     sp, sp, #40 ; 0x28
    and     r7, r0, r5
    and     r8, r1, r6
    str     r7, [sp, #8]
    str     r8, [sp, #12]
    mov     r9, #0
    mov     r4, r1
    and     r5, r0, r9
    mov     sl, #255 ; 0xff
    ldr     r9, [sp, #8]
    and     r6, r4, sl
    mov     ip, #16711680 ; 0xff0000
    str     r5, [sp, #16]
    str     r6, [sp, #20]
    lsl     r2, r0, #24
    and     ip, ip, r1
    lsr     r7, r4, #24
    mov     r1, #0
    lsr     r5, r9, #24
    mov     sl, #0
    mov     r9, #-16777216 ; 0xff000000
    and     fp, r0, r9
    lsr     r6, ip, #8
    orr     r9, r7, r1
    and     ip, r4, sl
    orr     sl, r1, r2
    str     r6, [sp]
    str     r9, [sp, #32]
    str     sl, [sp, #36] ; 0x24
    add     r8, sp, #32
    ldm     r8, r7, r8
    str     r1, [sp, #4]
    ldm     sp, r9, sl
    orr     r7, r7, r9
    orr     r8, r8, sl
    str     r7, [sp, #32]
    str     r8, [sp, #36] ; 0x24
    mov     r3, r0
    mov     r7, #16711680 ; 0xff0000
    mov     r8, #0
    and     r9, r3, r7
    and     sl, r4, r8
    ldr     r0, [sp, #16]
    str     fp, [sp, #24]
    str     ip, [sp, #28]
    stm     sp, r9, sl
    ldr     r7, [sp, #20]
    ldr     sl, [sp, #12]
    ldr     fp, [sp, #12]
    ldr     r8, [sp, #28]
    lsr     r0, r0, #8
    orr     r7, r0, r7, lsl #24
    lsr     r6, sl, #24
    orr     r5, r5, fp, lsl #8
    lsl     sl, r8, #8
    mov     fp, r7
    add     r8, sp, #32
    ldm     r8, r7, r8
    orr     r6, r6, r8
    ldr     r8, [sp, #20]
    ldr     r0, [sp, #24]
    orr     r5, r5, r7
    lsr     r8, r8, #8
    orr     sl, sl, r0, lsr #24
    mov     ip, r8
    ldr     r0, [sp, #4]
    orr     fp, fp, r5
    ldr     r5, [sp, #24]
    orr     ip, ip, r6
    ldr     r6, [sp]
    lsl     r9, r5, #8
    lsl     r8, r0, #24
    orr     fp, fp, r9
    lsl     r3, r3, #8
    orr     r8, r8, r6, lsr #8
    orr     ip, ip, sl
    lsl     r7, r6, #24
    and     r5, r3, #16711680 ; 0xff0000
    orr     r7, r7, fp
    orr     r8, r8, ip
    orr     r4, r1, r7
    orr     r5, r5, r8
    mov     r9, r6
    mov     r1, r5
    mov     r0, r4
    add     sp, sp, #40 ; 0x28
    pop     r4, r5, r6, r7, r8, r9, sl, fp
    bx      lr
    

    That’s right, 91 instructions to move 8 bytes around a bit. GCC definitely has a problem with 64-bit numbers. It is perhaps worth noting that the bswap_64 macro in glibc splits the 64-bit value into 32-bit halves which are then reversed independently, thus side-stepping this weakness of gcc.

    As a side note, ARM RVCT (armcc) compiles those functions perfectly into one and two REV instructions, respectively.

    AVR32

    There is not much to report here. The latest gcc version available is 4.2.4, which doesn’t appear to have the bswap functions. The other three are handled nicely, even using a bit-reverse for __builtin_ctz.

    MIPS / MIPS64

    The situation MIPS is similar to ARM. Both bswap builtins result in external libgcc calls, the rest giving sensible code.

    PowerPC

    I scarcely believe my eyes, but this one is actually not bad. The PowerPC has no byte-reversal instructions, yet someone seems to have taken the time to teach gcc a good instruction sequence for this operation. The PowerPC does have some powerful rotate-and-mask instructions which come in handy here. First the 32-bit version :

    rotlwi  r0,r3,8
    rlwimi  r0,r3,24,0,7
    rlwimi  r0,r3,24,16,23
    mr      r3,r0
    blr
    

    The 64-bit byte-reversal simply applies the above code on each half of the value :

    rotlwi  r0,r3,8
    rlwimi  r0,r3,24,0,7
    rlwimi  r0,r3,24,16,23
    rotlwi  r3,r4,8
    rlwimi  r3,r4,24,0,7
    rlwimi  r3,r4,24,16,23
    mr      r4,r0
    blr
    

    Although I haven’t analysed that code carefully, it looks pretty good.

    PowerPC64

    Doing 64-bit operations is easier on a 64-bit CPU, right ? For you and me perhaps, but not for gcc. Here __builtin_bswap64 gives us the now familiar __bswapdi2 call, and while not as bad as the ARM version, it is not pretty :

    rldicr  r0,r3,8,55
    rldicr  r10,r3,56,7
    rldicr  r0,r0,56,15
    rldicl  r11,r3,8,56
    rldicr  r9,r3,16,47
    or      r11,r10,r11
    rldicr  r9,r9,48,23
    rldicl  r10,r0,24,40
    rldicr  r0,r3,24,39
    or      r11,r11,r10
    rldicl  r9,r9,40,24
    rldicr  r0,r0,40,31
    or      r9,r11,r9
    rlwinm  r10,r3,0,0,7
    rldicl  r0,r0,56,8
    or      r0,r9,r0
    rldicr  r10,r10,8,55
    rlwinm  r11,r3,0,8,15
    or      r0,r0,r10
    rldicr  r11,r11,24,39
    rlwinm  r3,r3,0,16,23
    or      r0,r0,r11
    rldicr  r3,r3,40,23
    or      r3,r0,r3
    blr
    

    That is 6 times longer than the (presumably) hand-written 32-bit version.

    x86 / x86_64

    As one might expect, results on x86 are good. All the tested functions use the available special instructions. One word of caution though : the bit-counting instructions are very slow on some implementations, specifically the Atom, AMD chips, and the notoriously slow Pentium4E.

    Conclusion

    In conclusion, I would say gcc builtins can be useful to avoid fragile inline assembler. Before using them, however, one should make sure they are not in fact harmful on the required targets. Not even those builtins mapping directly to CPU instructions can be trusted.