# Stream media to a channel (/en/realtime-media/broadcast-streaming/build/manage-video-and-streaming/play-media/windows)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Playing media files during online business presentations, educational sessions, or casual meetups heightens user engagement. Video SDK enables you to add media playing functionality to your app.

    This page shows you how to use media player-related APIs to play local or online media resources with remote users in Broadcast Streaming channels.

    ## Understand the tech [#understand-the-tech-3]

    To play a media file in a channel, you open the file using a media player instance. When the file is ready to be played, you set up the local video container to display the media player output. You update channel media options to start publishing the media player stream, and stop publishing the camera and microphone streams. The remote user sees the camera and microphone streams of the media publishing user replaced by media streams.

    **Media player flow**

    ![Media player](https://assets-docs.agora.io/images/video-sdk/play-media.svg)

    ## Prerequisites [#prerequisites-3]

    Ensure that you have implemented the [SDK quickstart](../../index) in your project.

    ## Implement the logic [#implement-the-logic-3]

    To implement a media player in your app, follow these steps:

    1. After initializing an instance of `IRtcEngine`, create an `IMediaPlayer` object.

       ```cpp
       void CAgoraMediaPlayer::InitMediaPlayerKit() {
         // Create Agora media player
         m_mediaPlayer = m_rtcEngine->createMediaPlayer().get();
         m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("createAgoraMediaPlayer"));
         m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("Media player initialization"));

         // Set the player rendering view
         RECT rc = {0};
         m_localVideoWnd.GetWindowRect(&rc);
         int ret = m_mediaPlayer->setView(
           (agora::media::base::view_t)m_localVideoWnd.GetSafeHwnd());

         // Set the window to receive player events
         m_mediaPlayerEvent.SetMsgReceiver(m_hWnd);
       }
       ```

    2. To register the playback observer, call `registerPlayerSourceObserverthe` before you join the channel. To unregister the playback observer, call `unregisterPlayerSourceObserver` before you leave the channel.

       ```cpp
       void CAgoraMediaPlayer::OnBnClickedButtonJoinchannel() {
         // ...
         // Register the player observer
         ret = m_mediaPlayer->registerPlayerSourceObserver(&m_mediaPlayerEvent);
         m_lstInfo.InsertString(m_lstInfo.GetCount(),
                   _T("registerPlayerSourceObserver"));

         if (0 ==
           m_rtcEngine->joinChannel(APP_TOKEN, szChannelId.c_str(), 0, options)) {
           strInfo.Format(_T("Join channel %s, use ChannelMediaOptions"),
                 getCurrentTime());
         }
         else {
           // Unregister the player observer
           ret = m_mediaPlayer->unregisterPlayerSourceObserver(&m_mediaPlayerEvent);
           m_lstInfo.InsertString(m_lstInfo.GetCount(),
                     _T("unregisterPlayerSourceObserver"));

           // Leave the channel in the engine.
           if (0 == m_rtcEngine->leaveChannel()) {
             strInfo.Format(_T("Leave channel %s"), getCurrentTime());
           }
         }

         m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo);
       }
       ```

    3. Implement callbacks for the observer.

       ```cpp
       // Observe player state changes
       LRESULT CAgoraMediaPlayer::OnmediaPlayerStateChanged(WPARAM wParam,
                                  LPARAM lParam) {
         CString strState;
         CString strError;
         switch ((agora::media::base::MEDIA_PLAYER_STATE)wParam) {
           case agora::media::base::PLAYER_STATE_OPEN_COMPLETED:
             strState = _T("PLAYER_STATE_OPEN_COMPLETED");
             m_mediaPlayerState = mediaPLAYER_OPEN;
             int64_t duration;
             m_mediaPlayer->getDuration(duration);
             m_sldVideo.SetRangeMax((int)duration);

             break;
           // Additional cases for other player states...
         }

         switch ((agora::media::base::MEDIA_PLAYER_ERROR)lParam) {
           case agora::media::base::PLAYER_ERROR_URL_NOT_FOUND:
             strError = _T("PLAYER_ERROR_URL_NOT_FOUND");
             // Additional cases for other player errors...
             break;
         }
         CString strInfo;
         strInfo.Format(_T("State:%s,\nError:%s"), strState, strError);
         m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo);
         return TRUE;
       }

       // Observe current playback progress
       LRESULT CAgoraMediaPlayer::OnmediaPlayerPositionChanged(WPARAM wParam,
                                   LPARAM lParam) {
         int64_t *p = (int64_t *)wParam;
         m_sldVideo.SetPos((int)*p);
         delete p;
         return TRUE;
       }
       ```

    4. When joining a channel use `ChannelMediaOptions` to set the media player ID, publish media player's audio and video, and share media resources with remote users in the channel.

       ```cpp
       void CAgoraMediaPlayer::OnBnClickedButtonPublishVideo() {
         if (m_publishMeidaplayer) {
           ChannelMediaOptions op;
           op.clientRoleType = CLIENT_ROLE_BROADCASTER;
           op.publishMediaPlayerVideoTrack = false;
           op.publishMediaPlayerAudioTrack = false;
           op.publishMediaPlayerId = m_mediaPlayer->getMediaPlayerId();
           int ret = m_rtcEngine->updateChannelMediaOptions(op);
           ChannelMediaOptions op2;
           op2.clientRoleType = CLIENT_ROLE_BROADCASTER;
           op2.publishCameraTrack = true;
           ret = m_rtcEngine->updateChannelMediaOptions(op2);
           m_publishMeidaplayer = false;
         } else {
           ChannelMediaOptions options;
           options.clientRoleType = CLIENT_ROLE_BROADCASTER;
           options.publishMediaPlayerVideoTrack = true;
           options.publishMediaPlayerAudioTrack = true;
           options.publishMediaPlayerId = m_mediaPlayer->getMediaPlayerId();
           options.publishCameraTrack = false;
           options.publishAudioTrack = false;
           options.autoSubscribeAudio = false;
           options.autoSubscribeVideo = false;
           m_rtcEngine->updateChannelMediaOptions(options);
           m_publishMeidaplayer = true;
         }
       }
       ```

    5. Use the `open` method to open a local or online media file.

       ```swift
       void CAgoraMediaPlayer::OnBnClickedButtonOpen() {
         CString strUrl;
         CString strInfo;
         m_edtVideoSource.GetWindowText(strUrl);
         std::string tmp = cs2utf8(strUrl);
         switch (m_mediaPlayerState) {
           case mediaPLAYER_READY:
           case mediaPLAYER_STOP:
             if (tmp.empty()) {
               AfxMessageBox(_T("you can fill video source."));
               return;
             }
             m_mediaPlayer->open(tmp.c_str(), 0);
             break;
           default:
             m_lstInfo.InsertString(m_lstInfo.GetCount(),
                       _T("can not open player."));
             break;
         }
       }
       ```

    6. Call the `play` method to play the media file.

       ```cpp
       void CAgoraMediaPlayer::OnBnClickedButtonPlay() {
         int ret;
         switch (m_mediaPlayerState) {
           case mediaPLAYER_PAUSE:
           case mediaPLAYER_OPEN:
             // Play media file
             ret = m_mediaPlayer->play();
             if (ret == 0) {
               m_mediaPlayerState = mediaPLAYER_PLAYING;
             }
             break;
           case mediaPLAYER_PLAYING:
             // Pause playback
             ret = m_mediaPlayer->pause();
             if (ret == 0) {
               m_mediaPlayerState = mediaPLAYER_PAUSE;
             }
             break;
           default:
             break;
         }
       }
       ```

    <CalloutContainer type="warning">
      <CalloutDescription>
        Call the `play` method to play the media file only after receiving the `onPlayerSourceStateChanged` callback reporting the player state as `PLAYER_STATE_OPEN_COMPLETED`.
      </CalloutDescription>
    </CalloutContainer>

    1. When a user stops playback or leaves the channel, call `stop` to stop playback, and `destroyMediaPlayer` to release resources.

       ```cpp
       void CAgoraMediaPlayer::OnBnClickedButtonStop() {
         if (m_mediaPlayerState == mediaPLAYER_OPEN ||
           m_mediaPlayerState == mediaPLAYER_PLAYING ||
           m_mediaPlayerState == mediaPLAYER_PAUSE) {
           // Stop playback
           m_mediaPlayer->stop();
           m_mediaPlayerState = mediaPLAYER_STOP;
         }
       }

       void CAgoraMediaPlayer::OnDestroy() {
         // Destroy the media player
         CDialogEx::OnDestroy();
         m_mediaPlayer->destroy();
       }
       ```

    ## Reference [#reference-3]

    This section contains content that completes the information on this page, or points you to documentation that explains other aspects to this product.

    ### Supported formats and protocols [#supported-formats-and-protocols-3]

    The media player supports the following media formats and protocols:

    #### Video encoding formats [#video-encoding-formats-3]

    * H.263, H.264, H.265, MPEG-4, MPEG-2, RMVB, Theora, VP3, VP8, AVS, WMV

    #### Audio coding formats [#audio-coding-formats-3]

    * WAV, MP2, MP3, AAC, OPUS, FLAC, Vorbis, AMR-NB, AMR-WB, WMA v1, WMA v2

    #### Container formats [#container-formats-3]

    * WAV, FLAC, OGG, MOV, ASF, FLV, MP3, MP4, MPEG-TS, Matroska (MKV), AVI, ASS, CONCAT, DTS, AVS

    #### Supported protocols [#supported-protocols-3]

    * HTTP, HTTPS, RTMP, HLS, RTP, RTSP

    ### Sample project [#sample-project-3]

    Agora provides an open source [MediaPlayer](https://github.com/AgoraIO/API-Examples/tree/main/windows/APIExample/APIExample/Advanced/MediaPlayer) sample project on GitHub. Download it or view the source code for a more detailed example.

    ### API reference [#api-reference-3]

    * [`createMediaPlayer`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_irtcengine.html#api_irtcengine_createmediaplayer)
    * [`registerPlayerObserver`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_imediaplayer.html#api_imediaplayer_registerplayersourceobserver)
    * [`onPlayerStateChanged`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_imediaplayersourceobserver.html#callback_imediaplayersourceobserver_onplayersourcestatechanged)
    * [`onPositionChanged`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_imediaplayersourceobserver.html#callback_imediaplayersourceobserver_onpositionchanged)
    * [`getMediaPlayerId`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_imediaplayer.html#api_imediaplayer_registeraudioframeobserver2__parameters)
    * [`open`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_imediaplayer.html#api_imediaplayer_open)
    * [`play`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_imediaplayer.html#api_imediaplayer_play)
    * [`pause`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_imediaplayer.html#api_imediaplayer_pause)
    * [`stop`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_imediaplayer.html#api_imediaplayer_stop)
    * [`unRegisterPlayerObserver`](https://api-ref.agora.io/en/video-sdk/cpp/4.x/API/class_imediaplayer.html#api_imediaplayer_unregisterplayersourceobserver)

    
  
      
  
      
  
      
  
