当前位置:网站首页>Detailed explanation of miracast Technology (I): Wi Fi display

Detailed explanation of miracast Technology (I): Wi Fi display

2022-07-05 07:23:00 Enlarged EZ

Miracast summary

Miracast

Miracast By Wi-Fi Alliance in 2012 Formulated in , With Wi-Fi Direct connection (Wi-Fi Direct) Wireless display standards based on . Consumer electronics products that support this standard ( also called 3C equipment ) You can share video images wirelessly , For example, mobile phones can be accessed through Miracast Play movies or photos directly on TV or other devices without any cables , You don't have to go through a wireless hotspot (AP,Access Point).

Wi-Fi Direct

Wi-Fi Direct connection ( English :Wi-Fi Direct), Previously known as Wi-Fi Point to point (Wi-Fi Peer-to-Peer), It is a set of wireless network interconnection protocols , Give Way wifi Devices do not have to go through wireless network access points (Access Point), In a point-to-point way , Directly with another wifi Device connection , High speed data transmission . This agreement is made by Wi-Fi Alliance Development 、 Support and grant Authentication , Certified products will be available Wi-Fi CERTIFIED Wi-Fi Direct sign .

Wi-Fi Display

Wi-Fi Display yes Wi-Fi A standard agreement made by the alliance , It is a combination of Wi-Fi Standards and H.264 Video coding technology . Using this technology , Consumers can mirror audio and video content from a mobile device to a large screen in real time , At any time 、 Anywhere 、 Reliably transmit and view content between various devices .

Miracast It's actually Wi-Fi The alliance supports WiFi Display The certified name of the functional device , After the product passes the certification, it will be marked Miracast label .

Sink & Source

As shown in the figure below ,Miracast It can be divided into sender and receiver .Source intention Miracast Audio and video data sending end , Responsible for the collection of audio and video data 、 Encoding and sending . and Sink intention Miracast The receiving end of the service , Responsible for receiving Source End of the audio and video code stream and decode display , Among them through Wi-Fi Direct Technology to connect .

/**
 * A class representing Wifi Display information for a device
 * @hide
 */
public class WifiP2pWfdInfo implements Parcelable {
	...
    public WifiP2pWfdInfo() {
    }

    public WifiP2pWfdInfo(int devInfo, int ctrlPort, int maxTput) {
        mWfdEnabled = true;
        mDeviceInfo = devInfo;
        mCtrlPort = ctrlPort;
        mMaxThroughput = maxTput;
    }
    ...
}

about setWFDInfo() Method , We can use reflection to call :

private void setWFDInfoInner(WifiP2pWfdInfo wfdInfo) {
    try {
        Method method = ReflectUtil.getPrivateMethod(mManager.getClass(), "setWFDInfo",
                WifiP2pManager.Channel.class,
                WifiP2pWfdInfo.class,
                WifiP2pManager.ActionListener.class);
        method.invoke(mManager, mChannel, wfdInfo, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
                Log.d(TAG, "setWFDInfo onSuccess:");
            }

            @Override
            public void onFailure(int reason) {
                Log.e(TAG, "setWFDInfo onFailure:" + reason);
            }
        });
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

initialization WifiP2pWfdInfo, And make the following settings , See notes for several important fields :

public void setWfdInfo() {
    final WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo();
    //  Turn on WiFi Display
    wfdInfo.setWfdEnabled(true);
    wfdInfo.setSessionAvailable(true);
    wfdInfo.setCoupledSinkSupportAtSink(false);
    wfdInfo.setCoupledSinkSupportAtSource(false);
    //  Set the device mode to SINK End (Miracast The receiver )
    wfdInfo.setDeviceType(WifiP2pWfdInfo.PRIMARY_SINK);
    wfdInfo.setControlPort(WFD_DEFAULT_PORT);
    wfdInfo.setMaxThroughput(WFD_MAX_THROUGHPUT);
    setWFDInfoInner(wfdInfo);
}

If you want to close WiFi Display Pattern , directly setWfdEnabled(false) that will do :

public void clearWfdInfo() {
    final WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo();
    wfdInfo.setWfdEnabled(false);
    setWFDInfoInner(wfdInfo);
}

After completing the above steps , In the projection or projection function of the sending end , You should be able to search the corresponding Miracast Equipment .

Wi-Fi P2P Connect

Search for Miracast equipment , And click the corresponding device , You enter the connection process . here Sink The end should pop up a [ Connection invitation ] Authorization window for , You can choose to refuse or accept . Choose to accept , If it is the first connection , You will enter GO The process of negotiation .

GO negotiation (Group Owner Negotiation)

GO Negotiation is a complex process , There are three types of Action frame :GO Req、GO Resp、GO Confirm, After the interaction of these frames, the final confirmation is Sink End or end Source End as Group Owner, So who does GO It's uncertain . What are the specific negotiation rules ? The official flow chart clearly gives the answer :

  First, through Group Owner Intent Value of , The higher value is GO. if Intent The same value requires judgment Req In the frame Tie breaker position , Set up 1 Who is GO. if 2 All devices are set Intent Is the maximum , All hope to become GO, Then this negotiation failed .

that , How to set this Intent Is it worth it ? The sender is at connect() When , It can be done by groupOwnerIntent Field settings GO Priority of ( Range from 0-15,0 Indicates the minimum priority ), The method is as follows :

WifiP2pConfig config = new WifiP2pConfig();
...
config.groupOwnerIntent = 15; // I want this device to become the owner
mManager.connect(mChannel, config, actionListener);

PS: Yes GO Children's shoes interested in the whole negotiation process can be viewed Wi-Fi P2P Technical Specification Document 3.1.4.2 Group Owner Negotiation This chapter

Miracast Sink The end scenario is the receiving end , So it can't pass groupOwnerIntent Field to set GO priority . Then there are other ways to make Sink The end becomes GO Do you ? After all, many devices pass Miracast When casting the screen ,Sink The end must be as GO In order to achieve . The answer is simple , Create a group by yourself , Become yourself GO, Let others Client Add in , Call directly before connecting createGroup() Method to complete the group creation operation :

mManager.createGroup(mChannel, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        Log.d(TAG, "createGroup onSuccess");
    }

    @Override
    public void onFailure(int reason) {
        Log.d(TAG, "createGroup onFailure:" + reason);
    }
});

After the group is established successfully, we can pass requestGroupInfo() Method to view the basic information of the Group , And within the Group Client The situation of :

mManager.requestGroupInfo(mChannel, wifiP2pGroup -> {
    Log.d(TAG, "onGroupInfoAvailable detail:\n" + wifiP2pGroup.toString());
    Collection<WifiP2pDevice> clientList = wifiP2pGroup.getClientList();
    if (clientList != null) {
        int size = clientList.size();
        Log.d(TAG, "onGroupInfoAvailable - client count:" + size);
        // Handle all p2p client devices
    }
});

GO The negotiation is over , also Wi-Fi Direct When the connection is successful , We will receive WIFI_P2P_CONNECTION_CHANGED_ACTION This broadcast , At this point, we can call  requestConnectionInfo(), And in onConnectionInfoAvailable() Through the callback isGroupOwner Field to determine whether the current device is Group Owner, still Peer. adopt groupOwnerAddress, We can easily get Group Owner Of IP Address .

@Override
public void onConnectionInfoAvailable(WifiP2pInfo wifiP2pInfo) {
    if (wifiP2pInfo.groupFormed && wifiP2pInfo.isGroupOwner) {
        Log.d(TAG, "is groupOwner: ");
    } else if (wifiP2pInfo.groupFormed) {
        Log.d(TAG, "is peer: ");
    }
    String ownerIP = wifiP2pInfo.groupOwnerAddress.getHostAddress();
    Log.d(TAG, "onConnectionInfoAvailable ownerIP = " + ownerIP);
}

suffer WiFi P2P API The limitation of , Obtained by each device MAC and IP The address is shown in the figure below :

Because in the follow-up RTSP When conducting command communication , Need to pass through Socket And Source End establish connection , That is, we need to know first Source Terminal IP Address and port . According to the picture above , We may have the following 2 In this case :

  • situation 1:Sink intention Peer,Source intention GO.

In this case ,Sink End know Source End (GO) Of IP Address , It can be done directly Socket Connect .

  • situation 2:Sink intention GO,Source intention Peer.

In this case ,Sink You only know yourself (GO) Of IP Address , I do not know! Source End (Peer) Of IP Address , But you can get MAC Address .

adopt ARP Get the corresponding agreement MAC The equipment IP Address

In view of the above situation 2, We need to pass MAC Get the address of the corresponding host IP Address , To complete with Source Terminal Socket Connect , The classic solution is to use parsing ARP In the form of cache table .

ARP(Address Resolution Protocol), Address resolution protocol , It's based on IP Address gets a physical address TCP/IP agreement . When the host sends the information, it will include the target IP Address of the ARP Request broadcast to all hosts on the LAN , And receive the return message , To determine the physical address of the target ; After receiving the return message, it will be IP The address and physical address are stored in the machine ARP Cache and keep it for a certain time , The next time you ask for it, look it up directly ARP Cache to save resources .

stay Android On , We can get ARP Cache table :

Method 1: adopt busybox arp Instructions

dior:/ $ busybox arp
? (192.168.0.108) at f8:ff:c2:10:e7:62 [ether]  on wlan0
? (192.168.0.1) at 9c:a6:15:d6:e8:f4 [ether]  on wlan0

Method 2: adopt cat proc/net/arp command

dior:/ $ cat proc/net/arp
IP address HW type Flags HW address Mask Device
192.168.0.108 0x1 0x2 f8:ff:c2:10:e7:62 * wlan0
192.168.0.1 0x1 0x2 9c:a6:15:d6:e8:f4 * wlan0
 

The rest of the work is to use powerful regular expressions to parse the returned string , And find out the corresponding MAC The equipment IP Address .

obtain Source End RTSP Port number

Go through the above steps , We've got it Source Terminal IP Address , Only the port number is left . This step is simpler , adopt requestPeers() Method to get the connected peer device WifiP2pDevice, And get the WifiP2pWfdInfo You can get the port number :

mManager.requestPeers(mChannel, peers -> {
    Collection<WifiP2pDevice> devices = peers.getDeviceList();
    for (WifiP2pDevice device : devices) {
        boolean isConnected = (WifiP2pDevice.CONNECTED == device.status);
        if (isConnected) {
            int port = getDevicePort(device);
            break;
        }
    }
});

Here because WifiP2pDevice Medium wfdInfo Field is @hide, Therefore, we need to obtain by reflection WifiP2pWfdInfo. Finally through getControlPort() The way to get Source End RTSP Port number :

public int getDevicePort(WifiP2pDevice device) {
    int port = WFD_DEFAULT_PORT;
    try {
        Field field = ReflectUtil.getPrivateField(device.getClass(), "wfdInfo");
        if (field == null) {
            return port;
        }
        WifiP2pWfdInfo wfdInfo = (WifiP2pWfdInfo) field.get(device);
        if (wfdInfo != null) {
            port = wfdInfo.getControlPort();
            if (port == 0) {
                Log.w(TAG,"set port to WFD_DEFAULT_PORT");
                port = WFD_DEFAULT_PORT;
            }
        }
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return port;
}

Got it Source Terminal IP After the address and port number , We can build RTSP Connect , Establish the channel for subsequent control instructions , See the next blog .

Reference resources

Reprint of the article :

Miracast Technical details ( One ):Wi-Fi Display

原网站

版权声明
本文为[Enlarged EZ]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/186/202207050721265906.html