package org.ripple.power.sound; import java.awt.Color; import java.awt.Font; import java.awt.Image; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.util.Vector; import mediaframe.mpeg4.audio.AudioPlayer; import mediaframe.mpeg4.isofile.MP4Atom; import mediaframe.mpeg4.isofile.MP4Descriptor; import mediaframe.mpeg4.video.BitStream; import mediaframe.mpeg4.video.MPEG4Decoder; import mediaframe.mpeg4.video.VideoFrame; import org.ripple.power.collection.ArrayByte; import org.ripple.power.timer.LTimer; import org.ripple.power.ui.UIRes; import org.ripple.power.ui.graphics.LGraphics; import org.ripple.power.ui.view.WaitAnimation; import org.ripple.power.utils.DateUtils; import org.ripple.power.utils.GraphicsUtils; public class MP4Player implements IMpeg4 { private boolean visible; private WaitAnimation wait; private Image movieScreen = null; private int[] pixels = null; private Font ERROR_FONT = new Font("Arial", 0, 12); public final static int ALPHA_MASK = (255 << 24); public final static int SHIFT_BITS = 16; public final static int R_CR_COEFF = (int) (1.402 * (1 << SHIFT_BITS)); public final static int G_CR_COEFF = (int) (0.714 * (1 << SHIFT_BITS)); public final static int G_CB_COEFF = (int) (0.344 * (1 << SHIFT_BITS)); public final static int B_CB_COEFF = (int) (1.772 * (1 << SHIFT_BITS)); private boolean complete; private long start_playing_time = 0; private int video_width; private int video_height; private int pixel_frame_width; private int pixel_frame_height; int memory_image_width; int memory_image_height; private int current_frame = 0; private long last_sleep_time = 0; private long autoStop; public final int CONNECTION_SPEED_UNKNOWN = 0; public final int CONNECTION_SPEED_24K = 1; // 1333 ms public final int CONNECTION_SPEED_44K = 2; // 727 ms public final int CONNECTION_SPEED_128K = 3; // 250 ms public final int CONNECTION_SPEED_256K = 4; // 125 ms public final int CONNECTION_SPEED_350K = 5; // 91 ms public final int CONNECTION_SPEED_500K = 6; // 64 ms public final int CONNECTION_SPEED_800K = 7; // 40 ms public final String[] CONNECTION_PARAMETERS = { "default_media", "24k_media", "44k_media", "128k_media", "256k_media", "350k_media", "500k_media", "800+_media" }; public final String[] CONNECTION_TEXT = { "unknown", "24", "44", "128", "256", "350", "500", "800" }; public final int[] CONNECTION_VALUES = { -1, 24, 44, 128, 256, 350, 500, 800 }; private Vector<DataSample> audioSamples = new Vector<DataSample>(); private Vector<DataSample> videoSamples = new Vector<DataSample>(); public final String[] ERROR_MESSAGES = { null, "Unable to load the movie file", "The parameter \"default_media\" isn't specified", "Unsupported movie file format", "The license does not exist in the movie file", null, null, null, null, null, "MEDIAFRAME LOCKED!" }; public final static int MANUAL_PLAYBACK = 0; public final static int ROLLOWER_TO_PLAY = 1; public final static int CLICK_TO_PLAY = 2; public final static int START_STATE = 0; public final static int READY_STATE = 1; public final static int PLAY_STATE = 2; public final static int PAUSE_STATE = 3; public final static int STOP_STATE = 4; public final static int REWIND_STATE = 5; public final static int ERROR_STATE = 6; public final static String[] STATE_TEXT = { "start", "ready", "playing", "paused", "finished", "finished", "error" }; private volatile int player_state = START_STATE; private boolean buffering = true; private boolean firstLoop = true; private String fileName = null; private AudioPlayer audioPlayer = null; private MPEG4Decoder videoDecoder = null; private DataBuffer dataBuffer = null; private InputStream audioStream = null; private BitStream videoStream = null; private volatile int connection_speed = -1; private int movieTime = -1; private double video_rate = -1; private int movieLength = -1; private int movieDuration = -1; private int video_size = -1; private int playback_mode = CLICK_TO_PLAY; private boolean autoplay = false; public boolean audio_enabled = false; private boolean playback_loop = false; private String sBufferSize = "20%"; public boolean smooth_video = true; public boolean licenseIsCorrect = true; private int error_code = 0; private int volume = 100; public boolean mute; private LTimer timer; private int audioHeaderSize = 0; private long audioHeaderOffset = 0; private ArrayByte arrayByte; private volatile Thread movieParseThread = null; public MP4Player(int width, int height) { this.licenseIsCorrect = true; this.smooth_video = true; this.audio_enabled = true; this.playback_loop = true; this.playback_mode = MANUAL_PLAYBACK; this.playersetvolume("0%"); if (audio_enabled && (!AudioPlayer.isSoundEnabled())) { audio_enabled = false; mute = true; } this.autoStop = -1; this.wait = new WaitAnimation(width, height); this.wait.white(); this.timer = new LTimer(100); this.visible = true; } public void load(final String fileName) { this.wait.setRunning(true); Thread thread = new Thread(new Runnable() { public void run() { innerLoad(fileName); } }); thread.start(); thread = null; } private void innerLoad(String path) { if (player_state == REWIND_STATE) { return; } complete = true; error_code = 0; player_state = REWIND_STATE; close(); if (!audio_enabled) { audio_enabled = true; if (audio_enabled && (!AudioPlayer.isSoundEnabled())) { audio_enabled = false; mute = true; } else { mute = false; } } firstLoop = true; autoplay = false; if (arrayByte == null) { try { arrayByte = new ArrayByte( UIRes.getStream(this.fileName = path), ArrayByte.BIG_ENDIAN); } catch (IOException e) { arrayByte = null; } } if (arrayByte != null) { loadInputStream(new ByteArrayInputStream(arrayByte.getData()), arrayByte.length()); } else { wait.setRunning(true); player_state = PAUSE_STATE; complete = false; return; } if (dataBuffer != null) { movieScreen = null; pixels = null; movieParseThread = Thread.currentThread(); parseFile(); if (movieParseThread == Thread.currentThread()) { if (error_code == 0) { playerstart(); } movieParseThread = null; } } complete = false; } public void play(final String fileName) { if (!complete) { Thread thread = new Thread(new Runnable() { public void run() { load(fileName); while (buffering) { try { Thread.sleep(30); } catch (InterruptedException e) { } } playerplay(); } }); thread.start(); thread = null; } } public void finalize() { this.dispose(); } public void draw(LGraphics g, int x, int y, int width, int height) { if (player_state == ERROR_STATE) { g.setColor(Color.black); g.fillRect(x, y, width, height); g.setColor(Color.white); g.setFont(ERROR_FONT); if (error_code == 10) { g.drawString(ERROR_MESSAGES[error_code], x + (width / 2 - 70), x + (height / 2 - 3)); } else { g.drawString("ERROR: " + ERROR_MESSAGES[error_code], x + 10, y + 20); } } else if ((player_state == PLAY_STATE) || (player_state == PAUSE_STATE)) { if (movieScreen != null) { GraphicsUtils.setAntialias(g, true); if (smooth_video) { g.drawImage(movieScreen, x, y, width, height); } else { g.drawImage(movieScreen, x, y); } GraphicsUtils.setAntialias(g, false); } } } private void loadInputStream(InputStream is, int length) { movieTime = -1; try { boolean encryptedStream = false; movieLength = length; int bufferSize = parsePercentValue(movieLength, sBufferSize, movieLength / 5); if (bufferSize == 0) { bufferSize = movieLength / 5; } if (bufferSize > movieLength) { bufferSize = movieLength; } buffering = true; dataBuffer = new DataBuffer(this, is, movieLength, bufferSize, encryptedStream); } catch (Throwable ex) { ex.printStackTrace(); error_code = 1; player_state = ERROR_STATE; } } public void parseFile() { int timeScale = -1; long duration = -1; long videoHeaderOffset = 0; int videoHeaderSize = 0; try { audioSamples.removeAllElements(); videoSamples.removeAllElements(); DataStream stream = new DataStream(dataBuffer); for (; ((audioSamples.size() == 0) && (videoSamples.size() == 0));) { MP4Atom atom = MP4Atom.createAtom(stream); if (atom.getType() == MP4Atom.MP4MovieAtomType) { MP4Atom movieAtom = atom; int j = 0; MP4Atom trackAtom = movieAtom.lookup( MP4Atom.MP4TrackAtomType, j++); while (trackAtom != null) { MP4Atom mediaAtomType = trackAtom.lookup( MP4Atom.MP4MediaAtomType, 0); if (mediaAtomType == null) throw new Exception( "The MP4MediaAtom does not exist"); MP4Atom handlerAtom = mediaAtomType.lookup( MP4Atom.MP4HandlerAtomType, 0); if (handlerAtom == null) throw new Exception( "The MP4HandlerAtom does not exist"); if (handlerAtom.getHandlerType() == MP4Atom .typeToInt("soun") || handlerAtom.getHandlerType() == MP4Atom .typeToInt("vide")) { MP4Atom mediaInformationAtom = mediaAtomType .lookup(MP4Atom.MP4MediaInformationAtomType, 0); if (mediaInformationAtom == null) throw new Exception( "The MP4MediaInformationAtom does not exist"); MP4Atom sampleTableAtom = mediaInformationAtom .lookup(MP4Atom.MP4SampleTableAtomType, 0); if (sampleTableAtom == null) throw new Exception( "The MP4SampleTableAtom does not exist"); MP4Atom sampleDescriptionAtom = sampleTableAtom .lookup(MP4Atom.MP4SampleDescriptionAtomType, 0); if (sampleDescriptionAtom == null) throw new Exception( "The MP4SampleDescriptionAtom does not exist"); if (handlerAtom.getHandlerType() == MP4Atom .typeToInt("vide")) { MP4Atom mediaHeaderAtom = mediaAtomType.lookup( MP4Atom.MP4MediaHeaderAtomType, 0); if (mediaHeaderAtom == null) { throw new Exception( "The MP4MediaHeaderAtom does not exist"); } duration = mediaHeaderAtom.getDuration(); timeScale = mediaHeaderAtom.getTimeScale(); movieDuration = (int) (duration * 1000 / timeScale); MP4Atom visualSampleEntry = sampleDescriptionAtom .lookup(MP4Atom.MP4VisualSampleEntryAtomType, 0); if (visualSampleEntry == null) { throw new Exception( "The MP4VisualSampleEntryAtom does not exist"); } video_width = visualSampleEntry.getWidth(); video_height = visualSampleEntry.getHeight(); video_size = 0; videoHeaderOffset = videoHeaderSize = 0; MP4Atom esdAtom = visualSampleEntry.lookup( MP4Atom.MP4ESDAtomType, 0); if (esdAtom != null) { MP4Descriptor esd_descriptor = esdAtom .getEsd_descriptor(); if (esd_descriptor != null) { MP4Descriptor decoderConfigDescriptor = esd_descriptor .lookup(MP4Descriptor.MP4DecoderConfigDescriptorTag, 0); if (decoderConfigDescriptor != null) { MP4Descriptor decSpecificInfoDescriptor = decoderConfigDescriptor .lookup(MP4Descriptor.MP4DecSpecificInfoDescriptorTag, 0); if (decSpecificInfoDescriptor != null) { videoHeaderOffset = decSpecificInfoDescriptor .getDecSpecificDataOffset(); videoHeaderSize = decSpecificInfoDescriptor .getDecSpecificDataSize(); } } } } } else { MP4Atom audioSampleEntry = sampleDescriptionAtom .lookup(MP4Atom.MP4AudioSampleEntryAtomType, 0); if (audioSampleEntry == null) throw new Exception( "The MP4AudioSampleEntryAtom does not exist"); audioHeaderOffset = audioHeaderSize = 0; MP4Atom esdAtom = audioSampleEntry.lookup( MP4Atom.MP4ESDAtomType, 0); if (esdAtom != null) { MP4Descriptor esd_descriptor = esdAtom .getEsd_descriptor(); if (esd_descriptor != null) { MP4Descriptor decoderConfigDescriptor = esd_descriptor .lookup(MP4Descriptor.MP4DecoderConfigDescriptorTag, 0); if (decoderConfigDescriptor != null) { MP4Descriptor decSpecificInfoDescriptor = decoderConfigDescriptor .lookup(MP4Descriptor.MP4DecSpecificInfoDescriptorTag, 0); if (decSpecificInfoDescriptor != null) { audioHeaderOffset = decSpecificInfoDescriptor .getDecSpecificDataOffset(); audioHeaderSize = decSpecificInfoDescriptor .getDecSpecificDataSize(); } } } } } MP4Atom sampleToChunkAtom = sampleTableAtom.lookup( MP4Atom.MP4SampleToChunkAtomType, 0); if (sampleToChunkAtom == null) throw new Exception( "The MP4SampleToChunkAtom does not exist"); MP4Atom sampleSizeAtom = sampleTableAtom.lookup( MP4Atom.MP4SampleSizeAtomType, 0); if (sampleSizeAtom == null) { sampleSizeAtom = sampleTableAtom .lookup(MP4Atom.MP4CompactSampleSizeAtomType, 0); } if (sampleSizeAtom == null) throw new Exception( "The MP4SampleSizeAtom does not exist"); MP4Atom chunkOffsetAtomType = sampleTableAtom .lookup(MP4Atom.MP4ChunkOffsetAtomType, 0); if (chunkOffsetAtomType == null) { chunkOffsetAtomType = sampleTableAtom.lookup( MP4Atom.MP4ChunkLargeOffsetAtomType, 0); } if (chunkOffsetAtomType == null) throw new Exception( "The MP4ChunkOffsetAtom does not exist"); Vector<MP4Atom.Record> records = sampleToChunkAtom .getRecords(); int currentSample = 0; for (int i = 0; i < records.size(); i++) { MP4Atom.Record record = (MP4Atom.Record) records .elementAt(i); int maxChunkNumber = 0; if (i == records.size() - 1) { maxChunkNumber = chunkOffsetAtomType .getChunks().size(); } else { MP4Atom.Record nextRecord = (MP4Atom.Record) records .elementAt(i + 1); maxChunkNumber = nextRecord.getFirstChunk() - 1; } for (int chunkNumber = record.getFirstChunk() - 1; chunkNumber < maxChunkNumber; chunkNumber++) { Long offset = (Long) chunkOffsetAtomType .getChunks().elementAt(chunkNumber); if (offset == null) throw new Exception( "Unable to find the chunk with the id = " + record.getFirstChunk()); long sampleOffset = offset.longValue(); for (int num = 0; num < record .getSamplesPerChunk(); num++) { int size = sampleSizeAtom .getSampleSize(); if (size == 0) { Integer iSize = (Integer) sampleSizeAtom .getSamples().elementAt( currentSample); if (iSize == null) throw new Exception( "Unable to find the sample with the id = " + currentSample); size = iSize.intValue(); } DataSample sample = new DataSample( sampleOffset, size); if (handlerAtom.getHandlerType() == MP4Atom .typeToInt("soun")) { audioSamples.addElement(sample); } else if (handlerAtom.getHandlerType() == MP4Atom .typeToInt("vide")) { videoSamples.addElement(sample); video_size += size; } sampleOffset += size; currentSample++; } } } } trackAtom = movieAtom.lookup(MP4Atom.MP4TrackAtomType, j++); } } } } catch (InterruptedException iex) { return; } catch (InterruptedIOException iox) { return; } catch (Exception ex) { ex.printStackTrace(); error_code = 3; player_state = ERROR_STATE; } video_rate = (((double) videoSamples.size()) * ((double) timeScale) / (double) (duration)); if ((videoHeaderSize > 0) && (videoHeaderOffset > 0)) { videoSamples.insertElementAt(new DataSample(videoHeaderOffset, videoHeaderSize), 0); video_size += videoHeaderSize; } if ((audioHeaderSize > 0) && (audioHeaderOffset > 0)) { audioSamples.insertElementAt(new DataSample(audioHeaderOffset, audioHeaderSize), 0); } } public void playerstart() { try { if (audio_enabled) { try { audioStream = new DataChannel(DataChannel.AUDIO_CHANNEL, dataBuffer, audioSamples); audioPlayer = AudioPlayer.createAudioPlayer(audioStream, audioHeaderSize); audioPlayer.setVolume(volume); audioPlayer.setMute(mute); } catch (Exception ex) { mute = true; audioPlayer = null; audio_enabled = false; } } videoStream = new BitStream(new DataChannel( DataChannel.VIDEO_CHANNEL, dataBuffer, videoSamples)); videoDecoder = new MPEG4Decoder(this, videoStream, video_width, video_height, video_rate, video_size); } catch (Exception ex) { ex.printStackTrace(); } } public void playerplay() { this.wait.setRunning(true); synchronized (this) { if (firstLoop) { autoplay = true; return; } } if ((buffering == true) || ((player_state != READY_STATE) && (player_state != PAUSE_STATE))) { return; } if (playback_mode == ROLLOWER_TO_PLAY) { playback_mode = MANUAL_PLAYBACK; } try { if (audioPlayer != null) { audioPlayer.play(); } player_state = PLAY_STATE; synchronized (this) { notifyAll(); } complete = false; } catch (Exception ex) { } } public void playerpause() { this.wait.setRunning(false); if ((buffering == true) || (player_state != PLAY_STATE)) { return; } try { player_state = PAUSE_STATE; if (audioPlayer != null) { audioPlayer.pause(); } } catch (Exception ex) { } } private void playerstop() { this.wait.setRunning(false); if (audioPlayer != null) { try { audioPlayer.stop(); } catch (Exception ex) { } finally { audioPlayer = null; } } if (videoDecoder != null) { try { videoDecoder.stop(); } catch (Exception ex) { } finally { videoDecoder = null; } } movieTime = -1; } public void playerend() { this.wait.setRunning(false); if (!playback_loop) { player_state = STOP_STATE; } if (playback_loop) { if (videoDecoder.getBaseTime() >= videoDecoder.getDuration()) { autoplay = true; last_sleep_time = -1; movieTime = -1; start_playing_time = -1; playerrewind(); } } } public void playerrewind() { this.wait.setRunning(false); if ((player_state == ERROR_STATE) || (player_state == REWIND_STATE) || (player_state == START_STATE) || (player_state == READY_STATE)) { return; } if (buffering && (player_state != START_STATE)) { buffering = false; } player_state = REWIND_STATE; playerstop(); firstLoop = true; playerstart(); } public void startReBuffering() { buffering = true; if (player_state == PLAY_STATE) { if (audioPlayer != null) { audioPlayer.pause(); } } } public void stopBuffering() throws InterruptedIOException { try { if (player_state == PLAY_STATE) { if (audioPlayer != null) { audioPlayer.play(); } } buffering = false; synchronized (this) { notifyAll(); } if ((player_state == READY_STATE) || (player_state == START_STATE)) { Thread.sleep(300); } } catch (InterruptedException iex) { throw new InterruptedIOException(iex.getMessage()); } } public void stopReBuffering() throws InterruptedIOException { this.stopBuffering(); } public void playersetmute(boolean mute) { if (audio_enabled) { this.mute = mute; if (audioPlayer != null) { audioPlayer.setMute(mute); } } } public void playersetvolume(String sValue) { if (audio_enabled) { try { volume = parsePercentValue(100, sValue, volume); if ((sValue != null) && (sValue.length() >= 1) && (sValue.charAt(sValue.length() - 1) != '%')) { if (volume == Integer.parseInt(sValue)) { volume = (volume - 1) * 100 / 9; } } if (volume < 0) { volume = 0; } else if (volume > 100) { volume = 100; } if (audioPlayer != null) { audioPlayer.setVolume(volume); } } catch (Exception ex) { } } } public boolean getAudioState() { return mute; } public String getFileName() { return fileName == null ? "" : fileName; } public int getVolume() { return (int) ((float) volume * 9.f / 100.f + 1.5f); } public int getVolume(String type) { if ("%".equals(type)) { return volume; } return getVolume(); } public int getVideoSize() { return movieLength; } public int getVideoLength() { return movieDuration; } public int getVideoTime() { return movieTime; } public int getConnectionSpeed() { return CONNECTION_VALUES[connection_speed >= 0 ? connection_speed : 0]; } public String getState() { if (buffering && (player_state != ERROR_STATE)) { if ((player_state == START_STATE) || (player_state == READY_STATE) || firstLoop) { return "buffering"; } else { return "re-buffering"; } } return STATE_TEXT[player_state]; } public int get_errorcode() { return error_code; } public String get_errortext() { return ERROR_MESSAGES[error_code]; } /** * 解析图像桢 */ public void nextFrame(VideoFrame videoFrame) throws InterruptedIOException { int width = videoFrame.getFrameWidth(); int height = videoFrame.getFrameHeight(); int buffer_width = videoFrame.getBufferWidth(); int[][] y_cb_cr_pixels = videoFrame.getPixelData(); if (pixels == null) { if ((width == -1) && (height == -1)) { width = 320; height = 240; } else if (width == -1) { width = (width * height) / height; } else if (height == -1) { height = (height * width) / width; } } if (smooth_video) { memory_image_width = pixel_frame_width = width; memory_image_height = pixel_frame_height = height; } else { memory_image_width = width; memory_image_height = height; pixel_frame_width = width > width ? width : width; pixel_frame_height = height > height ? height : height; } if (pixels == null) { int pixelSize = pixel_frame_width * pixel_frame_height; pixels = new int[pixelSize]; movieScreen = GraphicsUtils.newAwtRGBImage(pixels, pixel_frame_width, pixel_frame_height, pixelSize); } long playingTime = System.currentTimeMillis() - start_playing_time; int i, j, y, cb, cr, r_cr, g_cr_cb, b_cb, r, g, b; int lumminance_index = 0; int chrominance_index = 0; int pixel_index = 0; // Y CR CB -> R G B transformation for (j = 0; j < height; j += 2) { for (i = 0; i < width; i++) { y = y_cb_cr_pixels[0][lumminance_index + i] << SHIFT_BITS; cb = y_cb_cr_pixels[1][chrominance_index + (i >> 1)] - 128; cr = y_cb_cr_pixels[2][chrominance_index + (i >> 1)] - 128; r_cr = R_CR_COEFF * cr; g_cr_cb = -G_CB_COEFF * cb - G_CR_COEFF * cr; b_cb = B_CB_COEFF * cb; r = -(y + r_cr) >> SHIFT_BITS; g = -(y + g_cr_cb) >> SHIFT_BITS; b = -(y + b_cb) >> SHIFT_BITS; r = -(r & (r >> 63)) - 255; g = -(g & (g >> 63)) - 255; b = -(b & (b >> 63)) - 255; pixels[pixel_index + i++] = ALPHA_MASK + ((b & (b >> 63)) + 255) + (((g & (g >> 63)) + 255) << 8) + (((r & (r >> 63)) + 255) << 16); y = y_cb_cr_pixels[0][lumminance_index + i] << SHIFT_BITS; r = -(y + r_cr) >> SHIFT_BITS; g = -(y + g_cr_cb) >> SHIFT_BITS; b = -(y + b_cb) >> SHIFT_BITS; // r = g = b = - ((y >> SHIFT_BITS) + 128); r = -(r & (r >> 63)) - 255; g = -(g & (g >> 63)) - 255; b = -(b & (b >> 63)) - 255; pixels[pixel_index + i--] = ALPHA_MASK + ((b & (b >> 63)) + 255) + (((g & (g >> 63)) + 255) << 8) + (((r & (r >> 63)) + 255) << 16); y = y_cb_cr_pixels[0][lumminance_index + buffer_width + i] << SHIFT_BITS; r = -(y + r_cr) >> SHIFT_BITS; g = -(y + g_cr_cb) >> SHIFT_BITS; b = -(y + b_cb) >> SHIFT_BITS; // r = g = b = - ((y >> SHIFT_BITS) + 128); r = -(r & (r >> 63)) - 255; g = -(g & (g >> 63)) - 255; b = -(b & (b >> 63)) - 255; pixels[pixel_index + pixel_frame_width + i++] = ALPHA_MASK + ((b & (b >> 63)) + 255) + (((g & (g >> 63)) + 255) << 8) + (((r & (r >> 63)) + 255) << 16); y = y_cb_cr_pixels[0][lumminance_index + buffer_width + i] << SHIFT_BITS; r = -(y + r_cr) >> SHIFT_BITS; g = -(y + g_cr_cb) >> SHIFT_BITS; b = -(y + b_cb) >> SHIFT_BITS; // r = g = b = - ((y >> SHIFT_BITS) + 128); r = -(r & (r >> 63)) - 255; g = -(g & (g >> 63)) - 255; b = -(b & (b >> 63)) - 255; pixels[pixel_index + pixel_frame_width + i] = ALPHA_MASK + ((b & (b >> 63)) + 255) + (((g & (g >> 63)) + 255) << 8) + (((r & (r >> 63)) + 255) << 16); } lumminance_index += buffer_width << 1; pixel_index += pixel_frame_width << 1; chrominance_index += buffer_width; } movieTime = (int) videoFrame.getPlaying_time(); try { synchronized (this) { if (firstLoop) { while (buffering) { wait(); } player_state = READY_STATE; firstLoop = false; if (autoplay) { autoplay = false; playerplay(); } last_sleep_time = start_playing_time = System .currentTimeMillis(); } current_frame++; while ((player_state != PLAY_STATE) || buffering) { long start_pause_time = System.currentTimeMillis(); wait(); start_playing_time += System.currentTimeMillis() - start_pause_time; last_sleep_time = playingTime; } } long pauseTime = movieTime - playingTime; if (pauseTime > 15) { last_sleep_time = playingTime; Thread.sleep(pauseTime - 10); } else if ((playingTime - last_sleep_time) > 250) { last_sleep_time = playingTime; if ((audioPlayer != null) && (audioPlayer.isDecoding())) { Thread.sleep(10); } } } catch (InterruptedException iex) { throw new InterruptedIOException(iex.getMessage()); } } /** * 关闭当前播放资源 * * */ public void close() { playerstop(); audioSamples = new Vector<DataSample>(); videoSamples = new Vector<DataSample>(); connection_speed = movieTime = -1; video_rate = movieLength = movieDuration = video_size = -1; last_sleep_time = start_playing_time = 0; Thread workThread = movieParseThread; movieParseThread = null; if (workThread != null) { workThread.interrupt(); workThread = null; } try { if (dataBuffer != null) { dataBuffer.stop(); dataBuffer.clear(); } } catch (Exception ex) { } finally { dataBuffer = null; } } /** * 解析数据百分比 * * @param base * @param sValue * @param defaultValue * @return */ private int parsePercentValue(int base, String sValue, int defaultValue) { int value = defaultValue; if (sValue != null) { try { if (sValue.charAt(sValue.length() - 1) == '%') { value = base * Integer.parseInt(sValue.substring(0, sValue.length() - 1)) / 100; } else { value = Integer.parseInt(sValue); } } catch (Exception ex) { } if (value < 0) { value = -value; } } return value; } /** * 获得文件已播放时长信息 * * @return */ public String getPlayedDurationInfo() { return DateUtils.toMillisInfoString(videoDecoder.getBaseTime() * 1000); } /** * 获得文件时长信息 * * @return */ public String getPlayDurationInfo() { return DateUtils.toMillisInfoString(videoDecoder.getDuration() * 1000); } /** * 文件时长 * * @return */ public int getPlayDuration() { return videoDecoder.getDuration(); } /** * 文件已播放时间 * * @return */ public int getPlayTimer() { return videoDecoder.getBaseTime(); } /** * 设定播放在指定秒后自动停止 * * @param ms */ public void setMinuteAutoStop(long ms) { autoStop = ms; } public void update(long elapsedTime) { if (visible) { if (timer.action(elapsedTime)) { if (autoStop > 0 && player_state == PLAY_STATE) { if (autoStop == getPlayTimer()) { playerpause(); autoStop = -1; } } if (player_state != PLAY_STATE && wait.isRunning()) { wait.next(); } } } } public void drawUI(LGraphics g, int x, int y, int w, int h) { if (visible) { if (player_state != PLAY_STATE && wait.isRunning()) { wait.draw(g, x, y, w, h); } else { draw(g, x, y, w, h); } } } public void dispose() { this.close(); } public boolean isComplete() { return complete; } public String getUIName() { return "Player"; } public int getCurrent_frame() { return current_frame; } public void setCurrent_frame(int current_frame) { this.current_frame = current_frame; } }