精品欧美一区二区三区在线观看 _久久久久国色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)

美女视频免费精品| 日韩欧美亚洲日产国产| 黄色片网址在线观看| 精品人妻无码一区二区三区| 在线看免费av| 亚洲福利网站| 亚洲摸摸操操av| 国产精品免费小视频| 国产老熟女伦老熟妇露脸| 国产区在线观看| 麻豆一区二区99久久久久| 国产视频久久久久| 成人在线国产视频| 国产黄a三级三级看三级| 日韩欧美一区免费| 在线区一区二视频| 欧美午夜精品久久久久久蜜| 青青操免费在线视频| 亚洲乱码一区| 亚洲蜜臀av乱码久久精品蜜桃| 国产一区二区三区黄| 久久精品国产亚洲av高清色欲| 日韩成人18| 一卡二卡三卡日韩欧美| av免费观看久久| 久草免费新视频| 亚洲一区二区三区在线免费| 色综合天天狠狠| 欧美日韩国产不卡在线看| 国产情侣在线播放| 欧美成人一品| 欧美mv日韩mv| 成人性生活视频免费看| 天天干天天做天天操| 国产欧美日韩一级| 亚洲欧美一区二区三区在线| 亚洲精品怡红院| www免费网站在线观看| 美女mm1313爽爽久久久蜜臀| 91av成人在线| 阿v天堂2014| 欧美一区二区三区婷婷| 亚洲女子a中天字幕| 日本中文不卡| 日韩大胆视频| 蜜桃av一区二区三区电影| 久久精品国产久精国产一老狼| 精品亚洲视频在线| 牛牛在线精品视频| 99久久久国产精品| 国产精品丝袜高跟| 青青草原免费观看| 中文视频一区| 亚洲国内高清视频| 无码日韩人妻精品久久蜜桃| av毛片在线播放| av成人免费在线| 不卡一区二区三区四区五区| 99久久精品国产一区色| 国产一区视频导航| 欧美中文在线观看| 91麻豆精品成人一区二区| av成人资源网| 在线亚洲欧美专区二区| 蜜臀久久99精品久久久酒店新书 | 男人av资源站| 国产成人一二片| 在线视频国内自拍亚洲视频| www日韩在线观看| 97成人超碰| 亚洲成人黄色影院| 亚洲国产激情一区二区三区| 成人午夜福利视频| 激情综合网av| 日本高清视频精品| 波多野结衣一本一道| 国产精品豆花视频| 视频直播国产精品| 亚洲久久久久久| 国产成人精品一区二区免费看京 | 国产97在线视频| 久久国产波多野结衣| 午夜国产精品视频免费体验区| 久久99精品视频一区97| 精品无码在线观看| 希岛爱理一区二区三区| 亚洲免费福利视频| 特级西西人体高清大胆| 嫩草国产精品入口| 日韩欧美另类在线| 粉色视频免费看| 女生影院久久| 狠狠躁天天躁日日躁欧美| 欧美黄色免费网址| 成人影院在线看| 国产精品视频yy9299一区| 久久久久久亚洲精品不卡4k岛国| www.97超碰| 国产真实精品久久二三区| 国产精品露出视频| 国产99999| 99re6这里只有精品视频在线观看| 91精品天堂| 国产视频一区二区三| 99久久综合99久久综合网站| 亚洲精品不卡| 在线能看的av网址| 日韩欧美大尺度| 国产 福利 在线| 成年男女免费视频网站不卡| 亚洲图片欧美一区| 你真棒插曲来救救我在线观看| 欧洲精品一区二区三区| 在线观看www91| 丰满少妇xbxb毛片日本| 黄色免费大全亚洲| 久久韩剧网电视剧| 亚洲图片在线视频| 日韩有码一区二区三区| 国产精品都在这里| 中文字幕乱码视频| 久久se这里有精品| 亚洲一区二区三区成人在线视频精品| 国产毛片一区二区三区va在线 | 国产99视频精品免费视频36| 国产jzjzjz丝袜老师水多| 久久久久成人黄色影片| 日韩欧美精品一区二区| 2020av在线| 欧美午夜精品久久久久久人妖| 欧美国产在线一区| 亚洲网一区二区三区| 日韩在线国产精品| 波多野结衣一本一道| 91在线观看一区二区| 国产 欧美 日韩 一区| 草草视频在线| 亚洲精品在线网站| 男女做爰猛烈刺激| 日韩午夜电影网| 国产精品久久久久久av福利软件| 婷婷在线免费视频| caoporm超碰国产精品| 日韩中文在线字幕| 日韩激情电影免费看| 欧美亚一区二区| 91丨porny丨九色| av大片在线免费观看| 国模套图日韩精品一区二区| 日本久久精品电影| 久国产精品视频| 91欧美日韩| 欧美激情视频一区二区三区不卡| 免费观看成人毛片| 久久99精品一区二区三区三区| 欧美日韩一区二区三| 免费高潮视频95在线观看网站| 精品粉嫩超白一线天av| 精品亚洲永久免费| 久久精品中文| 91在线精品观看| 最新国产露脸在线观看| 日韩欧美在线一区二区三区| 真人bbbbbbbbb毛片| 国产精品久久久久久麻豆一区软件| 欧美激情一二区| 瑟瑟视频在线免费观看| 成人一区二区三区视频在线观看| 日韩av在线电影观看| 日韩三区免费| 精品激情国产视频| 精品国自产在线观看| 亚洲一级二级在线| 亚洲一区二区三区无码久久| 可以看av的网站久久看| 国产高清在线一区二区| а√在线中文网新版地址在线| 亚洲国内精品视频| 亚洲中文无码av在线| 亚洲素人一区二区| 玩弄japan白嫩少妇hd| 日韩一区三区| 91在线短视频| 全亚洲第一av番号网站| 日韩在线观看精品| 亚洲 欧美 日韩 在线| 成人性视频网站| 能在线观看的av| 91久久偷偷做嫩草影院电| 97精品国产aⅴ7777| 国产农村妇女毛片精品| 亚洲韩国一区二区三区| 国产精品天天干| 国产精品一区二区男女羞羞无遮挡| 欧美综合激情| 中文字幕资源网在线观看免费 | 亚洲 欧美 激情 另类| 在线亚洲一区观看| 久久久久久国产精品免费播放| 久久色在线视频| 久久99久久99精品| 国产午夜一区| 99久久久久国产精品免费| 欧美日韩在线精品一区二区三区激情综合| 亚洲国产精品嫩草影院久久| 中文字幕福利视频| 亚洲成人av中文| 制服丨自拍丨欧美丨动漫丨| 日本成人中文字幕在线视频| 欧美日韩一区二区三区在线观看免 | 狠狠躁夜夜躁av无码中文幕| 欧美色图第一页| 国产探花视频在线播放| 视频一区国产视频| 日本一级黄视频| 四虎8848精品成人免费网站| 久久久久久久久久久久久久一区| 日韩精品中文字幕一区二区| 国产精品久久久久高潮| 丝袜诱惑一区二区| 欧美国产一区二区三区| 色哟哟免费在线观看| 在线成人高清不卡| 性色av无码久久一区二区三区| 精品在线播放午夜| 激情网站五月天| 99热免费精品| 日本不卡在线播放| 豆花视频一区二区| 91偷拍精品一区二区三区| 福利视频亚洲| 国产精品678| 久久精品视频免费看| 国产丝袜高跟一区| 无码国产精品96久久久久| 日韩美女主播在线视频一区二区三区 | 日本福利一区二区| 中文字幕亚洲精品在线| 亚洲国产视频直播| 精品午夜福利视频| 樱花草国产18久久久久| 稀缺小u女呦精品呦| 国产精品亚洲综合久久| 久青草视频在线播放| 欧美在线看片| 国产大尺度在线观看| 国产精品xxx在线观看| av日韩免费电影| 亚洲一区二区三区免费| 99精品欧美一区二区三区| 欧美经典一区| 国产97免费视| yw.尤物在线精品视频| 青草青草久热精品视频在线网站 | 一区二区三区在线观看免费视频| 国产网站一区二区| 红桃视频一区二区三区免费| 精品影院一区二区久久久| 国内自拍第二页| 国产精品综合二区| 亚洲图片欧美另类| 91蜜桃在线免费视频| 国内精品国产三级国产aⅴ久| 精品在线一区二区| 欧美日韩久久婷婷| 久久久xxx| 国产区二区三区| 日韩午夜免费| 浮妇高潮喷白浆视频| 久久精品观看| 五月天视频在线观看| 国产一区二区福利| japanese在线观看| 国产在线播放一区二区三区| 91精品国产三级| 成人午夜免费电影| 短视频在线观看| 成人黄色在线网站| 日韩视频在线观看一区二区三区| 国产精品88888| 国模私拍视频在线观看| 国产精品白丝av| 毛茸茸多毛bbb毛多视频| 日本一区二区视频在线| 中文字幕天堂av| 久久久亚洲欧洲日产国码αv| 青青青视频在线播放| 亚洲激情一二三区| www亚洲视频| 欧美日韩成人在线| 欧美三级网站在线观看| 这里只有精品电影| 亚洲图片小说视频| 在线视频国内自拍亚洲视频| av一区二区三| 亚洲人成网站999久久久综合| 四虎免费在线观看| 伊人精品在线观看| av电影在线播放高清免费观看| 久久久国产91| 日韩电影免费观| 99国产高清| 久久美女精品| 无码精品a∨在线观看中文| 狠狠色综合播放一区二区| 国产性生活毛片| 一区二区三区美女视频| 中文字幕丰满人伦在线| 亚洲国产欧美一区二区丝袜黑人 | 亚洲一卡二卡三卡四卡五卡| 亚洲精品91天天久久人人| 亚洲精品国产福利| 黄色免费网站在线观看| 国产suv精品一区二区三区88区| 日本一区二区三区电影免费观看| 色狠狠久久av五月综合|| 精品国产美女| 五月婷婷综合色| 亚洲在线成人| 九热视频在线观看| 91视频国产观看| 日本少妇激情视频| 欧美日韩国产中文字幕| www.蜜臀av| www.午夜精品| 欧美暴力调教| 蜜桃成人免费视频| 青青草91久久久久久久久| 一区二区三区不卡在线| 一区二区中文| 亚洲一级免费在线观看| 国产精品一二三在| 后入内射无码人妻一区| 色哟哟精品一区| 四虎影院在线域名免费观看| 色偷偷偷综合中文字幕;dd| 亚洲精品永久免费视频| 国内精品视频在线播放| 亚洲图片在线| 亚洲最大视频网| 国产视频亚洲色图| 狠狠人妻久久久久久| 亚洲免费视频在线观看| 中国色在线日|韩| 久久综合一区二区三区| 国产一区成人| 亚洲精品乱码久久久久久久| 调教+趴+乳夹+国产+精品| 在线观看免费中文字幕| 国产一区二区日韩| 性爱视频在线播放| 日本不卡免费高清视频| 岳的好大精品一区二区三区| 国产日韩一区二区在线观看| 久久99久久久欧美国产| 亚洲国产精品一区二区久久hs| 欧美午夜精品理论片a级按摩| 二区三区在线| 久久久亚洲成人| 九九热这里有精品| 国产精品免费观看高清| 亚洲国产精品第一区二区| 亚洲综合婷婷久久| 国产精品理伦片| 99热这里只有精品在线观看| 九九久久国产精品| 国产精品一区二区中文字幕| 久久成人免费观看| 国产日韩亚洲欧美综合| 一级黄色大毛片| 欧美成人免费小视频| 国精产品一区一区三区四川| 午夜久久资源| 国产精品中文欧美| 日韩人妻无码一区二区三区99| 亚洲欧美成人网| 97成人超碰| 精品人妻人人做人人爽| 26uuu精品一区二区| 中文字幕久久网| 欧美多人爱爱视频网站| 一区二区三区韩国免费中文网站| 538任你躁在线精品免费| 亚洲激情av在线| 丝袜+亚洲+另类+欧美+变态| 国产免费一区视频观看免费| 国产精品a级| 久久精品国产99久久99久久久| 亚洲国产一区二区a毛片| 国产小视频在线播放| 97香蕉久久超级碰碰高清版| 欧美精品一二| 国产av一区二区三区传媒| 色婷婷国产精品综合在线观看| 麻豆电影在线播放| 成人国产精品久久久久久亚洲| 精品一区不卡| 免费看三级黄色片| 91久久精品网| 欧美6一10sex性hd|