Ticket #2259: 2259.patch

File 2259.patch, 13.7 KB (added by meddle, 15 years ago)

Some patch for the design

  • modules/org.sophie2.main.media.natlib/src/test/java/org/sophie2/main/media/natlib/demo/AudioDemo.java

    ### Eclipse Workspace Patch 1.0
    #P sophie2
     
    3838 * streams. 
    3939 *  
    4040 * @author stefan 
    41  *  
     41 * @author milo, meddle 
    4242 */ 
    43 @SuppressWarnings("serial") 
    4443public class AudioDemo extends Component { 
    4544 
     45        private static final long serialVersionUID = 444592419471524579L; 
     46 
    4647        private BinData binData; 
    4748        private int time = 0; 
    4849 
     
    5960                        try { 
    6061                                img = this.videoHandler.getFrame(this.time); 
    6162                        } catch (RuntimeException e) { 
    62                                 img = new ImmImage(new BufferedImage((int) this.info 
    63                                                 .getDimensions().getWidth(),(int) this.info.getDimensions() 
    64                                                 .getHeight(), ImmImage.PREFERRED_BI_TYPE)); 
     63                                int width = (int) this.info.getDimensions().getWidth(); 
     64                                int height = (int) this.info.getDimensions().getHeight(); 
     65                                BufferedImage source =  
     66                                        new BufferedImage(width, height, ImmImage.PREFERRED_BI_TYPE); 
     67 
     68                                img = new ImmImage(source); 
    6569                        } 
    6670                        img.draw((Graphics2D) g, 0, 0); 
    6771                } 
     
    126130         */ 
    127131        protected AudioChunk getAudio(int millis) { 
    128132                AudioChunk audio = this.getAudioHandler().getAudio(millis); 
     133 
    129134                return audio; 
    130135        } 
    131136 
    132137        /** 
     138         * The main routine of the demo. 
     139         *  
    133140         * @param args 
    134141         *            Full path to media file. 
    135142         * @throws IOException 
     
    140147         */ 
    141148        @SuppressWarnings("unchecked") 
    142149        public static void main(final String[] args) throws IOException, 
    143                         InterruptedException, InvocationTargetException { 
     150        InterruptedException, InvocationTargetException { 
    144151                System.setProperty("sophie2.development", "true"); 
    145152                FakeModuleRegistry.start(BaseNatlibModule.class, MainMediaNatlibModule.class, BaseMediaModule.class); 
    146153                SophieLog.setMinLevel("", LogLevel.DEBUG); 
    147154                SophieLog.debug("starting"); 
    148 //              String path = "/home/stefan/Desktop/41_30secMP3pro-64.mp3"; 
    149 //              String path = "/home/stefan/Desktop/93613 (copy).mpg"; 
     155 
     156                //              String path = "/home/stefan/Desktop/41_30secMP3pro-64.mp3"; 
     157                //              String path = "/home/stefan/Desktop/93613 (copy).mpg"; 
    150158                //String path = "/home/pavel/Desktop/6jfzqz42iz0i2u3jwwx2ax1ts.mov"; 
    151159                //String path = "/home/milo/Desktop/07 - The Mirror.mp3"; 
    152160                // String path = "/home/stefan/11k16bitpcm.wav"; 
     
    158166                //String path = "/home/stefan/media samples/41_30secWMA8-64.wma"; 
    159167                //String path = "/home/stefan/media samples/RhinoCommercial.mov"; 
    160168                // String path = "/home/stefan/media samples/may16_99.mpg"; 
    161 //              String path = "/home/stefan/Desktop/Video/"; 
    162 //              path += "2007-10-31 - Carling Cup - LIVERPOOL FC 2-1 Cardiff - Gerrard.avi"; 
    163 //              path += "Banda Bassotti - Carabina.avi"; 
    164 //              path += "Mike's New Car - High.avi"; 
    165 //              path += "RhinoCommercial.mov"; 
    166 //              path += "Umbro Commercial.avi"; 
     169                //              String path = "/home/stefan/Desktop/Video/"; 
     170                //              path += "2007-10-31 - Carling Cup - LIVERPOOL FC 2-1 Cardiff - Gerrard.avi"; 
     171                //              path += "Banda Bassotti - Carabina.avi"; 
     172                //              path += "Mike's New Car - High.avi"; 
     173                //              path += "RhinoCommercial.mov"; 
     174                //              path += "Umbro Commercial.avi"; 
    167175                //audio 
    168                  
     176 
    169177                //String path = "/home/stefan/Desktop/Audio/"; 
    170178                //path += "Autotamponneuse.ogg"; 
    171 //              path += "Bugs Bunny.wav"; 
    172 //              String path = "/home/stefan/Desktop/tempFile15139tempFile44832tempFile26989tempFile26966CanadaGeese.wav"; 
    173                  
     179                //              path += "Bugs Bunny.wav"; 
     180                //              String path = "/home/stefan/Desktop/tempFile15139tempFile44832tempFile26989tempFile26966CanadaGeese.wav"; 
     181 
    174182                //String path = "/home/pavel/Desktop/res/carcass - swansong - 03 - blackstar.mp3"; 
    175 //              String path = "/home/pavel/Desktop/res/two.divx6.avi"; 
    176 //              String path = "/media/other/Music/Marduk/1999 - Panzer Division Marduk/01 - Marduk - Panzer Division Marduk.mp3"; 
    177 //              String path = "/home/pavel/Desktop/res/alice in chains - junkhead-singlesreleaseparty.mpg"; 
     183                //              String path = "/home/pavel/Desktop/res/two.divx6.avi"; 
     184                //              String path = "/media/other/Music/Marduk/1999 - Panzer Division Marduk/01 - Marduk - Panzer Division Marduk.mp3"; 
     185                //              String path = "/home/pavel/Desktop/res/alice in chains - junkhead-singlesreleaseparty.mpg"; 
    178186                //String path = "/home/pavel/Desktop/res/02 - Hype! (bonus performances).avi"; 
    179 //              String path = "/home/pavel/Desktop/res/8uksomunz336d4ai7414zfhkx.mov"; 
    180 //              String path = "/home/pavel/Desktop/res/6jfzqz42iz0i2u3jwwx2ax1ts.mov"; 
    181                 String path = "/home/pavel/Desktop/res/ulica_sezam_mana_mana_vbox7.avi"; 
     187                //String path = "/home/meddle/Movies/02 - Hype! (bonus performances).avi"; 
     188                //String path = "/home/meddle/nicotine/ulica_sezam_mana_mana_vbox7.avi"; 
     189                //String path = "/home/meddle/two.divx6.avi"; 
     190                //String path = "/home/meddle/Umbro Commercial.avi"; 
     191                String path = "/home/meddle/nicotine/zwan - number of the beast.mp3"; 
    182192 
    183193                final AudioDemo audioDemo = new AudioDemo(path); 
    184194                final NativeAudioOutput output = new NativeAudioOutput(); 
    185195                SwingUtilities.invokeAndWait(new Runnable() { 
    186196 
    187197                        public void run() { 
    188                                 SophieLog.debug("VideoDemo created"); 
    189                                 JFrame f = new JFrame( 
    190                                                 "Audio Demo - Java Wrapper of C++ application that uses ffmpeg"); 
     198                                SophieLog.debug("MediaDemo created"); 
     199                                JFrame frame = new JFrame( 
     200                                "Media Demo - Java Wrapper of C++ application that uses ffmpeg"); 
    191201 
    192                                 f.addWindowListener(new WindowAdapter() { 
     202                                frame.addWindowListener(new WindowAdapter() { 
    193203                                        @Override 
    194204                                        public void windowClosing(WindowEvent e) { 
    195205                                                audioDemo.stop(); 
    196206                                                System.exit(0); 
    197207                                        } 
    198208                                }); 
    199                                 f.add(audioDemo); 
    200                                 f.pack(); 
    201                                 f.setVisible(true); 
    202                                 f.pack(); 
     209                                 
     210                                frame.add(audioDemo); 
     211                                frame.pack(); 
     212                                frame.setVisible(true); 
     213                                frame.pack(); 
     214                                 
    203215                                output.start(); 
    204216                                output.registerComposite(new MediaComposite() { 
    205217 
     
    209221 
    210222                                        AudioChunk last = AudioChunk.SILENCE; 
    211223 
    212                                         public void getAudioChunks(List<AudioChunk> res, 
    213                                                         TimePos time) { 
     224                                        public void getAudioChunks(List<AudioChunk> res, TimePos time) { 
    214225                                                this.last = audioDemo.getAudio(localTime(time)); 
    215226                                                res.add(this.last); 
    216227                                        } 
    217228 
    218229                                        int localTime(TimePos time) { 
    219                                                 double d = audioDemo.getAudioHandler().getInfo() 
    220                                                                 .getDuration(); 
     230                                                double d = audioDemo.getAudioHandler().getInfo().getDuration(); 
    221231                                                int hundreds = (int) (d * 100) - 1; 
    222232                                                return (int) (time.getMillis() / 10 % hundreds) * 10; 
    223233                                        } 
     
    232242        } 
    233243 
    234244        /** 
    235          * Getter for {@link MediaHandler} that is contained in the demo. 
     245         * Getter for the video {@link MediaHandler} that is contained in the demo. 
    236246         *  
    237          * @return current demo's {@link MediaHandler}. 
     247         * @return  
     248         *                      The current demo's video {@link MediaHandler}. 
    238249         */ 
    239250        MediaHandler getVideoHandler() { 
    240251                return this.videoHandler; 
    241252        } 
    242253 
    243254        /** 
    244          * Getter for {@link MediaHandler} that is contained in the demo. 
     255         * Getter for the audio {@link MediaHandler} that is contained in the demo. 
    245256         *  
    246          * @return current demo's {@link MediaHandler}. 
     257         * @return  
     258         *                      The current demo's audio {@link MediaHandler}. 
    247259         */ 
    248260        MediaHandler getAudioHandler() { 
    249261                return this.audioHandler; 
    250262        } 
    251  
    252263} 
    253  No newline at end of file 
  • modules/org.sophie2.base.media/src/main/java/org/sophie2/base/media/MediaInfo.java

     
    77/** 
    88 * Immutable class for media meta data. 
    99 *  
    10  * @author Mira 
     10 * @author mira 
    1111 */ 
    12 // TODO: Add kind if this is persistable, or remove this comment if not. 
    1312@Immutable 
    1413public class MediaInfo { 
    1514 
  • modules/org.sophie2.main.media.natlib/src/main/java/org/sophie2/main/media/natlib/decoder/NativeMediaHandler.java

     
    11package org.sophie2.main.media.natlib.decoder; 
    22 
    3 import org.sophie2.base.commons.util.bindata.BinData; 
     3import java.util.Collections; 
     4import java.util.HashMap; 
     5import java.util.LinkedHashMap; 
     6import java.util.Map; 
     7import java.util.Map.Entry; 
     8import java.util.concurrent.BlockingQueue; 
     9import java.util.concurrent.LinkedBlockingQueue; 
     10 
    411import org.sophie2.base.commons.util.ImmImage; 
     12import org.sophie2.base.commons.util.bindata.BinData; 
    513import org.sophie2.base.commons.util.position.ImmSize; 
    614import org.sophie2.base.media.AudioChunk; 
    715import org.sophie2.base.media.MediaHandler; 
     
    1523 * This class is responsible for controlling the lifetime of the native bridge. 
    1624 *  
    1725 * @author milo 
    18  *  
    1926 */ 
    2027public class NativeMediaHandler implements MediaHandler { 
    2128 
     29        /** 
     30         * Thread that reads audio output from the natives and puts 
     31         * it into a buffer. That way Sophie has asynchronous audio.  
     32         *  
     33         * @author milo, meddle 
     34         */ 
     35        private class AudioThread extends Thread { 
     36                 
     37                /** 
     38                 * Capacity of the cache meaning that the stored 
     39                 * chunks are for 0.01ms * CACHE_CAPACITY time ahead. 
     40                 */ 
     41                private static final int CACHE_CAPACITY = 1000; 
     42                private static final int PREFETCH_COUNT = 400; 
     43                 
     44                private final MediaNativeBridge bridge;  
     45                // Requests and responses queues: 
     46                private final BlockingQueue<Integer> requestsQueue; 
     47                private final BlockingQueue<AudioChunk> responsesQueue; 
     48                private final Map<Integer, AudioChunk> audioCache; 
     49 
     50                private final int audioDuration; 
     51                 
     52                protected AudioThread(MediaNativeBridge audioBridge, int audioDuration) { 
     53                        this.bridge = audioBridge; 
     54                        this.requestsQueue = new LinkedBlockingQueue<Integer>(); 
     55                        this.responsesQueue = new LinkedBlockingQueue<AudioChunk>(); 
     56                        HashMap<Integer, AudioChunk> map = new LinkedHashMap<Integer, AudioChunk>(CACHE_CAPACITY) { 
     57                                 
     58                                private static final long serialVersionUID = 5345763680957046630L; 
     59 
     60                                @Override 
     61                                protected boolean removeEldestEntry(Entry<Integer, AudioChunk> eldest) { 
     62                                        return size() > CACHE_CAPACITY; 
     63                                } 
     64                        }; 
     65 
     66                        this.audioCache = Collections.synchronizedMap(map); 
     67                        this.audioDuration = audioDuration; 
     68                        setDaemon(true); 
     69                } 
     70 
     71                public synchronized AudioChunk getAudio(int millis) { 
     72                        AudioChunk res = this.audioCache.get(millis); 
     73                        if (res != null) { 
     74                                return res; 
     75                        } 
     76                        this.requestsQueue.add(millis); 
     77                         
     78                        try { 
     79                                return this.responsesQueue.take(); 
     80                        } catch (InterruptedException e) { 
     81                                throw new RuntimeException(e); 
     82                        } 
     83                } 
     84                 
     85                private AudioChunk getNativeAudio(int millis) { 
     86                        assert millis >= 0; 
     87                         
     88                        AudioChunk res = this.bridge.getAudio(millis);  
     89                        return res; 
     90                } 
     91 
     92                @Override 
     93                public void run() { 
     94                        BlockingQueue<Integer> reqQueue = this.requestsQueue; 
     95                        BlockingQueue<AudioChunk> resQueue = this.responsesQueue; 
     96 
     97                        int lastRequest = -1; 
     98                        while (true) { 
     99                                 
     100                                // If there are some requests for AudioChunks... 
     101                                if (!reqQueue.isEmpty()) { 
     102                                        lastRequest = reqQueue.poll(); 
     103                                        SophieLog.debug("Fetching request for position " + lastRequest); 
     104 
     105                                        // If the requested chunk is not in the cache retrieve it 
     106                                        // from the natives and put it in the cache. 
     107                                        if (!this.audioCache.containsKey(lastRequest)) { 
     108                                                this.audioCache.put(lastRequest, getNativeAudio(lastRequest)); 
     109                                        } 
     110                                         
     111                                        // Add the requested chunk into the queue with the responses. 
     112                                        resQueue.add(this.audioCache.get(lastRequest)); 
     113                                } else { 
     114                                        int len = AudioChunk.MILLIS_LEN; 
     115                                        int limit = lastRequest + PREFETCH_COUNT * len; 
     116                                         
     117                                        // Taking in mind audio duration: 
     118                                        limit = (limit > this.audioDuration) ? this.audioDuration : limit; 
     119                                         
     120                                        int nextNeeded = -1; 
     121                                         
     122                                        // Check if there is need to prefetch something: 
     123                                        for (int t = lastRequest; t < limit; t += len) { 
     124                                                if (!this.audioCache.containsKey(t)) { 
     125                                                        nextNeeded = t; 
     126                                                        break; 
     127                                                } 
     128                                        } 
     129                                         
     130                                        //prefetch 
     131                                        if (nextNeeded != -1) { 
     132                                                SophieLog.debug("Prefetching: " + nextNeeded); 
     133                                                this.audioCache.put(nextNeeded, getNativeAudio(nextNeeded)); 
     134                                        } else { 
     135                                                // If there is no request yet just sleep for a while... 
     136                                                if (lastRequest == -1 && reqQueue.isEmpty()) { 
     137                                                        try { 
     138                                                                sleep(1000 / 200); 
     139                                                                continue; 
     140                                                        } catch (InterruptedException e) { 
     141                                                                SophieLog.error("The Audio thread was interrupted", e); 
     142                                                                throw new RuntimeException(e); 
     143                                                        } 
     144                                                }                                        
     145                                        } 
     146                                } 
     147                        } 
     148                } 
     149 
     150        } 
     151 
    22152        private BinData mediaData; 
    23153 
    24154        // lazy 
     
    27157 
    28158        // lazy 
    29159        private MediaInfo info; 
     160         
     161        private final AudioThread audioThread;  
     162 
     163 
    30164 
    31165        /** 
    32166         * Constructs by the file data. 
     
    36170         */ 
    37171        public NativeMediaHandler(BinData mediaData) { 
    38172                this.mediaData = mediaData; 
    39  
     173                this.audioThread = new AudioThread(getAudioBridge(), getModLen()); 
     174                this.audioThread.start(); 
    40175        } 
    41176 
    42177        private MediaNativeBridge getAudioBridge() { 
     
    88223        } 
    89224 
    90225        public AudioChunk getAudio(long millis) { 
    91                 assert millis >= 0 && millis <= Integer.MAX_VALUE; 
    92                 // TODO: temporary just loop 
     226                int correctMillis = (int) millis % getModLen(); 
     227 
    93228                if (getInfo().hasAudio()) { 
    94                         return getAudioBridge().getAudio((int) millis % getModLen()); 
     229                        return this.audioThread.getAudio(correctMillis); 
    95230                } 
    96231                return AudioChunk.SILENCE; 
    97232        } 
    98233 
    99234        private ImmImage lastFrame = null; 
    100235        private long lastFrameMillis =  Long.MAX_VALUE / 5; 
    101          
    102          
     236 
     237 
    103238        public ImmImage getFrame(long millis) { 
    104239                assert millis >= 0 && millis <= Integer.MAX_VALUE; 
    105240                // TODO: temporary just loop