精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

HarmonyOS實(shí)現(xiàn)音視頻分離合成和截取

原創(chuàng)
系統(tǒng) OpenHarmony
本篇帶給大家用HarmonyOS實(shí)現(xiàn)音視頻分離合成和截取

??想了解更多內(nèi)容,請(qǐng)?jiān)L問:??

??51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)??

??https://harmonyos.51cto.com??

音視頻分離合理直播分享

權(quán)限配置:

"reqPermissions": [
{"name": "ohos.permission.WRITE_MEDIA"},
{"name": "ohos.permission.READ_MEDIA"}
]

requestPermissionsFromUser(
new String[]{SystemPermission.WRITE_MEDIA
,SystemPermission.READ_MEDIA},0);

界面布局:

主頁(yè):

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:orientation="vertical">

<Button
ohos:id="$+id:go_separate_btn"
ohos:text="音視頻分離和合成"
ohos:width="200vp"
ohos:height="match_content"
ohos:padding="8vp"
ohos:background_element="blue"
ohos:text_color="#fff"
ohos:text_size="20fp"/>

<Button
ohos:id="$+id:go_cut_btn"
ohos:text="視頻剪切"
ohos:width="200vp"
ohos:height="match_content"
ohos:padding="8vp"
ohos:background_element="blue"
ohos:text_color="#fff"
ohos:top_margin="15vp"
ohos:text_size="20fp"/>

<Button
ohos:id="$+id:go_join_btn"
ohos:text="視頻拼接"
ohos:width="200vp"
ohos:height="match_content"
ohos:padding="8vp"
ohos:background_element="blue"
ohos:text_color="#fff"
ohos:top_margin="15vp"
ohos:text_size="20fp"/>

</DirectionalLayout>

分離合成分離性:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="start"
ohos:orientation="vertical">

<Text
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="15fp"
ohos:text_color="#000"
ohos:text="提供音頻數(shù)據(jù):"
ohos:text_alignment="left"
/>

<DirectionalLayout
ohos:id="$+id:play_directionalLayout1"
ohos:width="match_parent"
ohos:height="240vp"
ohos:alignment="center"
ohos:background_element="#000000"
/>
<DirectionalLayout
ohos:height="match_content"
ohos:width="match_parent"
ohos:alignment="vertical_center"
ohos:orientation="horizontal"
>

<Text
ohos:id="$+id:current_time1"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="00:00:00"
ohos:text_color="#000"
ohos:text_size="12vp"/>

<Slider
ohos:id="$+id:progress1"
ohos:height="35vp"
ohos:width="0vp"
ohos:start_margin="5vp"
ohos:end_margin="5vp"
ohos:orientation="horizontal"
ohos:progress_element="#FF6103"
ohos:progress_width="5vp"
ohos:weight="1"/>

<Text
ohos:id="$+id:end_time1"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="00:00:00"
ohos:text_color="#000"
ohos:text_size="12vp"/>
</DirectionalLayout>

<DirectionalLayout
ohos:width="match_parent"
ohos:height="match_content"
ohos:top_margin="0vp"
ohos:left_margin="20vp"
ohos:right_margin="20vp"
ohos:layout_alignment="horizontal_center"
ohos:orientation="horizontal">

<Button
ohos:id="$+id:start_time_btn1"
ohos:text="確定開始時(shí)間"
ohos:width="0vp"
ohos:weight="1"
ohos:height="match_content"
ohos:padding="5vp"
ohos:right_margin="10vp"
ohos:background_element="blue"
ohos:text_color="#fff"
ohos:text_size="18fp"/>

<Button
ohos:id="$+id:end_time_btn1"
ohos:text="確定結(jié)束時(shí)間"
ohos:width="0vp"
ohos:weight="1"
ohos:height="match_content"
ohos:padding="5vp"
ohos:left_margin="10vp"
ohos:layout_alignment="vertical_center"
ohos:background_element="blue"
ohos:text_color="#fff"
ohos:text_size="18fp"/>
</DirectionalLayout>
<Text
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="15fp"
ohos:text_color="#000"
ohos:text="提供視頻數(shù)據(jù):"
ohos:text_alignment="left"
ohos:top_margin="10vp"
/>

<DirectionalLayout
ohos:id="$+id:play_directionalLayout2"
ohos:width="match_parent"
ohos:height="240vp"
ohos:alignment="center"
ohos:background_element="#000000"
/>
<DirectionalLayout
ohos:height="match_content"
ohos:width="match_parent"
ohos:alignment="vertical_center"
ohos:orientation="horizontal"
>
<Text
ohos:id="$+id:current_time2"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="00:00:00"
ohos:text_color="#000"
ohos:text_size="12vp"/>

<Slider
ohos:id="$+id:progress2"
ohos:height="35vp"
ohos:width="0vp"
ohos:start_margin="5vp"
ohos:end_margin="5vp"
ohos:orientation="horizontal"
ohos:progress_element="#FF6103"
ohos:progress_width="5vp"
ohos:weight="1"/>

<Text
ohos:id="$+id:end_time2"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="00:00:00"
ohos:text_color="#000"
ohos:text_size="12vp"/>
</DirectionalLayout>
<DirectionalLayout
ohos:width="match_parent"
ohos:height="match_content"
ohos:top_margin="0vp"
ohos:left_margin="20vp"
ohos:right_margin="20vp"
ohos:layout_alignment="horizontal_center"
ohos:orientation="horizontal">

<Button
ohos:id="$+id:start_time_btn2"
ohos:text="確定開始時(shí)間"
ohos:width="0vp"
ohos:weight="1"
ohos:height="match_content"
ohos:padding="5vp"
ohos:right_margin="10vp"
ohos:background_element="blue"
ohos:text_color="#fff"
ohos:text_size="18fp"/>
<Button
ohos:id="$+id:end_time_btn2"
ohos:text="確定結(jié)束時(shí)間"
ohos:width="0vp"
ohos:weight="1"
ohos:height="match_content"
ohos:padding="5vp"
ohos:left_margin="10vp"
ohos:layout_alignment="vertical_center"
ohos:background_element="blue"
ohos:text_color="#fff"
ohos:text_size="18fp"/>
</DirectionalLayout>
<Button
ohos:id="$+id:separate_btn"
ohos:height="match_content"
ohos:width="match_content"
ohos:padding="5vp"
ohos:text="開始分離合成"
ohos:text_size="18fp"
ohos:background_element="#ff0000"
ohos:top_margin="15vp"
ohos:layout_alignment="center"
/>
</DirectionalLayout>

視頻剪切:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">
<Text
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="20fp"
ohos:text_color="#000"
ohos:text="原視頻"
ohos:text_alignment="center"
/>

<DirectionalLayout
ohos:id="$+id:cut_play_directionalLayout"
ohos:width="match_parent"
ohos:height="240vp"
ohos:alignment="center"
ohos:background_element="#000000"
/>
<DirectionalLayout
ohos:height="match_content"
ohos:width="match_parent"
ohos:alignment="vertical_center"
ohos:orientation="horizontal"
>
<Text
ohos:id="$+id:current_time"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="00:00:00"
ohos:text_color="#000"
ohos:text_size="12vp"/>
<Slider
ohos:id="$+id:progress"
ohos:height="35vp"
ohos:width="0vp"
ohos:start_margin="5vp"
ohos:end_margin="5vp"
ohos:orientation="horizontal"
ohos:progress_element="#FF6103"
ohos:progress_width="5vp"
ohos:weight="1"/>
<Text
ohos:id="$+id:end_time"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="00:00:00"
ohos:text_color="#000"
ohos:text_size="12vp"/>
</DirectionalLayout>
<DirectionalLayout
ohos:width="match_parent"
ohos:height="match_content"
ohos:top_margin="0vp"
ohos:left_margin="20vp"
ohos:right_margin="20vp"
ohos:layout_alignment="horizontal_center"
ohos:orientation="horizontal">
<Button
ohos:id="$+id:start_time_btn"
ohos:text="確定開始時(shí)間"
ohos:width="0vp"
ohos:weight="1"
ohos:height="match_content"
ohos:padding="8vp"
ohos:right_margin="10vp"
ohos:background_element="blue"
ohos:text_color="#fff"
ohos:text_size="20fp"/>
<Button
ohos:id="$+id:end_time_btn"
ohos:text="確定結(jié)束時(shí)間"
ohos:width="0vp"
ohos:weight="1"
ohos:height="match_content"
ohos:padding="8vp"
ohos:left_margin="10vp"
ohos:layout_alignment="vertical_center"
ohos:background_element="blue"
ohos:text_color="#fff"
ohos:text_size="20fp"/>
</DirectionalLayout>
<Button
ohos:id="$+id:cut_btn"
ohos:height="match_content"
ohos:width="match_content"
ohos:padding="8vp"
ohos:text="開始剪切"
ohos:text_size="22fp"
ohos:background_element="#ff0000"
ohos:top_margin="15vp"
ohos:layout_alignment="center"
/>
</DirectionalLayout>

工具類:

讀寫外部存儲(chǔ)公共目錄工具:

public class StorageFileUtils {
public enum MediaType{
VIDEO,
IMAGE,
AUDIO,
DOWNLOADS
}

/**
* 獲取媒體文件保存的外部存儲(chǔ)公共目錄的fd,為了讀,查詢
* @param context
* @param fileName
* @return
*/
public static FileDescriptor getPublicFileFdForRead(Context context,MediaType type,String fileName){
DataAbilityHelper helper = DataAbilityHelper.creator(context); //api7以后,create方法替代了
Uri externalDataAbilityUri = null;
switch (type){
case VIDEO:
externalDataAbilityUri = AVStorage.Video.Media.EXTERNAL_DATA_ABILITY_URI;
break;
case IMAGE:
externalDataAbilityUri = AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI;
break;
case DOWNLOADS:
externalDataAbilityUri = AVStorage.Downloads.EXTERNAL_DATA_ABILITY_URI;
break;
case AUDIO:
externalDataAbilityUri = AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI;
break;
}
ResultSet rs = null;
FileDescriptor fileDescriptor = null;
try {
DataAbilityPredicates predicates =
new DataAbilityPredicates("_display_name = '" + fileName + "'");
rs = helper.query(externalDataAbilityUri,new String[]{AVStorage.Video.Media.ID},predicates);
System.out.println("rs count:" + rs.getRowCount());
if(rs != null){
while (rs.goToNextRow()) {
int mediaId = rs.getInt(rs.getColumnIndexForName(AVStorage.Video.Media.ID));
Uri uri = Uri.appendEncodedPathToUri(externalDataAbilityUri,"" + mediaId);
fileDescriptor = helper.openFile(uri, "r");
return fileDescriptor;
}
}
} catch (Exception e) {
System.out.println("rs read error!");
e.printStackTrace();
} finally {
if (rs != null) {
rs.close();
}
}
return fileDescriptor;
}

/**
* 獲取媒體文件保存的外部存儲(chǔ)公共目錄的fd,為了寫,插入
* @param context
* @param type
* @param name
* @return
*/
public static FileDescriptor getPublicFdForInsert(Context context,
MediaType type, String name) {
DataAbilityHelper helper = DataAbilityHelper.creator(context);
Uri externalDataAbilityUri = null;
ValuesBucket vb = new ValuesBucket();
switch (type){
case VIDEO:
externalDataAbilityUri = AVStorage.Video.Media.EXTERNAL_DATA_ABILITY_URI;
vb.putString(AVStorage.Video.Media.DISPLAY_NAME,name);
break;
case IMAGE:
externalDataAbilityUri = AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI;
vb.putString(AVStorage.Images.Media.DISPLAY_NAME,name);
break;
case DOWNLOADS:
externalDataAbilityUri = AVStorage.Downloads.EXTERNAL_DATA_ABILITY_URI;
vb.putString(AVStorage.Downloads.DISPLAY_NAME,name);
break;
case AUDIO:
externalDataAbilityUri = AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI;//這里uri對(duì)應(yīng)目錄
vb.putString(AVStorage.Audio.Media.DISPLAY_NAME,name);
break;
}
FileOutputStream outputStream = null;
FileDescriptor fd = null;
try {
int id = helper.insert(externalDataAbilityUri, vb);
System.out.println("insert rs:" + id);
Uri uri = Uri.appendEncodedPathToUri(externalDataAbilityUri, ""+id); //這個(gè)uri對(duì)應(yīng)文件
outputStream = (FileOutputStream) helper.obtainOutputStream(uri);
fd = outputStream.getFD();
return fd;
} catch (Exception e) {
System.out.println(" helper.insert error!");
e.printStackTrace();
}finally {
if(outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return fd;
}
}

視頻處理核心工具類:

public class MediaHandler {
public static boolean combineTwoVideos(Context context,
FileDescriptor audioFd,
int audioStartTime,
int audioEndTime,
FileDescriptor videoFd,
int videoStartTime,
int videoEndTime,
FileDescriptor outFd) {
if(audioFd == null || videoFd==null){
System.out.println("=======audioSrcFd或者framesSrcFd文件沒讀到!");
return false;
}

Extractor audioExtractor = new Extractor();
int mainAudioExtractorTrackIndex = -1; //(提供音頻的)視頻的音頻軌道號(hào)
int mainAudioMuxerTrackIndex = -1; //合成后的視頻的音頻軌
int mainAudioMaxInputSize = 0; //能獲取的音頻的最大值

Extractor frameExtractor = new Extractor();
int frameExtractorTrackIndex = -1; //(提供畫面的)視頻的視頻軌
int frameMuxerTrackIndex = -1; //合成后的視頻的視頻軌
int frameMaxInputSize = 0; //能獲取的視頻的最大值
int frameRate = 0; //視頻的幀率
long frameDuration = 0;

Muxer muxer = null; //用于合成音頻與視頻

try {
muxer = new Muxer(outFd,Muxer.MediaFileFormat.FORMAT_MPEG4);

//音軌信息
audioExtractor.setSource(new Source(audioFd)); //設(shè)置視頻源
int audioTrackCount = audioExtractor.getTotalStreams(); //獲取數(shù)據(jù)源的軌道數(shù)
//在此循環(huán)軌道數(shù),目的是找到我們想要的音頻軌
for (int i = 0; i < audioTrackCount; i++) {
Format format = audioExtractor.getStreamFormat(i);//得到指定索引的記錄格式
String mimeType = format.getStringValue(Format.MIME);
System.out.println("=======mimeType:"+mimeType);
if (mimeType.startsWith("audio/")) { //找到音軌
mainAudioExtractorTrackIndex = i;
mainAudioMuxerTrackIndex = muxer.appendTrack(format); //將音軌添加到Muxer,并返回新的軌道
mainAudioMaxInputSize = format.getIntValue(Format.MAX_INPUT_SIZE);
//得到能獲取的有關(guān)音頻的最大值
}
}

//圖像信息
frameExtractor.setSource(new Source(videoFd)); //設(shè)置視頻源
int trackCount = frameExtractor.getTotalStreams();//獲取數(shù)據(jù)源的軌道數(shù)
//在此循環(huán)軌道數(shù),目的是找到我們想要的視頻軌
for (int i = 0; i < trackCount; i++) {
Format vedioFormat = frameExtractor.getStreamFormat(i);
String vedioMimeType = vedioFormat.getStringValue(Format.MIME);
if (vedioMimeType.startsWith("video/")) { //找到視頻軌
frameExtractorTrackIndex = i;
frameMuxerTrackIndex = muxer.appendTrack(vedioFormat); //將視頻軌添加到Muxer,并返回新的軌道
frameMaxInputSize = vedioFormat.getIntValue(Format.MAX_INPUT_SIZE);
frameRate = vedioFormat.getIntValue(Format.FRAME_RATE); //獲取視頻的幀率
frameDuration = vedioFormat.getLongValue(Format.DURATION); //獲取視頻時(shí)長(zhǎng)
}
}

muxer.start(); //開始合成
audioExtractor.specifyStream(mainAudioExtractorTrackIndex); //將提供音頻的視頻選擇到音軌上
BufferInfo bufferInfo = new BufferInfo();
ByteBuffer audioByteBuffer = ByteBuffer.allocate(mainAudioMaxInputSize);
while (true) {
int readSampleSize = audioExtractor.readBuffer(audioByteBuffer, 0);
//檢索當(dāng)前編碼的樣本并將其存儲(chǔ)在字節(jié)緩沖區(qū)中
long audioSampleTime = audioExtractor.getFrameTimestamp(); //獲取當(dāng)前展示樣本的時(shí)間(單位毫秒)
if (readSampleSize < 0) { //如果沒有可獲取的樣本則退出循環(huán)
audioExtractor.unspecifyStream(mainAudioExtractorTrackIndex);
break;
}

if (audioSampleTime < audioStartTime*1000) { //如果樣本時(shí)間小于我們想要的開始時(shí)間就快進(jìn)
System.out.println("audioSampleTime < audioStartTime:"
+ audioSampleTime +","+ audioStartTime*1000);
audioExtractor.next(); //推進(jìn)到下一個(gè)樣本,類似快進(jìn)
continue;
}
//如果樣本時(shí)間大于結(jié)束時(shí)間,就退出循環(huán)
if (audioSampleTime > audioEndTime*1000) {
System.out.println("audioSampleTime > audioEndTime:" + audioSampleTime
+","+ audioEndTime*1000);
audioExtractor.unspecifyStream(mainAudioExtractorTrackIndex);
break;
}
//設(shè)置樣本編碼信息
bufferInfo.size = readSampleSize;
bufferInfo.offset = 0;
bufferInfo.bufferType = audioExtractor.getFrameType();
bufferInfo.timeStamp = audioSampleTime - audioStartTime*1000;

muxer.writeBuffer(mainAudioMuxerTrackIndex, audioByteBuffer, bufferInfo); //將樣本寫入
audioExtractor.next(); //推進(jìn)到下一個(gè)樣本,類似快進(jìn)
System.out.println("=======正在合成音頻...");
}

frameExtractor.specifyStream(frameExtractorTrackIndex); //將提供視頻圖像的視頻選擇到視頻軌上
BufferInfo vedioBufferInfo = new BufferInfo();
ByteBuffer videoByteBuffer = ByteBuffer.allocate(frameMaxInputSize);
while (true) {
int readSampleSize = frameExtractor.readBuffer(videoByteBuffer, 0);
//檢索當(dāng)前編碼的樣本并將其存儲(chǔ)在字節(jié)緩沖區(qū)中
if (readSampleSize < 0) { //如果沒有可獲取的樣本則退出循環(huán)
frameExtractor.unspecifyStream(frameExtractorTrackIndex);
break;
}

long videoSampleTime = frameExtractor.getFrameTimestamp(); //獲取當(dāng)前展示樣本的時(shí)間(單位毫秒)
if (videoSampleTime < videoStartTime*1000) { //如果樣本時(shí)間小于我們想要的開始時(shí)間就快進(jìn)
System.out.println("videoSampleTime < videoStartTime:"
+ videoSampleTime +","+ videoStartTime*1000);
frameExtractor.next(); //推進(jìn)到下一個(gè)樣本,類似快進(jìn)
continue;
}
//如果樣本時(shí)間大于結(jié)束時(shí)間,就退出循環(huán)
if (videoSampleTime > videoEndTime*1000) {
System.out.println("videoSampleTime > videoEndTime:"
+ videoSampleTime +","+ videoEndTime*1000);
frameExtractor.unspecifyStream(mainAudioExtractorTrackIndex);
break;
}
//設(shè)置樣本編碼信息
vedioBufferInfo.size = readSampleSize;
vedioBufferInfo.offset = 0;
vedioBufferInfo.bufferType = frameExtractor.getFrameType();
vedioBufferInfo.timeStamp += 1000 * 1000 / frameRate; //每幀的時(shí)間是 1/frameRate秒,需轉(zhuǎn)成微秒

muxer.writeBuffer(frameMuxerTrackIndex, videoByteBuffer, vedioBufferInfo); //將樣本寫入
frameExtractor.next(); //推進(jìn)到下一個(gè)樣本,類似快進(jìn)
System.out.println("=======正在合成視頻...");
}
System.out.println("=======合成完畢");
return true;
}catch (Exception e){
System.out.println("==========combineTwoVideos出錯(cuò)了!");
return false;
}finally {
//釋放資源
audioExtractor.release();
frameExtractor.release();
if (muxer != null) {
muxer.release();
}
}
}
}

毫秒轉(zhuǎn)00:00:00格式字符串工具:

public class DateUtils {
private static final int ONE_SECONDS_MS = 1000;
private static final int ONE_MINS_MINUTES = 60;
private static final int NUMBER = 16;
private static final String TIME_FORMAT = "%02d";
private static final String SEMICOLON = ":";

public static String msToString(int ms) {
StringBuilder sb = new StringBuilder(NUMBER);
int seconds = ms / ONE_SECONDS_MS;
int minutes = seconds / ONE_MINS_MINUTES;
if (minutes > ONE_MINS_MINUTES) {
sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, minutes / ONE_MINS_MINUTES));
sb.append(SEMICOLON);
sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, minutes % ONE_MINS_MINUTES));
sb.append(SEMICOLON);
} else {
sb.append("00:");
sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, minutes));
sb.append(SEMICOLON);
}

if (seconds > minutes * ONE_MINS_MINUTES) {
sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, seconds - minutes * ONE_MINS_MINUTES));
} else {
sb.append("00");
}
return sb.toString();
}
}

視頻播放器工具:

public class PlayerHandler {
private Player videoPlayer;
private Context context;
private Runnable videoRunnable;
private boolean isFirstPlay = true;
private EventHandler handler = new EventHandler(EventRunner.create());
private PlayerStateInterface playerStateInterface;
private PlayerCurrentTimeInterface playerCurrentTimeInterface;
public static interface PlayerCurrentTimeInterface{
void updateCurrentTime(int currentTime);
}

public void setPlayerCurrentTimeInterface(PlayerCurrentTimeInterface pcti){
this.playerCurrentTimeInterface = pcti;
}

private Timer timer = new Timer();
private TimerTask timerTask = null;

public PlayerHandler(Context context) {
this.context = context;
}

public synchronized void startPlay(Source source, Surface surface) {
if(videoPlayer == null){
videoPlayer = new Player(context);
}
videoPlayer.setPlayerCallback(new VideoCallBack());
System.out.println("======isFirstPlay:"+isFirstPlay);
if(isFirstPlay){
videoRunnable = () -> firstPlay(source, surface);
handler.postTask(videoRunnable);
isFirstPlay = false;
}else{
if(!videoPlayer.isNowPlaying()){
handler.removeTask(videoRunnable);
videoRunnable = () -> play();
handler.postTask(videoRunnable);
}
}
timer.purge();
if(timerTask==null){
timerTask = new TimerTask() {
@Override
public void run() {
playerCurrentTimeInterface.updateCurrentTime(getCurrentTime());
}
};
}
timer.schedule(timerTask, 0, 1000);
}

private void firstPlay(Source source, Surface surface) {
videoPlayer.setSource(source);
videoPlayer.setVideoSurface(surface);
videoPlayer.prepare();
videoPlayer.play();
}
private void play() {
if (videoPlayer == null) {
return;
}
videoPlayer.play();
}
public synchronized void pausePlay() {
if (videoPlayer == null) {
return;
}
videoPlayer.pause();
timerTask.cancel();
timerTask = null;//如果不重新new,會(huì)報(bào)異常
}

public void rewindTo(long ms) {
if (videoPlayer == null) {
return;
}
System.out.println("ms:" + ms);
videoPlayer.rewindTo(ms*1000);
}

public void release() {
if (videoPlayer != null) {
videoPlayer.stop();
videoPlayer.release();
videoPlayer = null;
timer.cancel();
timer = null;
}
}

public int getCurrentTime(){
if (videoPlayer == null) {
return 0;
}
return videoPlayer.getCurrentTime();
}

public static interface PlayerStateInterface {
void updateTotalTime(int totalTime);
}

public void setPlayerStateInterface(PlayerStateInterface psi){
this.playerStateInterface = psi;
}
private class VideoCallBack implements Player.IPlayerCallback{

@Override
public void onPrepared() {
playerStateInterface.updateTotalTime(videoPlayer.getDuration());
}

@Override
public void onMessage(int i, int i1) {

}

@Override
public void onError(int i, int i1) {

}

@Override
public void onResolutionChanged(int i, int i1) {

}

@Override
public void onPlayBackComplete() {

}

@Override
public void onRewindToComplete() {
}

@Override
public void onBufferingChange(int i) {

}

@Override
public void onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) {

}

@Override
public void onMediaTimeIncontinuity(Player.MediaTimeInfo mediaTimeInfo) {

}
}

}

業(yè)務(wù)邏輯實(shí)現(xiàn):

MainAbilitySlice:從外部存儲(chǔ)公共目錄里讀取視頻文件,調(diào)整到分了合成頁(yè)面或剪切頁(yè)面:

public class MainAbilitySlice extends AbilitySlice {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
initComponents();
}
private void initComponents() {
Component goCutBtn = findComponentById(ResourceTable.Id_go_cut_btn);
goCutBtn.setClickedListener(this::goCutBtnFunc);
Component goSeparateBtn = findComponentById(ResourceTable.Id_go_separate_btn);
goSeparateBtn.setClickedListener(this::goSeparateBtnFunc);
}
private void goSeparateBtnFunc(Component component) {
Intent intent = new Intent();
Operation build = new Intent.OperationBuilder()
.withBundleName(getBundleName())
.withDeviceId("")
.withAbilityName(SeparateAbility.class.getName())
.build();
intent.setParam("separateFiles",new String[]{"audioFile.mp4","videoFile.mp4"});
intent.setOperation(build);
startAbility(intent);
}

private void goCutBtnFunc(Component component) {
//這里可以做的更靈活一定,做一個(gè)文件列表讀取sd卡上的視頻文件,選擇要處理的拿出來它的文件名
Intent intent = new Intent();
Operation build = new Intent.OperationBuilder()
.withBundleName(getBundleName())
.withDeviceId("")
.withAbilityName(CutAbility.class.getName())
.build();
intent.setParam("cutFile","cut.mp4");
intent.setOperation(build);
startAbility(intent);
}

@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
}

視頻分離合成的邏輯:

public class SeparateAbilitySlice extends AbilitySlice {
private String[] separateFiles;
private FileDescriptor audioFd;
private FileDescriptor videoFd;
private SurfaceProvider audioSurfaceProvider;
private Surface audioSurface;
private SurfaceProvider videoSurfaceProvider;
private Surface videoSurface;
private PlayerHandler audioPlayerHandler;
private PlayerHandler videoPlayerHandler;
private boolean audioClick = false;
private boolean videoClick = false;
private int audioTotalTime;
private int videoTotalTime;
private Slider audioProgressBar;
private Slider videoProgressBar;
private Button startTime1,startTime2,endTime1,endTime2;
private Text currentTime1,currentTime2;
private int startAudioTime1,startVideoTimt2,endAudioTime1,endVideoTime2;
private Button separateBtn;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_separate);
//初始化組件
initCompoents();
//拿到參數(shù)和分離合成文件
initParam(intent);
//使用播放器播放視頻
initSurfaceProvider();
//設(shè)置組件的監(jiān)聽
initListeners();
}

private void initListeners() {
audioProgressBar.setValueChangedListener(new Slider.ValueChangedListener() {
@Override
public void onProgressUpdated(Slider slider, int value, boolean isB) {
getUITaskDispatcher().asyncDispatch(() ->
currentTime1.setText(DateUtils.msToString(value)));
}

@Override
public void onTouchStart(Slider slider) {

}

@Override
public void onTouchEnd(Slider slider) {
if (slider.getProgress() == audioTotalTime) {
audioPlayerHandler.release();
} else {
audioPlayerHandler.rewindTo(slider.getProgress());
}
}
});

videoProgressBar.setValueChangedListener(new Slider.ValueChangedListener() {
@Override
public void onProgressUpdated(Slider slider, int value, boolean isB) {
getUITaskDispatcher().asyncDispatch(() ->
currentTime2.setText(DateUtils.msToString(value)));
}

@Override
public void onTouchStart(Slider slider) {

}

@Override
public void onTouchEnd(Slider slider) {
if (slider.getProgress() == videoTotalTime) {
videoPlayerHandler.release();
} else {
videoPlayerHandler.rewindTo(slider.getProgress());
}
}
});
startTime1.setClickedListener(component -> {
startAudioTime1 = audioPlayerHandler.getCurrentTime();
startTime1.setText(DateUtils.msToString(startAudioTime1));
});

startTime2.setClickedListener(component -> {
startVideoTimt2 = videoPlayerHandler.getCurrentTime();
startTime2.setText(DateUtils.msToString(startVideoTimt2));
});

endTime1.setClickedListener(component -> {
endAudioTime1 = audioPlayerHandler.getCurrentTime();
endTime1.setText(DateUtils.msToString(endAudioTime1));
});

endTime2.setClickedListener(component -> {
endVideoTime2 = videoPlayerHandler.getCurrentTime();
endTime2.setText(DateUtils.msToString(endVideoTime2));
});

separateBtn.setClickedListener(component -> {
FileDescriptor outFd = StorageFileUtils.getPublicFdForInsert(this
, StorageFileUtils.MediaType.VIDEO, "combineFile.mp4");
boolean rs = MediaHandler.combineTwoVideos(this,audioFd,startAudioTime1,endAudioTime1
,videoFd,startVideoTimt2,endVideoTime2,outFd);
if (rs){
getUITaskDispatcher().asyncDispatch(()->{
new ToastDialog(this).setText("合成完成").show();
});
}
});
}
private void initCompoents() {
audioProgressBar = (Slider) findComponentById(ResourceTable.Id_progress1);
videoProgressBar = (Slider) findComponentById(ResourceTable.Id_progress2);
startTime1 = (Button)findComponentById(ResourceTable.Id_start_time_btn1);
startTime2 = (Button)findComponentById(ResourceTable.Id_start_time_btn2);
endTime1 = (Button)findComponentById(ResourceTable.Id_end_time_btn1);
endTime2 = (Button)findComponentById(ResourceTable.Id_end_time_btn2);
currentTime1 = (Text) findComponentById(ResourceTable.Id_current_time1);
currentTime2 = (Text) findComponentById(ResourceTable.Id_current_time2);
separateBtn = (Button)findComponentById(ResourceTable.Id_separate_btn);
}
private void initSurfaceProvider() {
audioSurfaceProvider = new SurfaceProvider(this);
audioSurfaceProvider.getSurfaceOps().get().addCallback(new AudioSurfaceCallBack());
audioSurfaceProvider.pinToZTop(true);
DirectionalLayout directionalLayout1 =
(DirectionalLayout) findComponentById(ResourceTable.Id_play_directionalLayout1);
directionalLayout1.addComponent(audioSurfaceProvider);

videoSurfaceProvider = new SurfaceProvider(this);
videoSurfaceProvider.getSurfaceOps().get().addCallback(new VedioSurfaceCallBack());
videoSurfaceProvider.pinToZTop(true);
DirectionalLayout directionalLayout2 =
(DirectionalLayout) findComponentById(ResourceTable.Id_play_directionalLayout2);
directionalLayout2.addComponent(videoSurfaceProvider);
}
private class AudioSurfaceCallBack implements SurfaceOps.Callback{
@Override
public void surfaceCreated(SurfaceOps surfaceOps) {
System.out.println("======audio surfaceCreated");
if (audioSurfaceProvider.getSurfaceOps().isPresent()) {
audioSurface = audioSurfaceProvider.getSurfaceOps().get().getSurface();
initAudioPlayer(audioSurface);
}
}
@Override
public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {}
@Override
public void surfaceDestroyed(SurfaceOps surfaceOps) {}
}

private class VedioSurfaceCallBack implements SurfaceOps.Callback{
@Override
public void surfaceCreated(SurfaceOps surfaceOps) {
System.out.println("======video surfaceCreated");
if (videoSurfaceProvider.getSurfaceOps().isPresent()) {
videoSurface = videoSurfaceProvider.getSurfaceOps().get().getSurface();
initVideoPlayer(videoSurface);
}
}
@Override
public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {}
@Override
public void surfaceDestroyed(SurfaceOps surfaceOps) {}
}

private void initAudioPlayer(Surface audioSurface) {
System.out.println("======initAudioPlayer");
audioPlayerHandler = new PlayerHandler(getApplicationContext());
audioPlayerHandler.setPlayerStateInterface(new PlayerHandler.PlayerStateInterface(){
@Override
public void updateTotalTime(int totalTime) {
System.out.println("======slice totalTime:" + totalTime);
audioTotalTime = totalTime;
getUITaskDispatcher().asyncDispatch(()->{
Text time1 = (Text)findComponentById(ResourceTable.Id_end_time1);
time1.setText(DateUtils.msToString(totalTime));
audioProgressBar.setMaxValue(totalTime);
});
}
});
audioPlayerHandler.setPlayerCurrentTimeInterface(new PlayerHandler.PlayerCurrentTimeInterface() {
@Override
public void updateCurrentTime(int currentTime) {
getUITaskDispatcher().asyncDispatch(()->{
audioProgressBar.setProgressValue(currentTime);
});
}
});
Source source = new Source(audioFd);
audioSurfaceProvider.setClickedListener(component -> {
if(!audioClick){
audioClick = !audioClick;
audioPlayerHandler.startPlay(source, audioSurface);
}else{
audioClick = !audioClick;
audioPlayerHandler.pausePlay();
}
});
}
private void initVideoPlayer(Surface audioSurface) {
System.out.println("======initVideoPlayer");
videoPlayerHandler = new PlayerHandler(getApplicationContext());
videoPlayerHandler.setPlayerStateInterface(new PlayerHandler.PlayerStateInterface(){
@Override
public void updateTotalTime(int totalTime) {
videoTotalTime = totalTime;
getUITaskDispatcher().asyncDispatch(()->{
Text time2 = (Text)findComponentById(ResourceTable.Id_end_time2);
time2.setText(DateUtils.msToString(totalTime));
videoProgressBar.setMaxValue(totalTime);
});
}
});
videoPlayerHandler.setPlayerCurrentTimeInterface(new PlayerHandler.PlayerCurrentTimeInterface() {
@Override
public void updateCurrentTime(int currentTime) {
videoProgressBar.setProgressValue(currentTime);
}
});
Source source = new Source(videoFd);
videoSurfaceProvider.setClickedListener(component -> {
if(!videoClick){
videoClick = !videoClick;
videoPlayerHandler.startPlay(source, videoSurface);
}else{
videoClick = !videoClick;
videoPlayerHandler.pausePlay();
}
});
}

private void initParam(Intent intent) {
if(intent != null){
separateFiles = intent.getStringArrayParam("separateFiles");
System.out.println("=====" + Arrays.toString(separateFiles));
if(separateFiles.length == 2){
audioFd = StorageFileUtils.getPublicFileFdForRead(
this,
StorageFileUtils.MediaType.VIDEO,
separateFiles[0]
);
videoFd = StorageFileUtils.getPublicFileFdForRead(
this,
StorageFileUtils.MediaType.VIDEO,
separateFiles[1]
);
}
}
}
@Override
protected void onStop() {
super.onStop();
audioPlayerHandler.release();
videoSurfaceProvider.release();
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
}

視頻截取邏輯代碼:

public class CutAbilitySlice extends AbilitySlice {
private Slider videoProgressBar;
private Button startTime;
private Button endTime;
private Button cutBtn;
private String cutFile;
private FileDescriptor videoFd;
private SurfaceProvider videoSurfaceProvider;
private Surface videoSurface;
private PlayerHandler videoPlayerHandler;
private int videoTotalTime;
private boolean videoClick;
private Text currentTimeText;
private int startVideoTime;
private int endVideoTime;

@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_cut);
//初始化組件
initCompoents();
//拿到參數(shù)和分離合成文件
initParam(intent);
//使用播放器播放視頻
initSurfaceProvider();
//設(shè)置組件的監(jiān)聽
initListeners();
}
private void initCompoents() {
videoProgressBar = (Slider) findComponentById(ResourceTable.Id_progress);
startTime = (Button)findComponentById(ResourceTable.Id_start_time_btn);
endTime = (Button)findComponentById(ResourceTable.Id_end_time_btn);
cutBtn = (Button)findComponentById(ResourceTable.Id_cut_btn);
currentTimeText = (Text) findComponentById(ResourceTable.Id_current_time);
}

private void initParam(Intent intent) {
if(intent != null){
cutFile = intent.getStringParam("cutFile");
videoFd = StorageFileUtils.getPublicFileFdForRead(
this,
StorageFileUtils.MediaType.VIDEO,
cutFile
);
}
}
private void initSurfaceProvider() {
videoSurfaceProvider = new SurfaceProvider(this);
videoSurfaceProvider.getSurfaceOps().get().addCallback(new VedioSurfaceCallBack());
videoSurfaceProvider.pinToZTop(true);
DirectionalLayout directionalLayout =
(DirectionalLayout) findComponentById(ResourceTable.Id_cut_play_directionalLayout);
directionalLayout.addComponent(videoSurfaceProvider);
}
private class VedioSurfaceCallBack implements SurfaceOps.Callback{
@Override
public void surfaceCreated(SurfaceOps surfaceOps) {
System.out.println("======video surfaceCreated");
if (videoSurfaceProvider.getSurfaceOps().isPresent()) {
videoSurface = videoSurfaceProvider.getSurfaceOps().get().getSurface();
initVideoPlayer(videoSurface);
}
}
@Override
public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {}
@Override
public void surfaceDestroyed(SurfaceOps surfaceOps) {}
}
private void initVideoPlayer(Surface audioSurface) {
System.out.println("======initVideoPlayer");
videoPlayerHandler = new PlayerHandler(getApplicationContext());
videoPlayerHandler.setPlayerStateInterface(new PlayerHandler.PlayerStateInterface(){
@Override
public void updateTotalTime(int totalTime) {
videoTotalTime = totalTime;
getUITaskDispatcher().asyncDispatch(()->{
Text time = (Text)findComponentById(ResourceTable.Id_end_time);
time.setText(DateUtils.msToString(totalTime));
videoProgressBar.setMaxValue(totalTime);
});
}
});
videoPlayerHandler.setPlayerCurrentTimeInterface(new PlayerHandler.PlayerCurrentTimeInterface() {
@Override
public void updateCurrentTime(int currentTime) {
videoProgressBar.setProgressValue(currentTime);
}
});
Source source = new Source(videoFd);
videoSurfaceProvider.setClickedListener(component -> {
if(!videoClick){
videoClick = !videoClick;
videoPlayerHandler.startPlay(source, videoSurface);
}else{
videoClick = !videoClick;
videoPlayerHandler.pausePlay();
}
});
}
private void initListeners() {
videoProgressBar.setValueChangedListener(new Slider.ValueChangedListener() {
@Override
public void onProgressUpdated(Slider slider, int value, boolean isB) {
getUITaskDispatcher().asyncDispatch(() ->
currentTimeText.setText(DateUtils.msToString(value)));
}

@Override
public void onTouchStart(Slider slider) {

}

@Override
public void onTouchEnd(Slider slider) {
if (slider.getProgress() == videoTotalTime) {
videoPlayerHandler.release();
} else {
videoPlayerHandler.rewindTo(slider.getProgress());
}
}
});
startTime.setClickedListener(component -> {
startVideoTime = videoPlayerHandler.getCurrentTime();
startTime.setText(DateUtils.msToString(startVideoTime));
});
endTime.setClickedListener(component -> {
endVideoTime = videoPlayerHandler.getCurrentTime();
endTime.setText(DateUtils.msToString(endVideoTime));
});

cutBtn.setClickedListener(component -> {
FileDescriptor outFd = StorageFileUtils.getPublicFdForInsert(this
, StorageFileUtils.MediaType.VIDEO, "cutFileRs.mp4");
boolean rs = MediaHandler.combineTwoVideos(this,videoFd,startVideoTime,endVideoTime
,videoFd,startVideoTime,endVideoTime,outFd);
if (rs){
getUITaskDispatcher().asyncDispatch(()->{
new ToastDialog(this).setText("剪切完成").show();
});
}
});
}
@Override
protected void onStop() {
super.onStop();
videoSurfaceProvider.release();
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
}

??想了解更多內(nèi)容,請(qǐng)?jiān)L問:??

??51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)??

??https://harmonyos.51cto.com??

責(zé)任編輯:jianghua 來源: 鴻蒙社區(qū)
相關(guān)推薦

2022-08-29 10:39:32

FFmpeg多媒體框架開源

2017-12-22 22:13:22

語(yǔ)音視頻SDK延遲

2024-10-15 13:30:03

2022-06-20 05:50:41

抖音春節(jié)活動(dòng)視頻發(fā)紅包

2023-03-03 15:40:43

抖音視頻編碼器

2021-11-04 16:05:08

鴻蒙HarmonyOS應(yīng)用

2017-12-22 22:33:04

游戲語(yǔ)音音視頻社交

2018-03-07 22:08:16

游戲語(yǔ)音

2010-09-30 15:07:59

必應(yīng)詞典微軟搜索

2022-09-21 11:48:40

端到端音視頻測(cè)試用戶體驗(yàn)

2022-06-20 05:59:35

5G技術(shù)音視頻技術(shù)安卓系統(tǒng)

2017-12-22 21:06:55

語(yǔ)音視頻SDK聽聲辨位

2025-05-14 07:35:27

UVR5合成管道集成

2024-02-28 08:22:07

2011-11-17 16:26:49

AndroidAdobeAIR

2020-09-27 10:40:06

音視頻即構(gòu)科技開源中國(guó)

2013-03-05 14:03:01

傲游云瀏覽器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

免费毛片网站在线观看| 欧美精品黑人性xxxx| **亚洲第一综合导航网站| 精品在线免费观看视频| 自拍偷拍精品| 欧美日韩你懂得| 一区二区三区欧美在线| 精品人妻伦一区二区三区久久 | 亚洲久久成人| 亚洲视频国产视频| 久久综合在线观看| 亚洲午夜天堂| 亚洲欧洲精品一区二区三区| 亚洲自拍中文字幕| 日韩精品在线一区二区三区| 欧美一区高清| 在线精品播放av| av影片在线播放| 日本少妇一区| 欧美日韩国产精品专区| 日本一本草久p| 国产小视频免费在线网址| 麻豆视频观看网址久久| 91黑丝高跟在线| 国产suv精品一区二区68| 五月天亚洲色图| 欧美一级欧美三级| 无限资源日本好片| 在线观看爽视频| 亚洲一区二区三区四区在线免费观看| 亚洲成人一区二区三区| 欧美日韩激情视频一区二区三区| 国产一区二区免费看| 国产精品美女免费| 国产亚洲精品久久久久久无几年桃| 久久综合国产| 国产亚洲在线播放| 欧美熟妇一区二区| 国产主播性色av福利精品一区| 在线成人免费视频| www.日日操| 美女100%一区| 欧美性猛交xxxx乱大交蜜桃| 波多野结衣乳巨码无在线| 欧美1234区| 樱桃视频在线观看一区| 欧美精品久久96人妻无码| 成人精品一区| 欧美国产在线观看| 日韩高清国产精品| 国产精品99999| 国产日韩三级在线| 日韩中文字幕一区二区| 国产精品免费播放| 国产精品青草久久| 在线视频不卡国产| 国产精品扒开做爽爽爽的视频| 中文字幕av一区二区三区高| 亚洲aⅴ天堂av在线电影软件| 久久久久久久久亚洲精品| 久久影院电视剧免费观看| 久久本道综合色狠狠五月| 亚洲欧美色视频| 久久老女人爱爱| 亚洲二区三区四区| 麻豆tv在线| 亚洲视频在线观看一区| 日韩成人手机在线| 国产社区精品视频| 色国产综合视频| www.com黄色片| 精品一区视频| 亚洲福利精品在线| 素人fc2av清纯18岁| 欧美伦理在线视频| 不卡av在线网站| 18精品爽视频在线观看| 亚洲一区二区三区高清不卡| 国产成人一区二区三区电影| 91精品国自产| 不卡视频在线观看| 欧洲精品久久| 国产婷婷视频在线| 性久久久久久久久久久久| 黄色片一级视频| 日韩专区视频| 亚洲精品电影在线| 色噜噜日韩精品欧美一区二区| 欧美日韩国产一区二区三区不卡| 久久精品视频导航| 色婷婷av国产精品| 精品一区二区三区香蕉蜜桃 | 免费观看成年在线视频网站| 国产精品久久久久久久浪潮网站| www国产无套内射com| 亚洲v.com| 制服丝袜亚洲色图| aa片在线观看视频在线播放| 久久国产成人精品| 97精品伊人久久久大香线蕉 | 性欧美精品一区二区三区在线播放 | 国语一区二区三区| 中文国产成人精品| 日本在线视频中文字幕| 老汉av免费一区二区三区| 国产精品一区二区三区在线观| 高清av在线| 性做久久久久久| 在线播放av中文字幕| 婷婷精品视频| 精品中文字幕在线2019| 真实的国产乱xxxx在线91| 国产91在线看| 中文字幕中文字幕一区三区| 亚洲一区站长工具| 精品久久久影院| 日本成人免费在线观看| 久久精品国产清高在天天线| 51成人做爰www免费看网站| 电影av一区| 狠狠干狠狠久久| 精品人妻在线视频| 亚洲国产一成人久久精品| 国产精品久久久久77777| 五月天婷婷视频| 亚洲影院久久精品| 一本之道在线视频| 99九九热只有国产精品| 国产成人啪精品视频免费网| 午夜国产在线观看| 亚洲成人一区二区| 色欲无码人妻久久精品| 国产精品传媒精东影业在线| 国产精品第一页在线| 久草在现在线| 欧美午夜片欧美片在线观看| 免费黄色三级网站| 狠狠色狠狠色综合日日tαg | 欧美xxxx在线| 久久久久久久香蕉网| 精品国产九九九| 亚洲精品美国一| 久久久久中文字幕亚洲精品| 欧美理论在线| 91精品网站| 午夜影院免费在线| 日韩一区二区在线播放| 农村妇女精品一区二区| 国产酒店精品激情| 狠狠精品干练久久久无码中文字幕| 亚洲一区二区三区久久久| 日韩最新在线视频| 国产精品毛片一区二区在线看舒淇| 国产精品美女久久久久高潮| 在线观看av网页| 婷婷久久综合| 亚洲影院色无极综合| 欧美videosex性欧美黑吊| 精品国产乱码久久| 久久不卡免费视频| 久久日一线二线三线suv| 欧美综合在线观看视频| 欧美亚洲高清| 亚洲free嫩bbb| 牛牛精品在线视频| 亚洲精品小视频在线观看| 天干夜夜爽爽日日日日| 国产精品你懂的在线欣赏| 亚洲免费成人在线视频| 亚洲网站视频| 免费精品视频一区| 四虎视频在线精品免费网址| 九九久久综合网站| 亚洲av激情无码专区在线播放| 色88888久久久久久影院按摩| 微拍福利一区二区| 国产一区欧美二区| 国产极品尤物在线| 成人直播大秀| 国产精品国色综合久久| 亚洲女色av| 久久精品欧美视频| 日本成人动漫在线观看| 欧美中文字幕亚洲一区二区va在线 | 天天影视色综合| 国产综合自拍| 色噜噜一区二区| 一区二区三区四区视频免费观看| 2019中文在线观看| 男人影院在线观看| 日韩成人在线观看| 国产女人18毛片18精品| 欧美日韩国产综合新一区 | 亚洲国产欧美在线人成| 色哟哟精品观看| 国产在线观看一区二区| 日本毛片在线免费观看| 一区二区三区在线观看免费| 久久偷窥视频| 午夜日韩影院| 国产精品福利网站| aa视频在线观看| 久久久999国产精品| 男女污污视频在线观看| 日韩一二三四区| 中文字幕人妻一区二区三区视频| 亚洲午夜精品网| 中文字幕乱码av| 久久九九影视网| 免费看毛片的网站| 国产一区二区导航在线播放| 欧美日韩亚洲第一| 激情综合网址| 国产精品igao激情视频| 久久精品播放| 茄子视频成人在线观看 | 国内不卡的二区三区中文字幕 | 日韩精品在线视频| 亚洲经典一区二区| 欧美高清视频www夜色资源网| 91精品国产综合久久久蜜臀九色| 一区二区在线电影| 欧美色视频一区二区三区在线观看| www久久久久| 美女黄色一级视频| 国产麻豆成人传媒免费观看| 天天操,天天操| 日韩av二区在线播放| 国产免费毛卡片| 亚洲高清二区| 91精品国产91久久久久麻豆 主演| 香蕉视频官网在线观看日本一区二区| 日韩av一区二区三区美女毛片| 日韩电影不卡一区| 国产日韩欧美综合精品| xvideos.蜜桃一区二区| 亚洲一区制服诱惑| 伊人久久噜噜噜躁狠狠躁| 亚洲精品日韩激情在线电影| 亚洲一区av| 91在线色戒在线| 免费欧美网站| 成人蜜桃视频| 97se亚洲国产一区二区三区| 99久热re在线精品996热视频| 国产一区二区三区免费在线| 亚洲xxxxx| 日本一区二区三区视频在线看 | 欧美一级片免费| 欧美精品一区二区高清在线观看| 囯产精品一品二区三区| 亚洲成人精品视频在线观看| 蜜臀av午夜精品| 日韩h在线观看| 少妇性bbb搡bbb爽爽爽欧美| 亚洲欧美精品在线| 国产小视频在线| 日韩在线视频观看| 成人国产免费电影| 国内精品久久久久久久久| 黄色在线网站噜噜噜| 热久久99这里有精品| 久久久人成影片一区二区三区在哪下载 | 日韩精品在线不卡| 狠狠躁天天躁日日躁欧美| 欧美一区二区三区四| 欧洲激情一区二区| 国产精品无码在线播放| 精品少妇一区二区三区视频免付费| 成人无码一区二区三区| 亚洲女人被黑人巨大进入| 777电影在线观看| 久久在线精品视频| 美女网站在线看| 国产精品久久久久久搜索| 国产一区二区三区精品在线观看 | 欧美呦呦网站| 99精品一区二区三区的区别| 欧美日韩亚洲一区三区 | 韩国av一区二区| 永久免费看片在线观看| 91麻豆国产精品久久| 日韩av片在线免费观看| 亚洲va欧美va人人爽午夜| 日本视频网站在线观看| 91精品国产91久久久久久最新毛片| 国产小视频免费观看| 亚洲视频在线观看网站| 在线看三级电影| 日本亚洲欧洲色α| 麻豆国产一区| 色播亚洲婷婷| 欧美视频成人| 国产色视频在线播放| 99精品在线免费| 日韩欧美123区| 日韩欧美黄色动漫| 99久久久国产精品无码网爆| 亚洲精品99久久久久| 日本高清中文字幕在线| 911国产网站尤物在线观看| 亚洲青青久久| 欧美 日韩 国产在线| 欧美在线网站| 91蝌蚪视频在线观看| 成人动漫av在线| 久久嫩草捆绑紧缚| 欧美日韩在线视频观看| av小说天堂网| 中文字幕精品一区久久久久| 不卡视频观看| 91在线免费看片| 欧美成人激情| 韩国日本美国免费毛片| 99国产精品久| 欧美又粗又大又长| 欧美日韩美女一区二区| 免费av在线电影| 992tv在线成人免费观看| 国产精品一区二区三区四区在线观看| 欧美日韩一区二区三区在线视频 | 欧美午夜性色大片在线观看| 国产福利免费视频| 国产亚洲一区二区在线| 午夜裸体女人视频网站在线观看| 91久久爱成人| 99久久精品国产亚洲精品 | 青青草成人av| 精品乱码亚洲一区二区不卡| 最新国产在线拍揄自揄视频| 国产在线视频2019最新视频| av一区二区高清| 日日摸日日碰夜夜爽av| 99久久综合狠狠综合久久| 动漫精品一区一码二码三码四码| 日韩欧美一区电影| 亚洲夜夜综合| 97自拍视频| 影音先锋中文字幕一区| 国产乱国产乱老熟300部视频| 玉米视频成人免费看| av官网在线观看| 欧美高清第一页| 成人爽a毛片| 日韩精品 欧美| 99re这里都是精品| 国产区一区二区三| 亚洲社区在线观看| 99蜜月精品久久91| 在线观看成人一级片| 精品亚洲porn| 一区二区视频免费看| 日韩精品最新网址| 欧美6一10sex性hd| 久久久福利视频| 美女国产一区| 91香蕉国产视频| 日韩欧美一区二区三区在线| 182在线播放| 日本成人三级| 另类中文字幕网| 亚洲色婷婷一区二区三区| 精品99一区二区三区| 日本在线高清| 先锋影音一区二区三区| 国产一区二区伦理| 日韩黄色a级片| 国产亚洲欧美aaaa| 国色天香久久精品国产一区| 青青青青在线视频| 久久久久久久av麻豆果冻| 欧美一级黄视频| 九九视频直播综合网| 校花撩起jk露出白色内裤国产精品| 国产精品欧美激情在线观看| 中文字幕乱码日本亚洲一区二区| 国产精品女同一区二区| 久久久久日韩精品久久久男男| 亚洲va久久| www.亚洲自拍| 精品久久久久久中文字幕一区奶水 | 日韩中文在线视频| 99re8这里有精品热视频免费| 116极品美女午夜一级| 国产精品国产三级国产专播品爱网| 国产成人毛毛毛片| 国产精品扒开腿做爽爽爽男男| 亚洲国产精品成人| 久久久无码人妻精品一区| 欧美精品丝袜久久久中文字幕| 丁香花在线电影| 亚洲欧美精品在线观看| 成人免费的视频| 一级片一区二区三区| 97久久久免费福利网址| 国产精品国产一区| 法国空姐电影在线观看| 欧美videos大乳护士334| 欧美男男gaygay1069| 啊啊啊一区二区|