Recherche avancée

Médias (2)

Mot : - Tags -/plugins

Autres articles (58)

  • La file d’attente de SPIPmotion

    28 novembre 2010, par

    Une file d’attente stockée dans la base de donnée
    Lors de son installation, SPIPmotion crée une nouvelle table dans la base de donnée intitulée spip_spipmotion_attentes.
    Cette nouvelle table est constituée des champs suivants : id_spipmotion_attente, l’identifiant numérique unique de la tâche à traiter ; id_document, l’identifiant numérique du document original à encoder ; id_objet l’identifiant unique de l’objet auquel le document encodé devra être attaché automatiquement ; objet, le type d’objet auquel (...)

  • Les autorisations surchargées par les plugins

    27 avril 2010, par

    Mediaspip core
    autoriser_auteur_modifier() afin que les visiteurs soient capables de modifier leurs informations sur la page d’auteurs

  • Demande de création d’un canal

    12 mars 2010, par

    En fonction de la configuration de la plateforme, l’utilisateur peu avoir à sa disposition deux méthodes différentes de demande de création de canal. La première est au moment de son inscription, la seconde, après son inscription en remplissant un formulaire de demande.
    Les deux manières demandent les mêmes choses fonctionnent à peu près de la même manière, le futur utilisateur doit remplir une série de champ de formulaire permettant tout d’abord aux administrateurs d’avoir des informations quant à (...)

Sur d’autres sites (5494)

  • How can I increase the performance of this video watermarking call which seems to be only using 6% of my system's CPU ? Currently using ffmpeg

    24 août 2023, par Codemonkey

    I have a php script to add a watermark to an uploaded video, using ffmpeg

    


    shell_exec("ffmpeg -y -i input.mp4 -i watermark.png -filter_complex $filter output.mp4")


    


    The video is 36 seconds long, 33MB and 1080x1920, 24fps. The output video comes in at 8MB, scaled down to 540x960 with a PNG overlaid as a watermark.

    


    The script takes about 3 seconds, averaging 320fps or so. For a one-off this would be ok, but I'm going to be processing hundreds/thousands of these at a time.

    


    I have 128GB of ram and an EPYC 7502p (32cores/64threads), and both input and output files are on NVMe drives.

    


    If I monitor top showing all my cores/threads in another window, with refresh delay set to a variety of things from 0.1 to 2 seconds, I'd guesstimate that this hits about 1/4 of my available threads, at about 25% utilisation each.

    


    So it kind of feels like I COULD see a 16x speed increase if it hit all of them at 100%. That actually wouldn't be ideal, locking up the server of course, but when my CPU is sat at 99% idle 99% of the time, I feel it could do better - it'd be nice to see it hitting at least half the cores or utilising at least 50% of them when it does...

    


    So, is there anything I can change with ffmpeg's config/build or the way I call it ? If this is as good as ffmpeg can do, are there better tools for the job ?

    


    Thank you

    



    


    EDIT :

    


    A few things I've learnt since posting :

    


      

    • -c:v libx264 -preset ultrafast - marginal help
    • 


    • nice -n -10 - marginal help (changing to -20 is makes negligible difference)
    • 


    • -c:a copy - significant help, which I found surprising
    • 


    


    FPS up from 320 to 540 using those 3 combined. I still feel there should be significantly more gains somewhere though...

    



    


    Here's the output from the original script, if it helps :

    


    ffmpeg version 4.2.9 Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 8 (GCC)
  configuration: --prefix=/usr --bindir=/usr/bin --datadir=/usr/share/ffmpeg --docdir=/usr/share/doc/ffmpeg --incdir=/usr/include/ffmpeg --libdir=/usr/lib64 --mandir=/usr/share/man --arch=x86_64 --optflags='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' --extra-ldflags='-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld ' --extra-cflags=' ' --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-version3 --enable-bzlib --disable-crystalhd --enable-fontconfig --enable-frei0r --enable-gcrypt --enable-gnutls --enable-ladspa --enable-libaom --enable-libdav1d --enable-libass --enable-libbluray --enable-libcdio --enable-libdrm --enable-libjack --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libmp3lame --enable-nvenc --enable-openal --enable-opencl --enable-opengl --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librsvg --enable-libsrt --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libvorbis --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-version3 --enable-vapoursynth --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-libzimg --enable-libzvbi --enable-avfilter --enable-avresample --enable-libmodplug --enable-postproc --enable-pthreads --disable-static --enable-shared --enable-gpl --disable-debug --disable-stripping --shlibdir=/usr/lib64 --enable-libmfx --enable-runtime-cpudetect
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Metadata:
    major_brand     : M4V
    minor_version   : 1
    compatible_brands: isomavc1mp42
    creation_time   : 2023-07-03T14:55:37.000000Z
  Duration: 00:00:36.50, start: 0.000000, bitrate: 7315 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/unknown), 1080x1920 [SAR 1:1 DAR 9:16], 7213 kb/s, 24 fps, 24 tbr, 24k tbn, 48 tbc (default)
    Metadata:
      creation_time   : 2023-07-03T14:55:37.000000Z
      handler_name    : ETI ISO Video Media Handler
      encoder         : Elemental H.264
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 96 kb/s (default)
    Metadata:
      creation_time   : 2023-07-03T14:55:37.000000Z
      handler_name    : ETI ISO Audio Media Handler
Input #1, png_pipe, from 'watermark.png':
  Duration: N/A, bitrate: N/A
    Stream #1:0: Video: png, rgba(pc), 1232x804 [SAR 11811:11811 DAR 308:201], 25 tbr, 25 tbn, 25 tbc
Stream mapping:
  Stream #0:0 (h264) -> scale (graph 0)
  Stream #1:0 (png) -> scale (graph 0)
  overlay (graph 0) -> Stream #0:0 (libx264)
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
[libx264 @ 0x56510d488e00] using SAR=1/1
[libx264 @ 0x56510d488e00] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 0x56510d488e00] profile High, level 3.1, 4:2:0, 8-bit
[libx264 @ 0x56510d488e00] 264 - core 157 r2980 34c06d1 - H.264/MPEG-4 AVC codec - Copyleft 2003-2019 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=30 lookahead_threads=5 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=24 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'output.mp4':
  Metadata:
    major_brand     : M4V
    minor_version   : 1
    compatible_brands: isomavc1mp42
    encoder         : Lavf58.29.100
    Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 540x960 [SAR 1:1 DAR 9:16], q=-1--1, 24 fps, 12288 tbn, 24 tbc (default)
    Metadata:
      encoder         : Lavc58.54.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      creation_time   : 2023-07-03T14:55:37.000000Z
      handler_name    : ETI ISO Audio Media Handler
      encoder         : Lavc58.54.100 aac
frame=  876 fps=324 q=-1.0 Lsize=    7768kB time=00:00:36.45 bitrate=1745.5kbits/s speed=13.5x
video:7177kB audio:566kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.336181%
[libx264 @ 0x56510d488e00] frame I:9     Avg QP:21.46  size: 37765
[libx264 @ 0x56510d488e00] frame P:237   Avg QP:23.78  size: 17862
[libx264 @ 0x56510d488e00] frame B:630   Avg QP:28.03  size:  4405
[libx264 @ 0x56510d488e00] consecutive B-frames:  2.9%  2.5%  3.8% 90.9%
[libx264 @ 0x56510d488e00] mb I  I16..4: 13.6% 65.9% 20.5%
[libx264 @ 0x56510d488e00] mb P  I16..4:  5.2% 16.6%  4.1%  P16..4: 32.8% 18.0% 12.5%  0.0%  0.0%    skip:10.8%
[libx264 @ 0x56510d488e00] mb B  I16..4:  1.1%  2.7%  0.2%  B16..8: 35.3%  7.2%  2.5%  direct: 3.3%  skip:47.7%  L0:37.0% L1:52.2% BI:10.8%
[libx264 @ 0x56510d488e00] 8x8 transform intra:65.0% inter:71.5%
[libx264 @ 0x56510d488e00] coded y,uvDC,uvAC intra: 54.7% 62.1% 11.5% inter: 17.9% 12.9% 0.5%
[libx264 @ 0x56510d488e00] i16 v,h,dc,p: 16% 28%  8% 47%
[libx264 @ 0x56510d488e00] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 21% 23% 18%  6%  6%  7%  7%  7%  7%
[libx264 @ 0x56510d488e00] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 23% 16% 11%  7%  9% 10%  8%  8%  8%
[libx264 @ 0x56510d488e00] i8c dc,h,v,p: 55% 20% 20%  5%
[libx264 @ 0x56510d488e00] Weighted P-Frames: Y:5.5% UV:3.4%
[libx264 @ 0x56510d488e00] ref P L0: 65.0% 18.8% 13.0%  3.0%  0.2%
[libx264 @ 0x56510d488e00] ref B L0: 95.0%  4.0%  1.1%
[libx264 @ 0x56510d488e00] ref B L1: 98.2%  1.8%
[libx264 @ 0x56510d488e00] kb/s:1610.57
[aac @ 0x56510d4865c0] Qavg: 22331.562


    


  • ffmpeg command to add moving text watermark to video [closed]

    13 octobre 2023, par Imran Khan
    

    

            // Constants for watermark movement, direction change intervals, fade intervals, and overlap duration
        const MOVE_SPEED = 3;
        const DIRECTION_CHANGE_MIN = 3000;
        const DIRECTION_CHANGE_MAX = 6000;
        const FADE_INTERVAL_MIN = 10000;
        const FADE_INTERVAL_MAX = 20000;
        const OVERLAP_DURATION = 2000;

        // Get references to the video container and watermarks
        const container = document.querySelector('.video-container');
        const watermark1 = document.getElementById('watermark1');
        const watermark2 = document.getElementById('watermark2');

        // Helper function to get a random integer between min and max (inclusive)
        function getRandomInt(min, max) {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        }

        // Helper function to get a random direction (either 1 or -1)
        function getRandomDirection() {
            return Math.random() > 0.5 ? 1 : -1;
        }

        // Set the initial position of the watermark inside the video container
        function setInitialPosition(watermark) {
            const x = getRandomInt(0, container.offsetWidth - watermark.offsetWidth);
            const y = getRandomInt(0, container.offsetHeight - watermark.offsetHeight);
            watermark.style.left = `${x}px`;
            watermark.style.top = `${y}px`;
            watermark.style.opacity = 1;
        }

        // Function to handle continuous movement of the watermark
        function continuousMove(watermark) {
            let dx = getRandomDirection() * MOVE_SPEED;
            let dy = getRandomDirection() * MOVE_SPEED;

            // Inner function to handle the actual movement logic
            function move() {
                let x = parseInt(watermark.style.left || 0) + dx;
                let y = parseInt(watermark.style.top || 0) + dy;

                // Check boundaries and reverse direction if necessary
                if (x < 0 || x > container.offsetWidth - watermark.offsetWidth) {
                    dx = -dx;
                }
                if (y < 0 || y > container.offsetHeight - watermark.offsetHeight) {
                    dy = -dy;
                }

                // Apply the new position
                watermark.style.left = `${x}px`;
                watermark.style.top = `${y}px`;

                // Continue moving
                setTimeout(move, 100);
            }

            move();

            // Change direction at random intervals
            setInterval(() => {
                const randomChoice = Math.random();
                if (randomChoice < 0.33) {
                    dx = getRandomDirection() * MOVE_SPEED;
                    dy = 0;
                } else if (randomChoice < 0.66) {
                    dy = getRandomDirection() * MOVE_SPEED;
                    dx = 0;
                } else {
                    dx = getRandomDirection() * MOVE_SPEED;
                    dy = getRandomDirection() * MOVE_SPEED;
                }
            }, getRandomInt(DIRECTION_CHANGE_MIN, DIRECTION_CHANGE_MAX));
        }

        // Handle the fading out of the old watermark and fading in of the new watermark
        function fadeOutAndIn(oldWatermark, newWatermark) {
            setTimeout(() => {
                setInitialPosition(newWatermark);
                newWatermark.style.opacity = 1;
            }, 0);

            setTimeout(() => {
                oldWatermark.style.opacity = 0;
            }, OVERLAP_DURATION);

            // Continue the cycle
            setTimeout(() => fadeOutAndIn(newWatermark, oldWatermark), getRandomInt(FADE_INTERVAL_MIN, FADE_INTERVAL_MAX));
        }

        // Initialize the watermarks
        setInitialPosition(watermark1);
        continuousMove(watermark1);
        setTimeout(() => fadeOutAndIn(watermark1, watermark2), getRandomInt(FADE_INTERVAL_MIN, FADE_INTERVAL_MAX));
        continuousMove(watermark2);
    

    


    body, html {
            height: 100%;
            margin: 0;
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #eee;
        }

        .video-container {
            width: 50vw;
            height: 50vh;
            background-color: black;
            position: relative;
            overflow: hidden;
        }

        .watermark {
            font-size: 22px;
            position: absolute;
            color: white;
            opacity: 0;
            transition: opacity 2s;
        }

    


    &#xA;&#xA;&#xA;    &#xA;    &#xA;    &#xA;&#xA;&#xA;    <div class="video-container">&#xA;        <span class="watermark">watermark</span>&#xA;        <span class="watermark">watermark</span>&#xA;    </div>&#xA;    &#xA;&#xA;

    &#xD;&#xA;

    &#xD;&#xA;

    &#xD;&#xA;&#xA;

    I am trying to achieve an animation effect using ffmpeg. I am adding text watermark to an input video and animate the text diagonally, horizontally or vertically changed randomly. Here is what I have achieved so far.

    &#xA;

    ffmpeg -i video.mp4 -c:v libx264 -preset veryfast -crf 25 -tune zerolatency -vendor ap10 -pix_fmt yuv420p -filter:v "drawtext=fontfile=./fonts/Roboto/Roboto-Light.ttf:text=&#x27;Watermark&#x27;:fontcolor=white:alpha=0.5:fontsize=60:y=h/10*mod(t\,10):x=w/10*mod(t\,10):enable=1" -c:a copy watermark.mp4

    &#xA;

    Here is what I want it to work.

    &#xA;

    Initial Position :&#xA;The watermark randomly placed in the video the first time they appear.

    &#xA;

    Continuous Movement :&#xA;The watermark continuously moves within the video.&#xA;The direction and speed of the watermark's movement are random. It can move diagonally, purely horizontally, or purely vertically.&#xA;When the watermark reaches the boundaries of the video, it bounces back, changing its direction.

    &#xA;

    Direction Change :&#xA;During its continuous movement, the watermark will suddenly change its direction at random intervals between 3 to 6 seconds.&#xA;When changing direction, the watermark can randomly determined move diagonally, purely horizontally, or purely vertically.

    &#xA;

    Fade In and Out :&#xA;Every 10 to 20 seconds (randomly determined), the current watermark begins to fade out.&#xA;As the old watermark starts to fade out, a new watermark fades in at a random position, ensuring that there's always a visible watermark on the screen.&#xA;These two watermarks (the fading old one and the emerging new one) overlap on the screen for a duration of 2 seconds, after which the old watermark completely disappears.&#xA;These patterns and characteristics together provide a dynamic, constantly moving, and changing watermark for the video

    &#xA;

    To achieve the result I think we can use the drawtext multiple times. I have attached the HTML and JavaScript variant just for the reference to understand the result but I am trying to do this using ffmpeg.

    &#xA;

  • Getting Error during executin native android code

    3 avril 2013, par dilipkaklotar

    Error on my console

    bash : cannot set terminal process group (-1) : Inappropriate ioctl for device
    bash : no job control in this shell
    Your group is currently "mkpasswd". This indicates that your
    gid is not in /etc/group and your uid is not in /etc/passwd.

    The /etc/passwd (and possibly /etc/group) files should be rebuilt.
    See the man pages for mkpasswd and mkgroup then, for example, run

    mkpasswd -l [-d] > /etc/passwd
    mkgroup -l [-d] > /etc/group

    Note that the -d switch is necessary for domain users.
    - ]0 ; -
    - [32mDILIP@DILIP-PC -[33m -[0m
    $

    public class VideoBrowser extends ListActivity implements ListView.OnScrollListener {

    /*this part communicates with native code through jni (java native interface)*/
    //load the native library
    static {
       System.loadLibrary("ffmpeg");
       System.loadLibrary("ffmpeg-test-jni");
    }
    //declare the jni functions
    private static native void naInit(String _videoFileName);
    private static native int[] naGetVideoResolution();
    private static native String naGetVideoCodecName();
    private static native String naGetVideoFormatName();
    private static native void naClose();

    private void showVideoInfo(final File _file) {
       String videoFilename = _file.getAbsolutePath();
       naInit(videoFilename);
       int[] prVideoRes = naGetVideoResolution();
       String prVideoCodecName = naGetVideoCodecName();
       String prVideoFormatName = naGetVideoFormatName();
       naClose();
       String displayText = "Video: " + videoFilename + "\n";
       displayText += "Video Resolution: " + prVideoRes[0] + "x" + prVideoRes[1] + "\n";
       displayText += "Video Codec: " + prVideoCodecName + "\n";
       displayText += "Video Format: " + prVideoFormatName + "\n";
       text_titlebar_text.setText(displayText);
    }


    /*the rest of the file deals with UI and other stuff*/
    private Context mContext;
    public static VideoBrowser self;

    /**
    * activity life cycle: this part of the source code deals with activity life cycle
    */
    @Override
    public void onCreate(Bundle icicle) {
       super.onCreate(icicle);
       mContext = this.getApplicationContext();
       self = this;
       initUI();
    }

    @Override
    protected void onDestroy() {
       super.onDestroy();
       unbindDisplayEntries();
    }

    public void unbindDisplayEntries() {
       if (displayEntries!=null) {
           int l_count = displayEntries.size();
           for (int i = 0; i &lt; l_count; ++i) {
               IconifiedTextSelected l_its = displayEntries.get(i);
               if (l_its != null) {
                   Drawable l_dr = l_its.getIcon();
                   if (l_dr != null) {
                       l_dr.setCallback(null);
                       l_dr = null;
                   }
               }
           }
       }
       if (l_displayEntries!=null) {
           int l_count = l_displayEntries.size();
           for (int i = 0; i &lt; l_count; ++i) {
               IconifiedTextSelected l_its = l_displayEntries.get(i);
               if (l_its != null) {
                   Drawable l_dr = l_its.getIcon();
                   if (l_dr != null) {
                       l_dr.setCallback(null);
                       l_dr = null;
                   }
               }
           }
       }
    }

    /**
    * Data: this part of the code deals with data processing
    */
    public List<iconifiedtextselected> displayEntries = new ArrayList<iconifiedtextselected>();
    public static List<iconifiedtextselected> l_displayEntries = new ArrayList<iconifiedtextselected>();;

    /**load images
    * this part of code deals with loading of images
    */
    private File currentDirectory;
    public int media_browser_load_option = 2;
    private static int last_media_browser_load_option = 2;
    private static int number_of_icons = 0;
    private static final String upOneLevel = "..";

    LoadVideoTask loadTask;
    private void loadVideosFromDirectory(String _dir) {
       try {
           loadTask = new LoadVideoTask();
           loadTask.execute(_dir);
       } catch (Exception e) {
           Toast.makeText(this, "Load media fail!", Toast.LENGTH_SHORT).show();
       }
    }

    private void getVideosFromDirectoryNonRecurAddParent(File _dir) {
       //add the upper one level data
       if (_dir.getParent()!=null) {
           this.displayEntries.add(new IconifiedTextSelected(
                   upOneLevel,
                   getResources().getDrawable(R.drawable.folderback),
                   false, false, 0));
       }
    }

    private void getVideosFromDirectoryNonRecur(File _dir) {
       Drawable folderIcon = this.getResources().getDrawable(R.drawable.normalfolder);
       //add the
       if (!_dir.isDirectory()) {
           return;
       }
       File[] files = _dir.listFiles();
       if (files == null) {
           return;
       }
       Drawable videoIcon = null;
       int l_iconType = 0;
       for (File currentFile : files) {
           if (currentFile.isDirectory()) {
               //if it&#39;s a directory
               this.displayEntries.add(new IconifiedTextSelected(
                       currentFile.getPath(),
                       folderIcon, false, false, 0));
           } else {
               String l_filename = currentFile.getName();
               if (checkEndsWithInStringArray(l_filename,
                           getResources().getStringArray(R.array.fileEndingVideo))) {
                   if (number_of_icons &lt; 10) {
                       videoIcon = null;
                       ++number_of_icons;
                       l_iconType = 22;
                   } else {
                       videoIcon = null;
                       l_iconType = 2;
                   }
                   this.displayEntries.add(new IconifiedTextSelected(
                           currentFile.getPath(),
                           videoIcon, false, false, l_iconType));
               }
           }
       }
    }

    private void getVideosFromDirectoryRecur(File _dir) {
       Drawable videoIcon = null;
       File[] files = _dir.listFiles();
       int l_iconType = 2;
       if (files == null) {
           return;
       }
       for (File currentFile : files) {
           if (currentFile.isDirectory()) {
               getVideosFromDirectoryRecur(currentFile);
               continue;
           } else {
               String l_filename = currentFile.getName();
               //if it&#39;s an image file
               if (checkEndsWithInStringArray(l_filename,
                       getResources().getStringArray(R.array.fileEndingVideo))) {
                   if (number_of_icons &lt; 10) {
                       videoIcon = null;
                       ++number_of_icons;
                       l_iconType = 22;
                   } else {
                       videoIcon = null;
                       l_iconType = 2;
                   }
                   this.displayEntries.add(new IconifiedTextSelected(
                           currentFile.getPath(),
                           videoIcon, false, false, l_iconType));
               }
           }
       }
    }

    private void getVideosFromGallery() {
       Drawable videoIcon = null;
       Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
       String[] projection = {MediaStore.Video.Media.DATA};
       Cursor l_cursor = this.managedQuery(uri, projection, null, null, null);
       int videoNameColumnIndex;
       String videoFilename;
       File videoFile;
       int l_iconType = 2;
       if (l_cursor!=null) {
           if (l_cursor.moveToFirst()) {
               do {
                   videoNameColumnIndex = l_cursor.getColumnIndexOrThrow(
                           MediaStore.Images.Media.DATA);
                   videoFilename = l_cursor.getString(videoNameColumnIndex);
                   videoFile = new File(videoFilename);
                   if (!videoFile.exists()) {
                       continue;
                   }
                   if (number_of_icons &lt;= 10) {
                       videoIcon = null;
                       ++number_of_icons;
                       l_iconType = 22;
                   } else {
                       videoIcon = null;
                       l_iconType = 2;
                   }
                   this.displayEntries.add(new IconifiedTextSelected(
                           videoFile.getAbsolutePath(),
                           videoIcon, false, false, l_iconType));
               } while (l_cursor.moveToNext());
           }
       }
       if (l_cursor!=null) {
           l_cursor.close();
       }
    }

    private boolean checkEndsWithInStringArray(String checkItsEnd,
           String[] fileEndings){
       for(String aEnd : fileEndings){
           if(checkItsEnd.endsWith(aEnd))
               return true;
       }
       return false;
    }

    private class LoadVideoTask extends AsyncTask {
       @Override
       protected void onPreExecute() {
           System.gc();
           displayEntries.clear();
           showDialog(DIALOG_LOAD_MEDIA);
       }
       @Override
       protected Void doInBackground(String... params) {
           File l_root = new File(params[0]);
           if (l_root.isDirectory()) {
               number_of_icons = 0;
               currentDirectory = l_root;
               if (media_browser_load_option == 0) {
                   //list all videos in the root directory without going into sub folder
                   getVideosFromDirectoryNonRecurAddParent(l_root);
                   getVideosFromDirectoryNonRecur(l_root);
               } else if (media_browser_load_option == 1) {
                   //list all videos in the root folder recursively
                   getVideosFromDirectoryRecur(l_root);
               } else if (media_browser_load_option == 2) {
                   //list all videos in the gallery
                   getVideosFromGallery();
               }
           }
           return null;
       }
       @Override
       protected void onPostExecute(Void n) {
           refreshUI();
           dismissDialog(DIALOG_LOAD_MEDIA);
       }
    }

    /**
    * UI: this part of the source code deals with UI
    */
    //bottom menu
    private int currentFocusedBtn = 1;
    private Button btn_bottommenu1;
    private Button btn_bottommenu2;
    private Button btn_bottommenu3;
    //private Button btn_bottommenu4;
    //title bar
    private TextView text_titlebar_text;

    private void initUI() {
       this.requestWindowFeature(Window.FEATURE_NO_TITLE);
       this.setContentView(R.layout.video_browser);
       //title bar
       text_titlebar_text = (TextView) findViewById(R.id.titlebar_text);
       text_titlebar_text.setText("Click a video to display info");

       //bottom menu
       int l_btnWidth = this.getWindowManager().getDefaultDisplay().getWidth()/4;
       btn_bottommenu1 = (Button) findViewById(R.id.video_browser_btn1);
       //btn_bottommenu1 = (ActionMenuButton) findViewById(R.id.main_topsecretimport_btn1);
       btn_bottommenu1.setWidth(l_btnWidth);
       btn_bottommenu1.setOnClickListener(new View.OnClickListener() {
           public void onClick(View v) {
               btn_bottommenu1.setEnabled(false);
               btn_bottommenu2.setEnabled(true);
               btn_bottommenu3.setEnabled(true);
               currentFocusedBtn = 1;
               last_list_view_pos = 0;
               media_browser_load_option = 2;
               last_media_browser_load_option = media_browser_load_option;
               loadVideosFromDirectory("/sdcard/");
           }
       });
       btn_bottommenu2 = (Button) findViewById(R.id.video_browser_btn2);
       btn_bottommenu2.setWidth(l_btnWidth);
       btn_bottommenu2.setOnClickListener(new View.OnClickListener() {
           public void onClick(View v) {
               btn_bottommenu1.setEnabled(true);
               btn_bottommenu2.setEnabled(false);
               btn_bottommenu3.setEnabled(true);
               currentFocusedBtn = 2;
               last_list_view_pos = 0;
               media_browser_load_option = 0;
               last_media_browser_load_option = media_browser_load_option;
               loadVideosFromDirectory("/sdcard/");
           }
       });
       btn_bottommenu3 = (Button) findViewById(R.id.video_browser_btn3);
       btn_bottommenu3.setWidth(l_btnWidth);
       btn_bottommenu3.setOnClickListener(new View.OnClickListener() {
           public void onClick(View v) {
               btn_bottommenu1.setEnabled(true);
               btn_bottommenu2.setEnabled(true);
               btn_bottommenu3.setEnabled(false);
               currentFocusedBtn = 3;
               last_list_view_pos = 0;
               media_browser_load_option = 1;
               last_media_browser_load_option = media_browser_load_option;
               loadVideosFromDirectory("/sdcard/");
           }
       });
       media_browser_load_option = last_media_browser_load_option;
       if (media_browser_load_option==2) {
           btn_bottommenu1.setEnabled(false);
       } else if (media_browser_load_option==0) {
           btn_bottommenu2.setEnabled(false);
       } else if (media_browser_load_option==1){
           btn_bottommenu3.setEnabled(false);
       }
       loadVideosFromDirectory("/sdcard/");
    }
    //refresh the UI when the directoryEntries changes
    private static int last_list_view_pos = 0;
    public void refreshUI() {
       int l_btnWidth = this.getWindowManager().getDefaultDisplay().getWidth()/4;
       btn_bottommenu1.setWidth(l_btnWidth);
       btn_bottommenu2.setWidth(l_btnWidth);
       btn_bottommenu3.setWidth(l_btnWidth);
       //btn_bottommenu4.setWidth(l_btnWidth);

       SlowAdapter itla = new SlowAdapter(this);
       itla.setListItems(this.displayEntries);    
       this.setListAdapter(itla);
       getListView().setOnScrollListener(this);
       int l_size = this.displayEntries.size();
       if (l_size > 50) {
           getListView().setFastScrollEnabled(true);
       } else {
           getListView().setFastScrollEnabled(false);
       }
       if (l_size > 0) {
           if (last_list_view_pos &lt; l_size) {
               getListView().setSelection(last_list_view_pos);
           } else {
               getListView().setSelection(l_size-1);
           }
       }
       registerForContextMenu(getListView());
    }

    @Override
    public void onConfigurationChanged (Configuration newConfig) {
       super.onConfigurationChanged(newConfig);
       refreshUI();
    }

    static final int DIALOG_LOAD_MEDIA = 1;
    static final int DIALOG_HELP = 2;
    @Override
    protected Dialog onCreateDialog(int id) {
       switch(id) {
       case DIALOG_LOAD_MEDIA:
           ProgressDialog dialog = new ProgressDialog(this);
           dialog.setTitle("Load Files");
           dialog.setMessage("Please wait while loading...");
           dialog.setIndeterminate(true);
           dialog.setCancelable(true);
           return dialog;
       default:
           return null;
       }
    }
    /**
    * scroll events methods: this part of the source code contain the control source code
    * for handling scroll events
    */
    private boolean mBusy = false;
    private void disableButtons() {
       btn_bottommenu1.setEnabled(false);
       btn_bottommenu2.setEnabled(false);
       btn_bottommenu3.setEnabled(false);
    }

    private void enableButtons() {
       if (currentFocusedBtn!=1) {
           btn_bottommenu1.setEnabled(true);
       }
       if (currentFocusedBtn!=2) {
           btn_bottommenu2.setEnabled(true);
       }
       if (currentFocusedBtn!=3) {
           btn_bottommenu3.setEnabled(true);
       }
    }
    public void onScroll(AbsListView view, int firstVisibleItem,
           int visibleItemCount, int totalItemCount) {
       last_list_view_pos = view.getFirstVisiblePosition();
    }

    //private boolean mSaveMemory = false;
    public void onScrollStateChanged(AbsListView view, int scrollState) {      
       switch (scrollState) {
       case OnScrollListener.SCROLL_STATE_IDLE:
           enableButtons();
           mBusy = false;
           int first = view.getFirstVisiblePosition();
           int count = view.getChildCount();
           int l_releaseTarget;
           for (int i=0; i/if outofmemory, we try to clean up 10 view image resources,
                       //and try again
                       for (int j = 0; j &lt; 10; ++j) {
                           l_releaseTarget = first - count - j;
                           if (l_releaseTarget > 0) {
                               IconifiedTextSelected l_its = displayEntries.get(l_releaseTarget);
                               IconifiedTextSelectedView l_itsv = (IconifiedTextSelectedView)
                                   this.getListView().getChildAt(l_releaseTarget);
                               if (l_itsv!=null) {
                                   l_itsv.setIcon(null);
                               }
                               if (l_its != null) {
                                   Drawable l_dr = l_its.getIcon();
                                   l_its.setIcon(null);
                                   if (l_dr != null) {
                                       l_dr.setCallback(null);
                                       l_dr = null;
                                   }
                               }
                           }
                       }
                       System.gc();
                       //after clean up, we try again
                       if (l_type == 1) {
                           l_icon = null;
                       } else if (l_type == 2) {
                           l_icon = null;
                       }
                   }
                   this.displayEntries.get(first+i).setIcon(l_icon);
                   if (l_icon != null) {
                       t.setIcon(l_icon);
                       t.setTag(null);
                   }
               }
           }
           //System.gc();
           break;
       case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
           disableButtons();
           mBusy = true;
           break;
       case OnScrollListener.SCROLL_STATE_FLING:
           disableButtons();
           mBusy = true;
           break;
       }
    }

    /**
    * List item click action
    */
    private File currentFile;
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
       super.onListItemClick(l, v, position, id);
       last_list_view_pos = position;
       String selectedFileOrDirName = this.displayEntries.get((int)id).getText();
       if (selectedFileOrDirName.equals(upOneLevel)) {
           if (this.currentDirectory.getParent()!=null) {
               last_list_view_pos = 0;
               browseTo(this.currentDirectory.getParentFile());
           }
       } else {
           File l_clickedFile = new File(this.displayEntries.get((int)id).getText());
           if (l_clickedFile != null) {
               if (l_clickedFile.isDirectory()) {
                   last_list_view_pos = 0;
                   browseTo(l_clickedFile);
               } else {
                   showVideoInfo(l_clickedFile);
               }
           }
       }
    }

    private void browseTo(final File _dir) {
       if (_dir.isDirectory()) {
           this.currentDirectory = _dir;
           loadVideosFromDirectory(_dir.getAbsolutePath());
       }
    }

    /**
    * Slow adapter: this part of the code implements the list adapter
    * Will not bind views while the list is scrolling
    */
    private class SlowAdapter extends BaseAdapter {
       /** Remember our context so we can use it when constructing views. */
       private Context mContext;

       private List<iconifiedtextselected> mItems = new ArrayList<iconifiedtextselected>();

       public SlowAdapter(Context context) {
           mContext = context;
       }

       public void setListItems(List<iconifiedtextselected> lit)
       { mItems = lit; }

       /** @return The number of items in the */
       public int getCount() { return mItems.size(); }

       public Object getItem(int position)
       { return mItems.get(position); }

       /** Use the array index as a unique id. */
       public long getItemId(int position) {
           return position;
       }

       /** @param convertView The old view to overwrite, if one is passed
        * @returns a IconifiedTextSelectedView that holds wraps around an IconifiedText */
       public View getView(int position, View convertView, ViewGroup parent) {
           IconifiedTextSelectedView btv;
           if (convertView == null) {
               btv = new IconifiedTextSelectedView(mContext, mItems.get(position));
           } else { // Reuse/Overwrite the View passed
               // We are assuming(!) that it is castable!
               btv = (IconifiedTextSelectedView) convertView;
               btv.setText(mItems.get(position).getText());
           }
           if (position==0) {
               if (VideoBrowser.self.media_browser_load_option==0) {
                   btv.setIcon(R.drawable.folderback);
               } else if (mItems.get(0).getIcon()!=null) {
                   btv.setIcon(mItems.get(position).getIcon());
               } else {
                   btv.setIcon(R.drawable.video);
               }
           }
           //in busy mode
           else if (mBusy){
               //if icon is NULL: the icon is not loaded yet; load default icon
               if (mItems.get(position).getIcon()==null) {
                   btv.setIcon(R.drawable.video);
                   //mark this view, indicates the icon is not loaded
                   btv.setTag(this);
               } else {
                   //if icon is not null, just display the icon
                   btv.setIcon(mItems.get(position).getIcon());
                   //mark this view, indicates the icon is loaded
                   btv.setTag(null);
               }
           } else {
               //if not busy
               Drawable d = mItems.get(position).getIcon();
               if (d == null) {
                   //icon is not loaded, load now
                   btv.setIcon(R.drawable.video);
                   btv.setTag(this);
               } else {
                   btv.setIcon(mItems.get(position).getIcon());
                   btv.setTag(null);
               }
           }
           return btv;
       }
    }
    </iconifiedtextselected></iconifiedtextselected></iconifiedtextselected></iconifiedtextselected></iconifiedtextselected></iconifiedtextselected></iconifiedtextselected>

    }